[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/util/file_copy/, src/

2024-03-15 Thread Mike Gilbert
commit: 23529ee81964665107400e87fc3d49c256e915c0
Author: Mike Gilbert  gentoo  org>
AuthorDate: Fri Mar  1 15:45:58 2024 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Fri Mar 15 20:05:34 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=23529ee8

Replace linux_reflink extension module

Python 3.8 added support for copy_file_range in the os module,
so we can just call that directly.

Also, we can use the FICLONE ioctl for fast file clones on supported
filesystems (btrfs).

Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/util/file_copy.py  | 137 ++
 lib/portage/util/file_copy/__init__.py |  36 ---
 lib/portage/util/file_copy/meson.build |   7 -
 lib/portage/util/meson.build   |   2 +-
 src/meson.build|  20 --
 src/portage_util_file_copy_reflink_linux.c | 396 -
 6 files changed, 138 insertions(+), 460 deletions(-)

diff --git a/lib/portage/util/file_copy.py b/lib/portage/util/file_copy.py
new file mode 100644
index 00..e3926d8ef6
--- /dev/null
+++ b/lib/portage/util/file_copy.py
@@ -0,0 +1,137 @@
+# Copyright 2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import errno
+import fcntl
+import logging
+import os
+import platform
+import shutil
+import sys
+
+
+logger = logging.getLogger(__name__)
+
+# Added in Python 3.12
+FICLONE = getattr(fcntl, "FICLONE", 0x40049409)
+
+# Unavailable in PyPy
+SEEK_DATA = getattr(os, "SEEK_DATA", 3)
+SEEK_HOLE = getattr(os, "SEEK_HOLE", 4)
+
+
+def _get_chunks(src):
+try:
+offset_hole = 0
+while True:
+try:
+# Find the next bit of data
+offset_data = os.lseek(src, offset_hole, SEEK_DATA)
+except OSError as e:
+# Re-raise for unexpected errno values
+if e.errno not in (errno.EINVAL, errno.ENXIO):
+raise
+
+offset_end = os.lseek(src, 0, os.SEEK_END)
+
+if e.errno == errno.ENXIO:
+# End of file
+if offset_end > offset_hole:
+# Hole at end of file
+yield (offset_end, 0)
+else:
+# SEEK_DATA failed with EINVAL, return the whole file
+yield (0, offset_end)
+
+break
+else:
+offset_hole = os.lseek(src, offset_data, SEEK_HOLE)
+yield (offset_data, offset_hole - offset_data)
+
+except OSError:
+logger.warning("_get_chunks failed unexpectedly", 
exc_info=sys.exc_info())
+raise
+
+
+def _do_copy_file_range(src, dst, offset, count):
+while count > 0:
+# count must fit in ssize_t
+c = min(count, sys.maxsize)
+written = os.copy_file_range(src, dst, c, offset, offset)
+if written == 0:
+# https://bugs.gentoo.org/828844
+raise OSError(errno.EOPNOTSUPP, os.strerror(errno.EOPNOTSUPP))
+offset += written
+count -= written
+
+
+def _do_sendfile(src, dst, offset, count):
+os.lseek(dst, offset, os.SEEK_SET)
+while count > 0:
+# count must fit in ssize_t
+c = min(count, sys.maxsize)
+written = os.sendfile(dst, src, offset, c)
+offset += written
+count -= written
+
+
+def _fastcopy(src, dst):
+with (
+open(src, "rb", buffering=0) as srcf,
+open(dst, "wb", buffering=0) as dstf,
+):
+srcfd = srcf.fileno()
+dstfd = dstf.fileno()
+
+if platform.system() == "Linux":
+try:
+fcntl.ioctl(dstfd, FICLONE, srcfd)
+return
+except OSError:
+pass
+
+try_cfr = hasattr(os, "copy_file_range")
+
+for offset, count in _get_chunks(srcfd):
+if count == 0:
+os.ftruncate(dstfd, offset)
+else:
+if try_cfr:
+try:
+_do_copy_file_range(srcfd, dstfd, offset, count)
+continue
+except OSError as e:
+try_cfr = False
+if e.errno not in (errno.EXDEV, errno.ENOSYS, 
errno.EOPNOTSUPP):
+logger.warning(
+"_do_copy_file_range failed unexpectedly",
+exc_info=sys.exc_info(),
+)
+try:
+_do_sendfile(srcfd, dstfd, offset, count)
+except OSError:
+logger.warning(
+"_do_sendfile failed unexpectedly", 
exc_info=sys.exc_info()
+)
+raise
+
+
+def copyfile(src, dst):
+"""
+Copy the contents (no metadata) of the file named src to a file
+named dst.
+
+If possible, 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2024-03-07 Thread Mike Gilbert
commit: b7e89f866a9a1d73ab72670d74e2292b05893849
Author: Mike Gilbert  gentoo  org>
AuthorDate: Wed Mar  6 04:01:27 2024 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Wed Mar  6 18:19:31 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=b7e89f86

util: set a timeout for urlopen calls

A hung urlopen call can cause emerge to produce no output when fetching
binhost data.

Bug: https://bugs.gentoo.org/926221
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/util/_urlopen.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/portage/util/_urlopen.py b/lib/portage/util/_urlopen.py
index 22f0e08df0..d451a94a89 100644
--- a/lib/portage/util/_urlopen.py
+++ b/lib/portage/util/_urlopen.py
@@ -26,10 +26,10 @@ def have_pep_476():
 return hasattr(__import__("ssl"), "_create_unverified_context")
 
 
-def urlopen(url, if_modified_since=None, headers={}, proxies=None):
+def urlopen(url, timeout=10, if_modified_since=None, headers={}, proxies=None):
 parse_result = urllib_parse.urlparse(url)
 if parse_result.scheme not in ("http", "https"):
-return _urlopen(url)
+return _urlopen(url, timeout=timeout)
 
 netloc = parse_result.netloc.rpartition("@")[-1]
 url = urllib_parse.urlunparse(
@@ -59,7 +59,7 @@ def urlopen(url, if_modified_since=None, headers={}, 
proxies=None):
 handlers.append(urllib_request.ProxyHandler(proxies))
 opener = urllib_request.build_opener(*handlers)
 
-hdl = opener.open(request)
+hdl = opener.open(request, timeout=timeout)
 if hdl.headers.get("last-modified", ""):
 try:
 add_header = hdl.headers.add_header



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_eventloop/, lib/portage/util/, lib/portage/tests/util/

2024-03-03 Thread Zac Medico
commit: 11c65496bd951c3b7778a3c1ea240e347b1f4c38
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  3 21:06:13 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  3 21:10:49 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=11c65496

socks5: Use run_coroutine_exitfuncs()

Since commit c3ebdbb42e72 the atexit_register(proxy.stop) call in
the get_socks5_proxy function can accept a coroutine function to
execute in run_coroutine_exitfuncs(), so convert the ProxyManager
stop method to a coroutine and use run_coroutine_exitfuncs().

Bug: https://bugs.gentoo.org/925240
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/tests/util/test_socks5.py |  5 ++-
 lib/portage/util/_eventloop/asyncio_event_loop.py | 12 ---
 lib/portage/util/socks5.py| 39 +++
 3 files changed, 7 insertions(+), 49 deletions(-)

diff --git a/lib/portage/tests/util/test_socks5.py 
b/lib/portage/tests/util/test_socks5.py
index 4a6d08169d..a8cd0c46c4 100644
--- a/lib/portage/tests/util/test_socks5.py
+++ b/lib/portage/tests/util/test_socks5.py
@@ -216,10 +216,9 @@ class Socks5ServerTestCase(TestCase):
 self.assertEqual(result, content)
 finally:
 try:
-# Also run_exitfuncs to test atexit hook cleanup.
-await socks5.proxy.stop()
+# Also run_coroutine_exitfuncs to test atexit hook cleanup.
 self.assertNotEqual(portage.process._exithandlers, [])
-portage.process.run_exitfuncs()
+await portage.process.run_coroutine_exitfuncs()
 self.assertEqual(portage.process._exithandlers, [])
 finally:
 portage.process._exithandlers = previous_exithandlers

diff --git a/lib/portage/util/_eventloop/asyncio_event_loop.py 
b/lib/portage/util/_eventloop/asyncio_event_loop.py
index a598b1b516..821cc7f102 100644
--- a/lib/portage/util/_eventloop/asyncio_event_loop.py
+++ b/lib/portage/util/_eventloop/asyncio_event_loop.py
@@ -15,7 +15,6 @@ except ImportError:
 PidfdChildWatcher = None
 
 import portage
-from portage.util import socks5
 
 
 class AsyncioEventLoop(_AbstractEventLoop):
@@ -75,17 +74,6 @@ class AsyncioEventLoop(_AbstractEventLoop):
 self._closing = False
 
 async def _close_main(self):
-# Even though this has an exit hook, invoke it here so that
-# we can properly wait for it and avoid messages like this:
-# [ERROR] Task was destroyed but it is pending!
-if socks5.proxy.is_running():
-# TODO: Convert socks5.proxy.stop() to a regular coroutine
-# function so that it doesn't need to be wrapped like this.
-async def stop_socks5_proxy():
-await socks5.proxy.stop()
-
-portage.process.atexit_register(stop_socks5_proxy)
-
 await portage.process.run_coroutine_exitfuncs()
 portage.process.run_exitfuncs()
 

diff --git a/lib/portage/util/socks5.py b/lib/portage/util/socks5.py
index f8fcdf9fca..c32ba77674 100644
--- a/lib/portage/util/socks5.py
+++ b/lib/portage/util/socks5.py
@@ -6,15 +6,8 @@ import asyncio
 import errno
 import os
 import socket
-from typing import Union
 
 import portage
-
-portage.proxy.lazyimport.lazyimport(
-globals(),
-"portage.util._eventloop.global_event_loop:global_event_loop",
-)
-
 import portage.data
 from portage import _python_interpreter
 from portage.data import portage_gid, portage_uid, userpriv_groups
@@ -65,41 +58,19 @@ class ProxyManager:
 **spawn_kwargs,
 )
 
-def stop(self) -> Union[None, asyncio.Future]:
+async def stop(self):
 """
-Stop the SOCKSv5 server.
-
-If there is a running asyncio event loop then asyncio.Future is
-returned which should be used to wait for the server process
-to exit.
+Stop the SOCKSv5 server. This method is a coroutine.
 """
-future = None
-try:
-loop = asyncio.get_running_loop()
-except RuntimeError:
-loop = None
 if self._proc is not None:
 self._proc.terminate()
-if loop is None:
-# In this case spawn internals would have used
-# portage's global loop when attaching a waiter to
-# self._proc, so we are obligated to use that.
-global_event_loop().run_until_complete(self._proc.wait())
-else:
-if self._proc_waiter is None:
-self._proc_waiter = asyncio.ensure_future(
-self._proc.wait(), loop=loop
-)
-future = asyncio.shield(self._proc_waiter)
-
-if loop is not None and future is None:
-future = loop.create_future()
-future.set_result(None)
+if self._proc_waiter is None:
+self._proc_waiter 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2024-03-01 Thread Mike Gilbert
commit: d8089d1af39c80e1edfb1669ae92fef7ab30e08a
Author: Mike Gilbert  gentoo  org>
AuthorDate: Fri Mar  1 15:49:26 2024 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Fri Mar  1 16:19:55 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=d8089d1a

Improve whitespace handling when parsing /proc/self/mountinfo

Only break lines on "\n" (line feed).
Only split lines on " " (space).

Bug: https://bugs.gentoo.org/925888
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/util/writeable_check.py | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/lib/portage/util/writeable_check.py 
b/lib/portage/util/writeable_check.py
index 3427315cf7..ad1d9edff0 100644
--- a/lib/portage/util/writeable_check.py
+++ b/lib/portage/util/writeable_check.py
@@ -47,6 +47,7 @@ def linux_ro_checker(dir_list):
 "/proc/self/mountinfo",
 encoding=_encodings["content"],
 errors="replace",
+newline="\n",
 ) as f:
 for line in f:
 # we're interested in dir and both attr fields which always
@@ -58,7 +59,7 @@ def linux_ro_checker(dir_list):
 # to the left of the ' - ', after the attr's, so split it there
 mount = line.split(" - ", 1)
 try:
-_dir, attr1 = mount[0].split()[4:6]
+_dir, attr1 = mount[0].split(" ")[4:6]
 except ValueError:
 # If it raises ValueError we can simply ignore the line.
 invalids.append(line)
@@ -68,10 +69,10 @@ def linux_ro_checker(dir_list):
 # for example: 16 1 0:16 / /root rw,noatime - lxfs  rw
 if len(mount) > 1:
 try:
-attr2 = mount[1].split()[2]
+attr2 = mount[1].split(" ")[2]
 except IndexError:
 try:
-attr2 = mount[1].split()[1]
+attr2 = mount[1].split(" ")[1]
 except IndexError:
 invalids.append(line)
 continue



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, src/

2024-03-01 Thread Mike Gilbert
commit: a860484b6e8c8d107255f2105796ae7f58812e9f
Author: Mike Gilbert  gentoo  org>
AuthorDate: Thu Feb 29 19:38:20 2024 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Thu Feb 29 19:38:20 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a860484b

Drop portage.util.libc extension module

This was originally added as a workaround for musl, where
ctypes.util.find_library fails.

Instead, we now try to load "libc.so" as a fallback and can just rely on
ctypes to call tolower() and toupper().

Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/util/locale.py |  9 +++
 src/meson.build|  9 ---
 src/portage_util_libc.c| 67 --
 3 files changed, 3 insertions(+), 82 deletions(-)

diff --git a/lib/portage/util/locale.py b/lib/portage/util/locale.py
index d0edeb4afe..f45d761760 100644
--- a/lib/portage/util/locale.py
+++ b/lib/portage/util/locale.py
@@ -43,12 +43,9 @@ def _check_locale(silent):
 """
 The inner locale check function.
 """
-try:
-from portage.util import libc
-except ImportError:
-(libc, _) = load_libc()
-if libc is None:
-return None
+(libc, _) = load_libc()
+if libc is None:
+return None
 
 lc = list(range(ord("a"), ord("z") + 1))
 uc = list(range(ord("A"), ord("Z") + 1))

diff --git a/src/meson.build b/src/meson.build
index cbc7aa611c..6a36724ceb 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -2,14 +2,6 @@
 # and for development. Meson does not allow you to build in-place and Python
 # cannot create a single namespace from two identically-named paths.
 
-libc_ext = py.extension_module(
-'libc',
-'portage_util_libc.c',
-dependencies : py.dependency(),
-subdir : 'portage' / 'util',
-install : true
-)
-
 whirlpool_ext = py.extension_module(
 '_whirlpool',
 'portage_util__whirlpool.c',
@@ -21,7 +13,6 @@ whirlpool_ext = py.extension_module(
 run_command(
 [
 'ln', '-srnf',
-libc_ext.full_path(),
 whirlpool_ext.full_path(),
 meson.project_source_root() / 'lib' / 'portage' / 'util/'
 ],

diff --git a/src/portage_util_libc.c b/src/portage_util_libc.c
deleted file mode 100644
index 12b2440c72..00
--- a/src/portage_util_libc.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright 2005-2020 Gentoo Authors
- * Distributed under the terms of the GNU General Public License v2
- */
-
-#include 
-#include 
-#include 
-
-static PyObject * _libc_tolower(PyObject *, PyObject *);
-static PyObject * _libc_toupper(PyObject *, PyObject *);
-
-static PyMethodDef LibcMethods[] = {
-   {
-   .ml_name = "tolower",
-   .ml_meth = _libc_tolower,
-   .ml_flags = METH_VARARGS,
-   .ml_doc = "Convert to lower case using system locale."
-
-   },
-   {
-   .ml_name = "toupper",
-   .ml_meth = _libc_toupper,
-   .ml_flags = METH_VARARGS,
-   .ml_doc = "Convert to upper case using system locale."
-   },
-   {NULL, NULL, 0, NULL}
-};
-
-static struct PyModuleDef moduledef = {
-   PyModuleDef_HEAD_INIT,
-   .m_name = "libc",
-   .m_doc = "Module for converting case using the system locale",
-   .m_size = -1,
-   .m_methods = LibcMethods,
-};
-
-PyMODINIT_FUNC
-PyInit_libc(void)
-{
-   PyObject *m;
-   m = PyModule_Create();
-   return m;
-}
-
-
-static PyObject *
-_libc_tolower(PyObject *self, PyObject *args)
-{
-   int c;
-
-   if (!PyArg_ParseTuple(args, "i", ))
-   return NULL;
-
-   return Py_BuildValue("i", tolower(c));
-}
-
-
-static PyObject *
-_libc_toupper(PyObject *self, PyObject *args)
-{
-   int c;
-
-   if (!PyArg_ParseTuple(args, "i", ))
-   return NULL;
-
-   return Py_BuildValue("i", toupper(c));
-}



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/, lib/_emerge/

2024-02-26 Thread Zac Medico
commit: 0ff7a3b28e0ec63d68d32e01145db8962d53774d
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Feb 26 05:09:21 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Feb 26 05:09:21 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=0ff7a3b2

SpawnProcess: Wait for async set_term_size

Use the SpawnProcess _unregister method to handle async
set_term_size results, avoiding possible messages like
bug 925456 triggered:

[ERROR] Task was destroyed but it is pending!

Also update _BinpkgFetcherProcess and _EbuildFetcherProcess
which inherit the _pty_ready attribute from SpawnProcess.

Fixes: f97e414ce980 ("set_term_size: Wait asynchronously if event loop is 
running")
Bug: https://bugs.gentoo.org/923750
Bug: https://bugs.gentoo.org/925456
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/BinpkgFetcher.py |  6 --
 lib/_emerge/EbuildFetcher.py |  6 --
 lib/_emerge/SpawnProcess.py  | 14 +-
 lib/portage/output.py| 13 +
 lib/portage/util/_pty.py | 23 ---
 5 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/lib/_emerge/BinpkgFetcher.py b/lib/_emerge/BinpkgFetcher.py
index a1524dc009..587e4a57a3 100644
--- a/lib/_emerge/BinpkgFetcher.py
+++ b/lib/_emerge/BinpkgFetcher.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2023 Gentoo Authors
+# Copyright 1999-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from _emerge.AsynchronousLock import AsynchronousLock
@@ -233,7 +233,9 @@ class _BinpkgFetcherProcess(SpawnProcess):
 stdout_pipe = None
 if not self.background:
 stdout_pipe = fd_pipes.get(1)
-got_pty, master_fd, slave_fd = 
_create_pty_or_pipe(copy_term_size=stdout_pipe)
+self._pty_ready, master_fd, slave_fd = _create_pty_or_pipe(
+copy_term_size=stdout_pipe
+)
 return (master_fd, slave_fd)
 
 def sync_timestamp(self):

diff --git a/lib/_emerge/EbuildFetcher.py b/lib/_emerge/EbuildFetcher.py
index 7a45d95172..81d4b1054b 100644
--- a/lib/_emerge/EbuildFetcher.py
+++ b/lib/_emerge/EbuildFetcher.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2023 Gentoo Authors
+# Copyright 1999-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import copy
@@ -394,7 +394,9 @@ class _EbuildFetcherProcess(ForkProcess):
 stdout_pipe = None
 if not self.background:
 stdout_pipe = fd_pipes.get(1)
-got_pty, master_fd, slave_fd = 
_create_pty_or_pipe(copy_term_size=stdout_pipe)
+self._pty_ready, master_fd, slave_fd = _create_pty_or_pipe(
+copy_term_size=stdout_pipe
+)
 return (master_fd, slave_fd)
 
 def _eerror(self, lines):

diff --git a/lib/_emerge/SpawnProcess.py b/lib/_emerge/SpawnProcess.py
index b63afae01c..9fc12c42e5 100644
--- a/lib/_emerge/SpawnProcess.py
+++ b/lib/_emerge/SpawnProcess.py
@@ -46,6 +46,7 @@ class SpawnProcess(SubProcess):
 + (
 "_main_task",
 "_main_task_cancel",
+"_pty_ready",
 "_selinux_type",
 )
 )
@@ -193,6 +194,9 @@ class SpawnProcess(SubProcess):
 self._main_task.add_done_callback(self._main_exit)
 
 async def _main(self, build_logger, pipe_logger, loop=None):
+if isinstance(self._pty_ready, asyncio.Future):
+await self._pty_ready
+self._pty_ready = None
 try:
 if pipe_logger.poll() is None:
 await pipe_logger.async_wait()
@@ -238,7 +242,9 @@ class SpawnProcess(SubProcess):
 stdout_pipe = None
 if not self.background:
 stdout_pipe = fd_pipes.get(1)
-got_pty, master_fd, slave_fd = 
_create_pty_or_pipe(copy_term_size=stdout_pipe)
+self._pty_ready, master_fd, slave_fd = _create_pty_or_pipe(
+copy_term_size=stdout_pipe
+)
 return (master_fd, slave_fd)
 
 def _spawn(
@@ -258,6 +264,12 @@ class SpawnProcess(SubProcess):
 SubProcess._unregister(self)
 if self._main_task is not None:
 self._main_task.done() or self._main_task.cancel()
+if isinstance(self._pty_ready, asyncio.Future):
+(
+self._pty_ready.done()
+and (self._pty_ready.cancelled() or self._pty_ready.result() 
or True)
+) or self._pty_ready.cancel()
+self._pty_ready = None
 
 def _cancel(self):
 if self._main_task is not None:

diff --git a/lib/portage/output.py b/lib/portage/output.py
index 7d3a6278f3..4408705c45 100644
--- a/lib/portage/output.py
+++ b/lib/portage/output.py
@@ -8,6 +8,7 @@ import itertools
 import re
 import subprocess
 import sys
+from typing import Optional
 
 import portage
 
@@ -554,10 +555,16 @@ def get_term_size(fd=None):
 return (0, 0)
 
 
-def set_term_size(lines, columns, fd):
+def set_term_size(lines: int, columns: int, fd: int) -> 
Optional[asyncio.Future]:

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/

2024-02-22 Thread Zac Medico
commit: d718cea94a180042b2285698b2c19113c5d25987
Author: Zac Medico  gentoo  org>
AuthorDate: Thu Feb 22 06:41:49 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Thu Feb 22 07:28:38 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=d718cea9

_get_running_loop: Support real asyncio.run

When called via the real asyncio.run implementation, wrap
the running asyncio loop. Otherwise, it's not possible to
call portage libraries via the real asyncio.run without
triggering Future "attached to a different loop" errors.

Bug: https://bugs.gentoo.org/761538
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/_asyncio/__init__.py | 28 +--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/lib/portage/util/futures/_asyncio/__init__.py 
b/lib/portage/util/futures/_asyncio/__init__.py
index 22241f335d..4eecc46a89 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -325,13 +325,37 @@ def _safe_loop():
 
 
 def _get_running_loop():
+"""
+This calls the real asyncio get_running_loop() and wraps that with
+portage's internal AsyncioEventLoop wrapper. If there is no running
+asyncio event loop but portage has a reference to another running
+loop in this thread, then use that instead.
+
+This behavior enables portage internals to use the real asyncio.run
+while remaining compatible with internal code that does not use the
+real asyncio.run.
+"""
+try:
+_loop = _real_asyncio.get_running_loop()
+except RuntimeError:
+_loop = None
+
 with _thread_weakrefs.lock:
 if _thread_weakrefs.pid == portage.getpid():
 try:
 loop = _thread_weakrefs.loops[threading.get_ident()]
 except KeyError:
-return None
-return loop if loop.is_running() else None
+pass
+else:
+if _loop is loop._loop:
+return loop
+elif _loop is None:
+return loop if loop.is_running() else None
+
+# If _loop it not None here it means it was probably a temporary
+# loop created by asyncio.run, so we don't try to cache it, and
+# just return a temporary wrapper.
+return None if _loop is None else _AsyncioEventLoop(loop=_loop)
 
 
 def _thread_weakrefs_atexit():



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/tests/util/

2024-02-22 Thread Zac Medico
commit: fbaaa4a733aaadc2744b656527756ac4e2b7ab58
Author: Zac Medico  gentoo  org>
AuthorDate: Thu Feb 22 06:47:33 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Thu Feb 22 07:28:38 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=fbaaa4a7

socks5: Use real asyncio.run

Use real asyncio.run to demonstrate that it is compatible with
portage internals. Since the socks5 ProxyManager uses the
process.spawn function, the internal _running_loop function
needs to return the correct loop for use in the wait method of
MultiprocessingProcess, or else it will lead to Future
"attached to a different loop" errors.

Bug: https://bugs.gentoo.org/761538
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/tests/util/test_socks5.py | 45 +++
 lib/portage/util/socks5.py| 30 ---
 2 files changed, 46 insertions(+), 29 deletions(-)

diff --git a/lib/portage/tests/util/test_socks5.py 
b/lib/portage/tests/util/test_socks5.py
index 987b41af29..7b33cb3f6b 100644
--- a/lib/portage/tests/util/test_socks5.py
+++ b/lib/portage/tests/util/test_socks5.py
@@ -1,6 +1,7 @@
-# Copyright 2019-2021 Gentoo Authors
+# Copyright 2019-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
+import asyncio
 import functools
 import shutil
 import socket
@@ -10,7 +11,6 @@ import time
 
 import portage
 from portage.tests import TestCase
-from portage.util._eventloop.global_event_loop import global_event_loop
 from portage.util import socks5
 from portage.const import PORTAGE_BIN_PATH
 
@@ -88,18 +88,20 @@ class AsyncHTTPServerTestCase(TestCase):
 if f is not None:
 f.close()
 
-def test_http_server(self):
+async def _test_http_server(self):
+asyncio.run(self._test_http_server())
+
+async def _test_http_server(self):
 host = "127.0.0.1"
 content = b"Hello World!\n"
 path = "/index.html"
-loop = global_event_loop()
+
+loop = asyncio.get_running_loop()
 for i in range(2):
 with AsyncHTTPServer(host, {path: content}, loop) as server:
 for j in range(2):
-result = loop.run_until_complete(
-loop.run_in_executor(
-None, self._fetch_directly, host, 
server.server_port, path
-)
+result = await loop.run_in_executor(
+None, self._fetch_directly, host, server.server_port, 
path
 )
 self.assertEqual(result, content)
 
@@ -177,7 +179,10 @@ class Socks5ServerTestCase(TestCase):
 return f.read()
 
 def test_socks5_proxy(self):
-loop = global_event_loop()
+asyncio.run(self._test_socks5_proxy())
+
+async def _test_socks5_proxy(self):
+loop = asyncio.get_running_loop()
 
 host = "127.0.0.1"
 content = b"Hello World!"
@@ -193,20 +198,18 @@ class Socks5ServerTestCase(TestCase):
 }
 
 proxy = socks5.get_socks5_proxy(settings)
-loop.run_until_complete(socks5.proxy.ready())
-
-result = loop.run_until_complete(
-loop.run_in_executor(
-None,
-self._fetch_via_proxy,
-proxy,
-host,
-server.server_port,
-path,
-)
+await socks5.proxy.ready()
+
+result = await loop.run_in_executor(
+None,
+self._fetch_via_proxy,
+proxy,
+host,
+server.server_port,
+path,
 )
 
 self.assertEqual(result, content)
 finally:
-socks5.proxy.stop()
+await socks5.proxy.stop()
 shutil.rmtree(tempdir)

diff --git a/lib/portage/util/socks5.py b/lib/portage/util/socks5.py
index 6c68ff4106..74592aeefe 100644
--- a/lib/portage/util/socks5.py
+++ b/lib/portage/util/socks5.py
@@ -2,15 +2,16 @@
 # Copyright 2015-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
+import asyncio
 import errno
 import os
 import socket
+from typing import Union
 
 import portage.data
 from portage import _python_interpreter
 from portage.data import portage_gid, portage_uid, userpriv_groups
 from portage.process import atexit_register, spawn
-from portage.util.futures import asyncio
 
 
 class ProxyManager:
@@ -57,23 +58,36 @@ class ProxyManager:
 **spawn_kwargs,
 )
 
-def stop(self):
+def stop(self) -> Union[None, asyncio.Future]:
 """
 Stop the SOCKSv5 server.
+
+If there is a running asyncio event loop then asyncio.Future is
+returned which should be used to wait 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/, lib/portage/package/ebuild/, ...

2024-02-21 Thread Zac Medico
commit: 18cdb6331a66c1cc92f296b1aaf0538f63586875
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Feb 13 08:44:50 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Feb 21 15:27:31 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=18cdb633

EbuildPhase: async_check_locale

Change config.environ() check_locale calls to async_check_locale
calls in the EbuildPhase _async_start method in order to eliminate
synchronous waiting for child processes in the main event loop
thread.

Bug: https://bugs.gentoo.org/923841
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/EbuildMetadataPhase.py|  4 
 lib/_emerge/EbuildPhase.py| 28 ++-
 lib/portage/package/ebuild/config.py  | 26 +++--
 lib/portage/util/futures/_asyncio/__init__.py |  9 +
 lib/portage/util/locale.py| 28 ++-
 5 files changed, 70 insertions(+), 25 deletions(-)

diff --git a/lib/_emerge/EbuildMetadataPhase.py 
b/lib/_emerge/EbuildMetadataPhase.py
index fc64d84c94..54177840c7 100644
--- a/lib/_emerge/EbuildMetadataPhase.py
+++ b/lib/_emerge/EbuildMetadataPhase.py
@@ -8,6 +8,7 @@ import portage
 
 portage.proxy.lazyimport.lazyimport(
 globals(),
+"_emerge.EbuildPhase:_setup_locale",
 "portage.package.ebuild._metadata_invalid:eapi_invalid",
 )
 from portage import os
@@ -83,6 +84,9 @@ class EbuildMetadataPhase(SubProcess):
 settings.setcpv(self.cpv)
 settings.configdict["pkg"]["EAPI"] = parsed_eapi
 
+# This requires above setcpv and EAPI setup.
+await _setup_locale(self.settings)
+
 debug = settings.get("PORTAGE_DEBUG") == "1"
 master_fd = None
 slave_fd = None

diff --git a/lib/_emerge/EbuildPhase.py b/lib/_emerge/EbuildPhase.py
index 3b366f39c7..b472803438 100644
--- a/lib/_emerge/EbuildPhase.py
+++ b/lib/_emerge/EbuildPhase.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2021 Gentoo Authors
+# Copyright 1999-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import functools
@@ -24,6 +24,7 @@ from portage.package.ebuild.prepare_build_dirs import (
 _prepare_fake_distdir,
 _prepare_fake_filesdir,
 )
+from portage.eapi import _get_eapi_attrs
 from portage.util import writemsg, ensure_dirs
 from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
 from portage.util._async.BuildLogger import BuildLogger
@@ -54,12 +55,34 @@ portage.proxy.lazyimport.lazyimport(
 + "_post_src_install_write_metadata,"
 + "_preinst_bsdflags",
 "portage.util.futures.unix_events:_set_nonblocking",
+"portage.util.locale:async_check_locale,split_LC_ALL",
 )
 from portage import os
 from portage import _encodings
 from portage import _unicode_encode
 
 
+async def _setup_locale(settings):
+eapi_attrs = _get_eapi_attrs(settings["EAPI"])
+if eapi_attrs.posixish_locale:
+split_LC_ALL(settings)
+settings["LC_COLLATE"] = "C"
+# check_locale() returns None when check can not be executed.
+if await async_check_locale(silent=True, env=settings.environ()) is 
False:
+# try another locale
+for l in ("C.UTF-8", "en_US.UTF-8", "en_GB.UTF-8", "C"):
+settings["LC_CTYPE"] = l
+if await async_check_locale(silent=True, 
env=settings.environ()):
+# TODO: output the following only once
+# writemsg(
+# _("!!! LC_CTYPE unsupported, using %s instead\n")
+# % self.settings["LC_CTYPE"]
+# )
+break
+else:
+raise AssertionError("C locale did not pass the test!")
+
+
 class EbuildPhase(CompositeTask):
 __slots__ = ("actionmap", "fd_pipes", "phase", "settings") + 
("_ebuild_lock",)
 
@@ -95,6 +118,9 @@ class EbuildPhase(CompositeTask):
 self._start_task(AsyncTaskFuture(future=future), 
self._async_start_exit)
 
 async def _async_start(self):
+
+await _setup_locale(self.settings)
+
 need_builddir = self.phase not in 
EbuildProcess._phases_without_builddir
 
 if need_builddir:

diff --git a/lib/portage/package/ebuild/config.py 
b/lib/portage/package/ebuild/config.py
index c89354cbf7..bafdc55a08 100644
--- a/lib/portage/package/ebuild/config.py
+++ b/lib/portage/package/ebuild/config.py
@@ -29,7 +29,6 @@ portage.proxy.lazyimport.lazyimport(
 "portage.dbapi.vartree:vartree",
 "portage.package.ebuild.doebuild:_phase_func_map",
 "portage.util.compression_probe:_compressors",
-"portage.util.locale:check_locale,split_LC_ALL",
 )
 from portage import bsd_chflags, load_mod, os, selinux, _unicode_decode
 from portage.const import (
@@ -3371,20 +3370,17 @@ class config:
 mydict["EBUILD_PHASE_FUNC"] = phase_func
 
 if eapi_attrs.posixish_locale:
-split_LC_ALL(mydict)
-  

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/

2024-02-21 Thread Zac Medico
commit: a42c2164ada634262ae1f791ad60298fe3468a94
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Feb 13 03:39:35 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Feb 21 15:27:31 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a42c2164

asyncio: Wrap asyncio.Lock for python 3.9 compat

Wrap asyncio.Lock for compatibility with python 3.9 where the
deprecated loop parameter is required in order to avoid "got
Future  attached to a different loop" errors.

The pordbapi async_aux_get method can use asyncio.Lock to
serialize access to its doebuild_settings attribute in order
to prevent issues like bug 924319.

Bug: https://bugs.gentoo.org/924319
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/_asyncio/__init__.py | 17 +
 1 file changed, 17 insertions(+)

diff --git a/lib/portage/util/futures/_asyncio/__init__.py 
b/lib/portage/util/futures/_asyncio/__init__.py
index 8f1b8e8275..b6481c281e 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -9,6 +9,7 @@ __all__ = (
 "CancelledError",
 "Future",
 "InvalidStateError",
+"Lock",
 "TimeoutError",
 "get_child_watcher",
 "get_event_loop",
@@ -22,6 +23,7 @@ __all__ = (
 "wait_for",
 )
 
+import sys
 import types
 import weakref
 
@@ -35,6 +37,7 @@ from asyncio import (
 FIRST_EXCEPTION,
 Future,
 InvalidStateError,
+Lock as _Lock,
 shield,
 TimeoutError,
 wait_for,
@@ -159,6 +162,20 @@ def iscoroutinefunction(func):
 return False
 
 
+class Lock(_Lock):
+"""
+Inject loop parameter for python3.9 or less in order to avoid
+"got Future  attached to a different loop" errors.
+"""
+
+def __init__(self, **kwargs):
+if sys.version_info >= (3, 10):
+kwargs.pop("loop", None)
+elif "loop" not in kwargs:
+kwargs["loop"] = _safe_loop()._loop
+super().__init__(**kwargs)
+
+
 class Task(Future):
 """
 Schedule the execution of a coroutine: wrap it in a future. A task



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2024-02-14 Thread Zac Medico
commit: 038ad1029ea574b106906380e47479db1041bee2
Author: Zac Medico  gentoo  org>
AuthorDate: Wed Feb 14 05:55:31 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Feb 14 06:04:22 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=038ad102

BuildLogger: Fix portage.locks._open_fds memory leak

The _file_close_wrapper __getattribute__ method needs to
be overridden to expose its close method, otherwise the
underlying file's close method is called and the closed
file object remains as a memory leak in the global
portage.locks._open_fds dict. For reference, see similar
classes like portage.util.atomic_ofstream which overrides
methods in the same way.

Bug: https://bugs.gentoo.org/919072
Fixes: df212738bbb2 ("BuildLogger: Close self._stdin after fork")
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/BuildLogger.py | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lib/portage/util/_async/BuildLogger.py 
b/lib/portage/util/_async/BuildLogger.py
index 9f8a21ab2b..0cfc90a942 100644
--- a/lib/portage/util/_async/BuildLogger.py
+++ b/lib/portage/util/_async/BuildLogger.py
@@ -1,4 +1,4 @@
-# Copyright 2020-2023 Gentoo Authors
+# Copyright 2020-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import functools
@@ -31,6 +31,11 @@ class _file_close_wrapper(ObjectProxy):
 def _get_target(self):
 return object.__getattribute__(self, "_file")
 
+def __getattribute__(self, attr):
+if attr == "close":
+return object.__getattribute__(self, attr)
+return getattr(object.__getattribute__(self, "_file"), attr)
+
 def close(self):
 file = object.__getattribute__(self, "_file")
 if not file.closed:



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2024-02-09 Thread Zac Medico
commit: ba33bc425363977eaf549a087b2469720a79e2a4
Author: Zac Medico  gentoo  org>
AuthorDate: Thu Feb  8 06:46:04 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Fri Feb  9 08:19:00 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ba33bc42

check_locale: Use multiprocessing.Process instead of os.fork()

Since os.fork() is unsafe in threaded processes, use
multiprocessing.Process instead. This way the fork will be
eliminated when the default multiprocessing start method
changes to "spawn".

TODO: Make async version of check_locale and call it from
EbuildPhase instead of config.environ(), since it's bad to
synchronously wait for the process in the main event loop
thread where config.environ() tends to be called.

Bug: https://bugs.gentoo.org/923841
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/locale.py | 56 +++---
 1 file changed, 33 insertions(+), 23 deletions(-)

diff --git a/lib/portage/util/locale.py b/lib/portage/util/locale.py
index a620dbd544..b5da8d949b 100644
--- a/lib/portage/util/locale.py
+++ b/lib/portage/util/locale.py
@@ -9,7 +9,8 @@ locale.
 
 import locale
 import logging
-import os
+import multiprocessing
+import sys
 import textwrap
 import traceback
 
@@ -96,6 +97,24 @@ def _check_locale(silent):
 return True
 
 
+def _set_and_check_locale(silent, env, mylocale):
+try:
+if env is not None:
+try:
+locale.setlocale(locale.LC_CTYPE, mylocale)
+except locale.Error:
+sys.exit(2)
+
+ret = _check_locale(silent)
+if ret is None:
+sys.exit(2)
+else:
+sys.exit(0 if ret else 1)
+except Exception:
+traceback.print_exc()
+sys.exit(2)
+
+
 def check_locale(silent=False, env=None):
 """
 Check whether the locale is sane. Returns True if it is, prints
@@ -116,29 +135,20 @@ def check_locale(silent=False, env=None):
 except KeyError:
 pass
 
-pid = os.fork()
-if pid == 0:
-try:
-if env is not None:
-try:
-locale.setlocale(locale.LC_CTYPE, 
portage._native_string(mylocale))
-except locale.Error:
-os._exit(2)
-
-ret = _check_locale(silent)
-if ret is None:
-os._exit(2)
-else:
-os._exit(0 if ret else 1)
-except Exception:
-traceback.print_exc()
-os._exit(2)
-
-pid2, ret = os.waitpid(pid, 0)
-assert pid == pid2
+# TODO: Make async version of check_locale and call it from
+# EbuildPhase instead of config.environ(), since it's bad to
+# synchronously wait for the process in the main event loop
+# thread where config.environ() tends to be called.
+proc = multiprocessing.Process(
+target=_set_and_check_locale,
+args=(silent, env, None if env is None else 
portage._native_string(mylocale)),
+)
+proc.start()
+proc.join()
+
 pyret = None
-if os.WIFEXITED(ret):
-ret = os.WEXITSTATUS(ret)
+if proc.exitcode >= 0:
+ret = proc.exitcode
 if ret != 2:
 pyret = ret == 0
 



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/, lib/portage/util/, ...

2024-02-09 Thread Zac Medico
commit: c95fc64abf9698263090b3ffd4a056e989dd2be1
Author: Zac Medico  gentoo  org>
AuthorDate: Fri Feb  9 06:38:41 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Fri Feb  9 08:19:00 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=c95fc64a

EbuildPhase: async_check_locale

Change config.environ() check_locale calls to async_check_locale
calls in the EbuildPhase _async_start method in order to eliminate
synchronous waiting for child processes in the main event loop
thread.

Bug: https://bugs.gentoo.org/923841
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/EbuildMetadataPhase.py| 21 
 lib/_emerge/EbuildPhase.py| 28 ++-
 lib/portage/package/ebuild/config.py  | 26 +++--
 lib/portage/util/futures/_asyncio/__init__.py |  9 +
 lib/portage/util/locale.py| 28 ++-
 5 files changed, 87 insertions(+), 25 deletions(-)

diff --git a/lib/_emerge/EbuildMetadataPhase.py 
b/lib/_emerge/EbuildMetadataPhase.py
index f4f685e81c..53b7ad9624 100644
--- a/lib/_emerge/EbuildMetadataPhase.py
+++ b/lib/_emerge/EbuildMetadataPhase.py
@@ -8,12 +8,14 @@ import portage
 
 portage.proxy.lazyimport.lazyimport(
 globals(),
+"_emerge.EbuildPhase:_setup_locale",
 "portage.package.ebuild._metadata_invalid:eapi_invalid",
 )
 from portage import os
 from portage import _encodings
 from portage import _unicode_decode
 from portage import _unicode_encode
+from portage.util.futures import asyncio
 
 import fcntl
 
@@ -44,6 +46,12 @@ class EbuildMetadataPhase(SubProcess):
 _files_dict = slot_dict_class(_file_names, prefix="")
 
 def _start(self):
+asyncio.ensure_future(
+self._async_start(), loop=self.scheduler
+).add_done_callback(self._async_start_done)
+
+async def _async_start(self):
+
 ebuild_path = self.ebuild_hash.location
 
 with open(
@@ -75,6 +83,9 @@ class EbuildMetadataPhase(SubProcess):
 settings.setcpv(self.cpv)
 settings.configdict["pkg"]["EAPI"] = parsed_eapi
 
+# This requires above setcpv and EAPI setup.
+await _setup_locale(self.settings)
+
 debug = settings.get("PORTAGE_DEBUG") == "1"
 master_fd = None
 slave_fd = None
@@ -139,6 +150,16 @@ class EbuildMetadataPhase(SubProcess):
 
 self._proc = retval
 
+def _async_start_done(self, future):
+future.cancelled() or future.result()
+if future.cancelled():
+self.cancel()
+self._was_cancelled()
+
+if self.returncode is not None:
+self._unregister()
+self.wait()
+
 def _output_handler(self):
 while True:
 buf = self._read_buf(self._files.ebuild)

diff --git a/lib/_emerge/EbuildPhase.py b/lib/_emerge/EbuildPhase.py
index c81bf54a81..c8caf73722 100644
--- a/lib/_emerge/EbuildPhase.py
+++ b/lib/_emerge/EbuildPhase.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2021 Gentoo Authors
+# Copyright 1999-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import functools
@@ -24,6 +24,7 @@ from portage.package.ebuild.prepare_build_dirs import (
 _prepare_fake_distdir,
 _prepare_fake_filesdir,
 )
+from portage.eapi import _get_eapi_attrs
 from portage.util import writemsg, ensure_dirs
 from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
 from portage.util._async.BuildLogger import BuildLogger
@@ -54,12 +55,34 @@ portage.proxy.lazyimport.lazyimport(
 + "_post_src_install_write_metadata,"
 + "_preinst_bsdflags",
 "portage.util.futures.unix_events:_set_nonblocking",
+"portage.util.locale:async_check_locale,split_LC_ALL",
 )
 from portage import os
 from portage import _encodings
 from portage import _unicode_encode
 
 
+async def _setup_locale(settings):
+eapi_attrs = _get_eapi_attrs(settings["EAPI"])
+if eapi_attrs.posixish_locale:
+split_LC_ALL(settings)
+settings["LC_COLLATE"] = "C"
+# check_locale() returns None when check can not be executed.
+if await async_check_locale(silent=True, env=settings.environ()) is 
False:
+# try another locale
+for l in ("C.UTF-8", "en_US.UTF-8", "en_GB.UTF-8", "C"):
+settings["LC_CTYPE"] = l
+if await async_check_locale(silent=True, 
env=settings.environ()):
+# TODO: output the following only once
+# writemsg(
+# _("!!! LC_CTYPE unsupported, using %s instead\n")
+# % self.settings["LC_CTYPE"]
+# )
+break
+else:
+raise AssertionError("C locale did not pass the test!")
+
+
 class EbuildPhase(CompositeTask):
 __slots__ = ("actionmap", "fd_pipes", "phase", "settings") + 
("_ebuild_lock",)
 
@@ -94,6 +117,9 @@ class 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/elf/, lib/portage/dep/soname/, /

2024-02-08 Thread Sam James
commit: da6607f012572b4d13fdc6fd5ecd4a62d62a417b
Author: Matoro Mahri  matoro  tk>
AuthorDate: Tue Oct 31 21:00:34 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Fri Feb  9 07:26:32 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=da6607f0

ELF: add entries for ARC machines

Signed-off-by: Matoro Mahri  matoro.tk>
Closes: https://github.com/gentoo/portage/pull/1166
Signed-off-by: Sam James  gentoo.org>

 NEWS|  1 +
 lib/portage/dep/soname/multilib_category.py | 10 ++
 lib/portage/util/elf/constants.py   |  5 +
 3 files changed, 16 insertions(+)

diff --git a/NEWS b/NEWS
index 220a0f4f7e..396723d8a8 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@ portage-3.0.62 (UNRELEASED)
 
 Features:
 * cnf: make.conf.example.arc: add for the arc arch.
+* ELF: add entries for ARC machines
 
 portage-3.0.61 (2024-01-05)
 --

diff --git a/lib/portage/dep/soname/multilib_category.py 
b/lib/portage/dep/soname/multilib_category.py
index 14a9eea770..baca439fd2 100644
--- a/lib/portage/dep/soname/multilib_category.py
+++ b/lib/portage/dep/soname/multilib_category.py
@@ -52,6 +52,11 @@ from portage.util.elf.constants import (
 EM_AARCH64,
 EM_ALPHA,
 EM_AMDGPU,
+EM_ARC,
+EM_ARC_COMPACT,
+EM_ARC_COMPACT2,
+EM_ARC_COMPACT3,
+EM_ARC_COMPACT3_64,
 EM_ARM,
 EM_ALTERA_NIOS2,
 EM_IA_64,
@@ -80,6 +85,11 @@ _machine_prefix_map = {
 EM_ALPHA: "alpha",
 EM_AMDGPU: "amdgpu",
 EM_ALTERA_NIOS2: "nios2",
+EM_ARC: "arc",
+EM_ARC_COMPACT: "arc",
+EM_ARC_COMPACT2: "arc",
+EM_ARC_COMPACT3: "arc",
+EM_ARC_COMPACT3_64: "arc",
 EM_ARM: "arm",
 EM_IA_64: "ia64",
 EM_LOONGARCH: "loong",

diff --git a/lib/portage/util/elf/constants.py 
b/lib/portage/util/elf/constants.py
index 022e78d776..9216a35353 100644
--- a/lib/portage/util/elf/constants.py
+++ b/lib/portage/util/elf/constants.py
@@ -31,12 +31,17 @@ EM_S390 = 22
 EM_ARM = 40
 EM_SH = 42
 EM_SPARCV9 = 43
+EM_ARC = 45
 EM_IA_64 = 50
 EM_X86_64 = 62
+EM_ARC_COMPACT = 93
 EM_ALTERA_NIOS2 = 113
 EM_AARCH64 = 183
+EM_ARC_COMPACT2 = 195
 EM_AMDGPU = 224
 EM_RISCV = 243
+EM_ARC_COMPACT3_64 = 253
+EM_ARC_COMPACT3 = 255
 EM_LOONGARCH = 258
 EM_ALPHA = 0x9026
 



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2024-02-06 Thread Zac Medico
commit: fa8e8f1895ed889aece2f67725df55d6ccf127fb
Author: Zac Medico  gentoo  org>
AuthorDate: Sat Feb  3 23:41:45 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Feb  7 00:55:46 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=fa8e8f18

socks5: Migrate to spawn returnproc parameter

Bug: https://bugs.gentoo.org/916566
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/socks5.py | 36 +++-
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/lib/portage/util/socks5.py b/lib/portage/util/socks5.py
index fedb8599d5..6c68ff4106 100644
--- a/lib/portage/util/socks5.py
+++ b/lib/portage/util/socks5.py
@@ -1,10 +1,9 @@
 # SOCKSv5 proxy manager for network-sandbox
-# Copyright 2015-2021 Gentoo Authors
+# Copyright 2015-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import errno
 import os
-import signal
 import socket
 
 import portage.data
@@ -22,7 +21,8 @@ class ProxyManager:
 
 def __init__(self):
 self.socket_path = None
-self._pids = []
+self._proc = None
+self._proc_waiter = None
 
 def start(self, settings):
 """
@@ -51,9 +51,9 @@ class ProxyManager:
 spawn_kwargs.update(
 uid=portage_uid, gid=portage_gid, groups=userpriv_groups, 
umask=0o077
 )
-self._pids = spawn(
+self._proc = spawn(
 [_python_interpreter, server_bin, self.socket_path],
-returnpid=True,
+returnproc=True,
 **spawn_kwargs,
 )
 
@@ -61,12 +61,19 @@ class ProxyManager:
 """
 Stop the SOCKSv5 server.
 """
-for p in self._pids:
-os.kill(p, signal.SIGINT)
-os.waitpid(p, 0)
+if self._proc is not None:
+self._proc.terminate()
+loop = asyncio.get_event_loop()
+if self._proc_waiter is None:
+self._proc_waiter = asyncio.ensure_future(self._proc.wait(), 
loop)
+if loop.is_running():
+self._proc_waiter.add_done_callback(lambda future: 
future.result())
+else:
+loop.run_until_complete(self._proc_waiter)
 
 self.socket_path = None
-self._pids = []
+self._proc = None
+self._proc_waiter = None
 
 def is_running(self):
 """
@@ -80,16 +87,11 @@ class ProxyManager:
 """
 Wait for the proxy socket to become ready. This method is a coroutine.
 """
+if self._proc_waiter is None:
+self._proc_waiter = asyncio.ensure_future(self._proc.wait())
 
 while True:
-try:
-wait_retval = os.waitpid(self._pids[0], os.WNOHANG)
-except OSError as e:
-if e.errno == errno.EINTR:
-continue
-raise
-
-if wait_retval is not None and wait_retval != (0, 0):
+if self._proc_waiter.done():
 raise OSError(3, "No such process")
 
 try:



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/, lib/portage/sync/modules/rsync/

2024-02-06 Thread Zac Medico
commit: 62332ee82b8b88fa5a65aafa7c221ccdaa7d65a8
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Feb  4 00:11:07 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Feb  7 00:55:46 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=62332ee8

RsyncSync: Migrate to spawn returnproc parameter

Bug: https://bugs.gentoo.org/916566
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/sync/modules/rsync/rsync.py   | 40 +--
 lib/portage/util/futures/_asyncio/__init__.py |  6 +++-
 2 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/lib/portage/sync/modules/rsync/rsync.py 
b/lib/portage/sync/modules/rsync/rsync.py
index 175c7f2e8e..5d442d2626 100644
--- a/lib/portage/sync/modules/rsync/rsync.py
+++ b/lib/portage/sync/modules/rsync/rsync.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2023 Gentoo Authors
+# Copyright 1999-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import datetime
@@ -708,48 +708,47 @@ class RsyncSync(NewBase):
 command.append(syncuri.rstrip("/") + "/metadata/timestamp.chk")
 command.append(tmpservertimestampfile)
 content = None
-pids = []
+proc = None
+proc_waiter = None
+loop = asyncio.get_event_loop()
 try:
 # Timeout here in case the server is unresponsive.  The
 # --timeout rsync option doesn't apply to the initial
 # connection attempt.
 try:
-if self.rsync_initial_timeout:
-
portage.exception.AlarmSignal.register(self.rsync_initial_timeout)
-
-pids.extend(
-portage.process.spawn(command, returnpid=True, 
**self.spawn_kwargs)
+proc = portage.process.spawn(
+command, returnproc=True, **self.spawn_kwargs
+)
+proc_waiter = asyncio.ensure_future(proc.wait(), loop)
+future = (
+asyncio.wait_for(
+asyncio.shield(proc_waiter), self.rsync_initial_timeout
+)
+if self.rsync_initial_timeout
+else proc_waiter
 )
-exitcode = os.waitpid(pids[0], 0)[1]
+exitcode = loop.run_until_complete(future)
 if self.usersync_uid is not None:
 portage.util.apply_permissions(
 tmpservertimestampfile, uid=os.getuid()
 )
 content = portage.grabfile(tmpservertimestampfile)
 finally:
-if self.rsync_initial_timeout:
-portage.exception.AlarmSignal.unregister()
 try:
 os.unlink(tmpservertimestampfile)
 except OSError:
 pass
-except portage.exception.AlarmSignal:
+except (TimeoutError, asyncio.TimeoutError):
 # timed out
 print("timed out")
 # With waitpid and WNOHANG, only check the
 # first element of the tuple since the second
 # element may vary (bug #337465).
-if pids and os.waitpid(pids[0], os.WNOHANG)[0] == 0:
-os.kill(pids[0], signal.SIGTERM)
-os.waitpid(pids[0], 0)
+if proc_waiter and not proc_waiter.done():
+proc.terminate()
+loop.run_until_complete(proc_waiter)
 # This is the same code rsync uses for timeout.
 exitcode = 30
-else:
-if exitcode != os.EX_OK:
-if exitcode & 0xFF:
-exitcode = (exitcode & 0xFF) << 8
-else:
-exitcode = exitcode >> 8
 
 if content:
 try:
@@ -758,7 +757,6 @@ class RsyncSync(NewBase):
 )
 except (OverflowError, ValueError):
 pass
-del command, pids, content
 
 if exitcode == os.EX_OK:
 if (servertimestamp != 0) and (servertimestamp == timestamp):

diff --git a/lib/portage/util/futures/_asyncio/__init__.py 
b/lib/portage/util/futures/_asyncio/__init__.py
index a5a6cb3a5b..8f1b8e8275 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2018-2021 Gentoo Authors
+# Copyright 2018-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 __all__ = (
@@ -15,9 +15,11 @@ __all__ = (
 "set_child_watcher",
 "get_event_loop_policy",
 "set_event_loop_policy",
+"shield",
 "sleep",
 "Task",
 "wait",
+"wait_for",
 )
 
 import types
@@ -33,7 +35,9 @@ from asyncio import (
 FIRST_EXCEPTION,
 Future,
 InvalidStateError,
+shield,
 TimeoutError,
+wait_for,
 )
 
 import threading



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/executor/, lib/portage/tests/util/futures/

2024-02-06 Thread Zac Medico
commit: 6c4b542b2a830587869b6180e879b719e97fda66
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Feb  6 04:00:29 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Feb  7 00:49:26 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=6c4b542b

ForkExecutor: multiprocessing spawn compat

Use the AsyncFunction create_pipe=False parameter to avoid issues
in the pipe code triggered with the "spawn" multiprocessing start
method when spawn uses multiprocessing.Process (bug 916566), since
these jobs should inherit stdio streams and run in the foreground
with no log. Also fix RetryForkExecutorTestCase to avoid pickling
issues.

Bug: https://bugs.gentoo.org/923854
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/tests/util/futures/test_retry.py | 42 ++--
 lib/portage/util/futures/executor/fork.py|  6 ++--
 2 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/lib/portage/tests/util/futures/test_retry.py 
b/lib/portage/tests/util/futures/test_retry.py
index a5b56bdc7f..6bd3f4b64a 100644
--- a/lib/portage/tests/util/futures/test_retry.py
+++ b/lib/portage/tests/util/futures/test_retry.py
@@ -1,4 +1,4 @@
-# Copyright 2018-2023 Gentoo Authors
+# Copyright 2018-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from concurrent.futures import Future, ThreadPoolExecutor
@@ -9,7 +9,6 @@ import threading
 import weakref
 import time
 
-import portage
 from portage.tests import TestCase
 from portage.util._eventloop.global_event_loop import global_event_loop
 from portage.util.backoff import RandomExponentialBackoff
@@ -229,16 +228,19 @@ class RetryForkExecutorTestCase(RetryTestCase):
 
 @contextlib.contextmanager
 def _wrap_coroutine_func(self, coroutine_func):
+uses_subprocess = isinstance(self._executor, ForkExecutor)
 parent_loop = global_event_loop()
-parent_pid = portage.getpid()
 pending = weakref.WeakValueDictionary()
 
 # Since ThreadPoolExecutor does not propagate cancellation of a
 # parent_future to the underlying coroutine, use kill_switch to
 # propagate task cancellation to wrapper, so that HangForever's
 # thread returns when retry eventually cancels parent_future.
-def wrapper(kill_switch):
-if portage.getpid() == parent_pid:
+if uses_subprocess:
+wrapper = _run_coroutine_in_subprocess(coroutine_func)
+else:
+
+def wrapper(kill_switch):
 # thread in main process
 def done_callback(result):
 result.cancelled() or result.exception() or result.result()
@@ -262,22 +264,19 @@ class RetryForkExecutorTestCase(RetryTestCase):
 else:
 return future.result().result()
 
-# child process
-loop = global_event_loop()
-try:
-return loop.run_until_complete(coroutine_func())
-finally:
-loop.close()
-
 def execute_wrapper():
-kill_switch = threading.Event()
+# Use kill_switch for threads because they can't be killed
+# like processes. Do not pass kill_switch to subprocesses
+# because it is not picklable.
+kill_switch = None if uses_subprocess else threading.Event()
+wrapper_args = [kill_switch] if kill_switch else []
 parent_future = asyncio.ensure_future(
-parent_loop.run_in_executor(self._executor, wrapper, 
kill_switch),
+parent_loop.run_in_executor(self._executor, wrapper, 
*wrapper_args),
 loop=parent_loop,
 )
 
 def kill_callback(parent_future):
-if not kill_switch.is_set():
+if kill_switch is not None and not kill_switch.is_set():
 kill_switch.set()
 
 parent_future.add_done_callback(kill_callback)
@@ -298,6 +297,19 @@ class RetryForkExecutorTestCase(RetryTestCase):
 future.cancelled() or future.exception() or future.result()
 
 
+class _run_coroutine_in_subprocess:
+def __init__(self, coroutine_func):
+self._coroutine_func = coroutine_func
+
+def __call__(self):
+# child process
+loop = global_event_loop()
+try:
+return loop.run_until_complete(self._coroutine_func())
+finally:
+loop.close()
+
+
 class RetryThreadExecutorTestCase(RetryForkExecutorTestCase):
 def _setUpExecutor(self):
 self._executor = ThreadPoolExecutor(max_workers=1)

diff --git a/lib/portage/util/futures/executor/fork.py 
b/lib/portage/util/futures/executor/fork.py
index 61ad6aecfb..1e3d010724 100644
--- a/lib/portage/util/futures/executor/fork.py
+++ b/lib/portage/util/futures/executor/fork.py
@@ -1,4 +1,4 @@
-# Copyright 2018 Gentoo Foundation
+# Copyright 2018-2024 Gentoo Authors
 # Distributed under the 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2024-02-06 Thread Zac Medico
commit: 7d7ef237f3dddcf450fedab5aabfd57d1fb3406d
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Feb  6 01:35:25 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Feb  7 00:36:56 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=7d7ef237

ForkProcess: Handle BrokenPipeError in _send_fd_pipes

Convert _send_fd_pipes BrokenPipeError to asyncio.CancelledError,
in order to gracefully handle a concurrently terminated child
process as in testAsynchronousLockWaitCancel. Even if the child
terminated abnormally, then there is no harm in suppressing the
exception here, since the child error should have gone to stderr.

Bug: https://bugs.gentoo.org/923852
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/ForkProcess.py | 25 +
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/lib/portage/util/_async/ForkProcess.py 
b/lib/portage/util/_async/ForkProcess.py
index cb240d0712..ebcbd94107 100644
--- a/lib/portage/util/_async/ForkProcess.py
+++ b/lib/portage/util/_async/ForkProcess.py
@@ -153,15 +153,24 @@ class ForkProcess(SpawnProcess):
 This performs blocking IO, intended for invocation via run_in_executor.
 """
 fd_list = list(set(self._fd_pipes.values()))
-self._files.connection.send(
-(self._fd_pipes, fd_list),
-)
-for fd in fd_list:
-multiprocessing.reduction.send_handle(
-self._files.connection,
-fd,
-self.pid,
+try:
+self._files.connection.send(
+(self._fd_pipes, fd_list),
 )
+for fd in fd_list:
+multiprocessing.reduction.send_handle(
+self._files.connection,
+fd,
+self.pid,
+)
+except BrokenPipeError as e:
+# This case is triggered by testAsynchronousLockWaitCancel
+# when the test case terminates the child process while
+# this thread is still sending the fd_pipes (bug 923852).
+# Even if the child terminated abnormally, then there is
+# no harm in suppressing the exception here, since the
+# child error should have gone to stderr.
+raise asyncio.CancelledError from e
 
 # self._fd_pipes contains duplicates that must be closed.
 for fd in fd_list:



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2024-02-03 Thread Zac Medico
commit: 9f96ce5105e7bd2580ae9acc34d6ebad914dae47
Author: Zac Medico  gentoo  org>
AuthorDate: Sat Feb  3 19:36:05 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sat Feb  3 19:55:19 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=9f96ce51

ForkProcess: Use duplicate fd_pipes in _send_fd_pipes thread

In order to allow callers to manage the lifecycle of fd_pipes
file descriptors, create duplicates for _send_fd_pipes to
close when it has finished sending them.

This fixes bug 916601 in a nice way, allowing commit
3b1234ba69a31709cd5aec1ae070901e3a28bb7c to be reverted.

Bug: https://bugs.gentoo.org/916601
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/ForkProcess.py | 55 +-
 1 file changed, 48 insertions(+), 7 deletions(-)

diff --git a/lib/portage/util/_async/ForkProcess.py 
b/lib/portage/util/_async/ForkProcess.py
index 711bd2a7ba..3acbe34fc6 100644
--- a/lib/portage/util/_async/ForkProcess.py
+++ b/lib/portage/util/_async/ForkProcess.py
@@ -24,6 +24,8 @@ class ForkProcess(SpawnProcess):
 "kwargs",
 "target",
 "_child_connection",
+# Duplicate file descriptors for use by _send_fd_pipes background 
thread.
+"_fd_pipes",
 )
 
 _file_names = ("connection", "slave_fd")
@@ -53,7 +55,13 @@ class ForkProcess(SpawnProcess):
 duplex=self._HAVE_SEND_HANDLE
 )
 
-self._proc = self._spawn(self.args, fd_pipes=self.fd_pipes)
+# Handle fd_pipes in _main instead, since file descriptors are
+# not inherited with the multiprocessing "spawn" start method.
+# Pass fd_pipes=None to spawn here so that it doesn't leave
+# a closed stdin duplicate in fd_pipes (that would trigger
+# "Bad file descriptor" error if we tried to send it via
+# send_handle).
+self._proc = self._spawn(self.args, fd_pipes=None)
 
 self._registered = True
 
@@ -74,6 +82,25 @@ class ForkProcess(SpawnProcess):
 self.fd_pipes[1] = slave_fd
 self.fd_pipes[2] = slave_fd
 self._files = self._files_dict(connection=connection, 
slave_fd=slave_fd)
+
+# Create duplicate file descriptors in self._fd_pipes
+# so that the caller is free to manage the lifecycle
+# of the original fd_pipes.
+self._fd_pipes = {}
+fd_map = {}
+for dest, src in list(self.fd_pipes.items()):
+if src not in fd_map:
+src_new = fd_map[src] = os.dup(src)
+old_fdflags = fcntl.fcntl(src, fcntl.F_GETFD)
+fcntl.fcntl(src_new, fcntl.F_SETFD, old_fdflags)
+os.set_inheritable(
+src_new, not bool(old_fdflags & fcntl.FD_CLOEXEC)
+)
+self._fd_pipes[dest] = fd_map[src]
+
+asyncio.ensure_future(
+self._proc.wait(), self.scheduler
+).add_done_callback(self._close_fd_pipes)
 else:
 master_fd = connection
 
@@ -81,6 +108,19 @@ class ForkProcess(SpawnProcess):
 master_fd, log_file_path=self.logfile, stdout_fd=stdout_fd
 )
 
+def _close_fd_pipes(self, future):
+"""
+Cleanup self._fd_pipes if needed, since _send_fd_pipes could
+have been cancelled.
+"""
+# future.result() raises asyncio.CancelledError if
+# future.cancelled(), but that should not happen.
+future.result()
+if self._fd_pipes is not None:
+for fd in set(self._fd_pipes.values()):
+os.close(fd)
+self._fd_pipes = None
+
 @property
 def _fd_pipes_send_handle(self):
 """Returns True if we have a connection to implement fd_pipes via 
send_handle."""
@@ -95,9 +135,9 @@ class ForkProcess(SpawnProcess):
 Communicate with _bootstrap to send fd_pipes via send_handle.
 This performs blocking IO, intended for invocation via run_in_executor.
 """
-fd_list = list(set(self.fd_pipes.values()))
+fd_list = list(set(self._fd_pipes.values()))
 self._files.connection.send(
-(self.fd_pipes, fd_list),
+(self._fd_pipes, fd_list),
 )
 for fd in fd_list:
 multiprocessing.reduction.send_handle(
@@ -106,6 +146,11 @@ class ForkProcess(SpawnProcess):
 self.pid,
 )
 
+# self._fd_pipes contains duplicates that must be closed.
+for fd in fd_list:
+os.close(fd)
+self._fd_pipes = None
+
 async def _main(self, build_logger, pipe_logger, loop=None):
 try:
 if self._fd_pipes_send_handle:
@@ -167,10 +212,6 @@ class ForkProcess(SpawnProcess):
 )
 fd_pipes[0] = stdin_dup
 
- 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/, lib/portage/tests/locks/

2024-01-29 Thread Zac Medico
commit: d4c495c6bd543d07f3c5d6e72145e177999edaab
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Jan 28 23:44:23 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Jan 29 04:08:42 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=d4c495c6

Rely on os.register_at_fork for _ForkWatcher hook invocation

Because os.register_at_fork is used instead of
multiprocessing.util.register_after_fork since commit
cc7c40199850acb3d36f0a6452987231d592c360, we can rely on the
_ForkWatcher hook being automatically invoked after os.fork().

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/process.py| 10 +++---
 lib/portage/tests/locks/test_lock_nonblock.py |  3 +--
 lib/portage/util/locale.py|  3 +--
 3 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/lib/portage/process.py b/lib/portage/process.py
index 28f977a046..0d58adecad 100644
--- a/lib/portage/process.py
+++ b/lib/portage/process.py
@@ -1,5 +1,5 @@
 # portage.py -- core Portage functionality
-# Copyright 1998-2023 Gentoo Authors
+# Copyright 1998-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 
@@ -456,7 +456,6 @@ def spawn(
 pid = os.fork()
 
 if pid == 0:
-portage._ForkWatcher.hook(portage._ForkWatcher)
 try:
 _exec(
 binary,
@@ -504,8 +503,8 @@ def spawn(
 sys.stderr.flush()
 
 finally:
-# Don't used portage.getpid() here, due to a race with the above
-# portage._ForkWatcher cache update.
+# Don't used portage.getpid() here, in case there is a race
+# with getpid cache invalidation via _ForkWatcher hook.
 if pid == 0 or (pid is None and _os.getpid() != parent_pid):
 # Call os._exit() from a finally block in order
 # to suppress any finally blocks from earlier
@@ -775,9 +774,6 @@ def _exec(
 if unshare_pid:
 main_child_pid = os.fork()
 if main_child_pid == 0:
-# The portage.getpid() cache may need to be 
updated here,
-# in case the pre_exec function invokes 
portage APIs.
-portage._ForkWatcher.hook(portage._ForkWatcher)
 # pid namespace requires us to become init
 binary, myargs = (
 portage._python_interpreter,

diff --git a/lib/portage/tests/locks/test_lock_nonblock.py 
b/lib/portage/tests/locks/test_lock_nonblock.py
index e3f9b4d023..9bb91b428e 100644
--- a/lib/portage/tests/locks/test_lock_nonblock.py
+++ b/lib/portage/tests/locks/test_lock_nonblock.py
@@ -1,4 +1,4 @@
-# Copyright 2011-2020 Gentoo Authors
+# Copyright 2011-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import tempfile
@@ -19,7 +19,6 @@ class LockNonblockTestCase(TestCase):
 lock1 = portage.locks.lockfile(path)
 pid = os.fork()
 if pid == 0:
-portage._ForkWatcher.hook(portage._ForkWatcher)
 portage.locks._close_fds()
 # Disable close_fds since we don't exec
 # (see _setup_pipes docstring).

diff --git a/lib/portage/util/locale.py b/lib/portage/util/locale.py
index 0d0c120157..a620dbd544 100644
--- a/lib/portage/util/locale.py
+++ b/lib/portage/util/locale.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2020 Gentoo Authors
+# Copyright 2015-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 """
@@ -118,7 +118,6 @@ def check_locale(silent=False, env=None):
 
 pid = os.fork()
 if pid == 0:
-portage._ForkWatcher.hook(portage._ForkWatcher)
 try:
 if env is not None:
 try:



[gentoo-commits] proj/portage:master commit in: lib/portage/util/file_copy/, lib/_emerge/, lib/portage/util/_async/, ...

2024-01-28 Thread Zac Medico
commit: 3d55e159c473075c7b2f87c92293b0df6fa57563
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Jan 28 22:01:58 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Jan 28 23:09:26 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3d55e159

*/*: rerun black w/ 24.1.0

Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/AsynchronousTask.py |  6 +--
 lib/_emerge/EbuildMetadataPhase.py  | 11 ++---
 lib/_emerge/MergeListItem.py|  1 -
 lib/_emerge/PipeReader.py   |  1 -
 lib/_emerge/SpawnProcess.py |  1 -
 lib/_emerge/depgraph.py | 59 ++---
 lib/_emerge/resolver/slot_collision.py  | 12 ++---
 lib/portage/_emirrordist/DeletionIterator.py|  8 ++--
 lib/portage/_emirrordist/FetchIterator.py   |  8 ++--
 lib/portage/_sets/libs.py   |  1 -
 lib/portage/dbapi/porttree.py   |  1 -
 lib/portage/dbapi/vartree.py| 28 +++-
 lib/portage/dep/__init__.py |  1 -
 lib/portage/package/ebuild/config.py| 38 
 lib/portage/package/ebuild/doebuild.py  | 16 ---
 lib/portage/proxy/objectproxy.py|  1 -
 lib/portage/tests/ebuild/test_fetch.py  | 10 ++---
 lib/portage/tests/process/test_AsyncFunction.py |  8 ++--
 lib/portage/util/_async/PipeLogger.py   |  1 -
 lib/portage/util/_async/TaskScheduler.py|  1 -
 lib/portage/util/_dyn_libs/LinkageMapELF.py |  3 --
 lib/portage/util/file_copy/__init__.py  |  7 +--
 lib/portage/util/futures/_sync_decorator.py |  8 ++--
 23 files changed, 119 insertions(+), 112 deletions(-)

diff --git a/lib/_emerge/AsynchronousTask.py b/lib/_emerge/AsynchronousTask.py
index 4290eede36..4049ba5eb6 100644
--- a/lib/_emerge/AsynchronousTask.py
+++ b/lib/_emerge/AsynchronousTask.py
@@ -46,9 +46,9 @@ class AsynchronousTask(SlotObject):
 )
 self.addExitListener(exit_listener)
 waiter.add_done_callback(
-lambda waiter: self.removeExitListener(exit_listener)
-if waiter.cancelled()
-else None
+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

diff --git a/lib/_emerge/EbuildMetadataPhase.py 
b/lib/_emerge/EbuildMetadataPhase.py
index fd695e0253..8905a058fc 100644
--- a/lib/_emerge/EbuildMetadataPhase.py
+++ b/lib/_emerge/EbuildMetadataPhase.py
@@ -19,7 +19,6 @@ import fcntl
 
 
 class EbuildMetadataPhase(SubProcess):
-
 """
 Asynchronous interface for the ebuild "depend" phase which is
 used to extract metadata from the ebuild.
@@ -200,12 +199,10 @@ class EbuildMetadataPhase(SubProcess):
 # entries for unsupported EAPIs.
 if self.eapi_supported:
 if metadata.get("INHERITED", False):
-metadata[
-"_eclasses_"
-] = self.portdb.repositories.get_repo_for_location(
-self.repo_path
-).eclass_db.get_eclass_data(
-metadata["INHERITED"].split()
+metadata["_eclasses_"] = (
+self.portdb.repositories.get_repo_for_location(
+self.repo_path
+
).eclass_db.get_eclass_data(metadata["INHERITED"].split())
 )
 else:
 metadata["_eclasses_"] = {}

diff --git a/lib/_emerge/MergeListItem.py b/lib/_emerge/MergeListItem.py
index efe485c2e0..ae894704a4 100644
--- a/lib/_emerge/MergeListItem.py
+++ b/lib/_emerge/MergeListItem.py
@@ -13,7 +13,6 @@ from _emerge.PackageUninstall import PackageUninstall
 
 
 class MergeListItem(CompositeTask):
-
 """
 TODO: For parallel scheduling, everything here needs asynchronous
 execution support (start, poll, and wait methods).

diff --git a/lib/_emerge/PipeReader.py b/lib/_emerge/PipeReader.py
index 026346e0bb..76ab7f1882 100644
--- a/lib/_emerge/PipeReader.py
+++ b/lib/_emerge/PipeReader.py
@@ -8,7 +8,6 @@ from _emerge.AbstractPollTask import AbstractPollTask
 
 
 class PipeReader(AbstractPollTask):
-
 """
 Reads output from one or more files and saves it in memory,
 for retrieval via the getvalue() method. This is driven by

diff --git a/lib/_emerge/SpawnProcess.py b/lib/_emerge/SpawnProcess.py
index 72fa72c613..40740df9aa 100644
--- a/lib/_emerge/SpawnProcess.py
+++ b/lib/_emerge/SpawnProcess.py
@@ -16,7 +16,6 @@ from portage.util.futures import asyncio
 
 
 class SpawnProcess(SubProcess):
-
 """
 Constructor keyword args are passed into 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/_dyn_libs/, lib/portage/tests/util/dyn_libs/

2024-01-20 Thread Zac Medico
commit: 95d3e5e80ab9561db870858c2caf6e3bffbf47b0
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Jan 15 20:30:57 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sat Jan 20 05:18:12 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=95d3e5e8

installed_dynlibs: Resolve *.so symlinks

Resolve *.so symlinks to check if they point to regular files
inside the top directory. If a symlink points outside the top
directory then try to follow the corresponding file inside the
top directory if it exists, and otherwise stop following.

Bug: https://bugs.gentoo.org/921170
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/tests/util/dyn_libs/meson.build|  1 +
 .../tests/util/dyn_libs/test_installed_dynlibs.py  | 65 ++
 lib/portage/util/_dyn_libs/dyn_libs.py | 43 +-
 3 files changed, 106 insertions(+), 3 deletions(-)

diff --git a/lib/portage/tests/util/dyn_libs/meson.build 
b/lib/portage/tests/util/dyn_libs/meson.build
index ddb08f5b1a..8f2c919c13 100644
--- a/lib/portage/tests/util/dyn_libs/meson.build
+++ b/lib/portage/tests/util/dyn_libs/meson.build
@@ -1,5 +1,6 @@
 py.install_sources(
 [
+'test_installed_dynlibs.py',
 'test_soname_deps.py',
 '__init__.py',
 '__test__.py',

diff --git a/lib/portage/tests/util/dyn_libs/test_installed_dynlibs.py 
b/lib/portage/tests/util/dyn_libs/test_installed_dynlibs.py
new file mode 100644
index 00..421dcf6061
--- /dev/null
+++ b/lib/portage/tests/util/dyn_libs/test_installed_dynlibs.py
@@ -0,0 +1,65 @@
+# Copyright 2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import os
+import tempfile
+
+from portage.const import BASH_BINARY
+from portage.tests import TestCase
+from portage.util import ensure_dirs
+from portage.util._dyn_libs.dyn_libs import installed_dynlibs
+from portage.util.file_copy import copyfile
+
+
+class InstalledDynlibsTestCase(TestCase):
+def testInstalledDynlibsRegular(self):
+"""
+Return True for *.so regular files.
+"""
+with tempfile.TemporaryDirectory() as directory:
+bash_copy = os.path.join(directory, "lib", "libfoo.so")
+ensure_dirs(os.path.dirname(bash_copy))
+copyfile(BASH_BINARY, bash_copy)
+self.assertTrue(installed_dynlibs(directory))
+
+def testInstalledDynlibsOnlySymlink(self):
+"""
+If a *.so symlink is installed but does not point to a regular
+file inside the top directory, installed_dynlibs should return
+False (bug 921170).
+"""
+with tempfile.TemporaryDirectory() as directory:
+symlink_path = os.path.join(directory, "lib", "libfoo.so")
+ensure_dirs(os.path.dirname(symlink_path))
+os.symlink(BASH_BINARY, symlink_path)
+self.assertFalse(installed_dynlibs(directory))
+
+def testInstalledDynlibsSymlink(self):
+"""
+Return True for a *.so symlink pointing to a regular file inside
+the top directory.
+"""
+with tempfile.TemporaryDirectory() as directory:
+bash_copy = os.path.join(directory, BASH_BINARY.lstrip(os.sep))
+ensure_dirs(os.path.dirname(bash_copy))
+copyfile(BASH_BINARY, bash_copy)
+symlink_path = os.path.join(directory, "lib", "libfoo.so")
+ensure_dirs(os.path.dirname(symlink_path))
+os.symlink(bash_copy, symlink_path)
+self.assertTrue(installed_dynlibs(directory))
+
+def testInstalledDynlibsAbsoluteSymlink(self):
+"""
+If a *.so symlink target is outside of the top directory,
+traversal follows the corresponding file inside the top
+directory if it exists, and otherwise stops following the
+symlink.
+"""
+with tempfile.TemporaryDirectory() as directory:
+bash_copy = os.path.join(directory, BASH_BINARY.lstrip(os.sep))
+ensure_dirs(os.path.dirname(bash_copy))
+copyfile(BASH_BINARY, bash_copy)
+symlink_path = os.path.join(directory, "lib", "libfoo.so")
+ensure_dirs(os.path.dirname(symlink_path))
+os.symlink(BASH_BINARY, symlink_path)
+self.assertTrue(installed_dynlibs(directory))

diff --git a/lib/portage/util/_dyn_libs/dyn_libs.py 
b/lib/portage/util/_dyn_libs/dyn_libs.py
index ee28e8839c..6f8a07d70d 100644
--- a/lib/portage/util/_dyn_libs/dyn_libs.py
+++ b/lib/portage/util/_dyn_libs/dyn_libs.py
@@ -1,14 +1,51 @@
-# Copyright 2021 Gentoo Authors
+# Copyright 2021-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import os
+import stat
+
+import portage
 
 
 def installed_dynlibs(directory):
-for _dirpath, _dirnames, filenames in os.walk(directory):
+"""
+This traverses installed *.so symlinks to check if they point to
+regular files. If a symlink 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2023-12-06 Thread Zac Medico
commit: df212738bbb209356472911cda79902f0e25918e
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Dec  5 04:23:56 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Dec  6 16:22:56 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=df212738

BuildLogger: Close self._stdin after fork

In order to ensure that we can observe EOF on the read end of the pipe,
close self._stdin after fork. Since portage.locks._close_fds() already
does something similar for _lock_manager instances which have a close()
method, it will also work with these _file_close_wrapper objects.

The portage.locks._close_fds() function calls close after fork, in
the ForkProcess._bootstrap method. For more general fork coverage,
we could move the _close_fds() call to the _ForkWatcher.hook method
in portage/__init__.py, but I've reserved that for a later change
since _close_fds() has been working fine for us where we call it now.

Bug: https://bugs.gentoo.org/919072
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/BuildLogger.py | 34 +++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/lib/portage/util/_async/BuildLogger.py 
b/lib/portage/util/_async/BuildLogger.py
index 502b3390e5..9f8a21ab2b 100644
--- a/lib/portage/util/_async/BuildLogger.py
+++ b/lib/portage/util/_async/BuildLogger.py
@@ -1,4 +1,4 @@
-# Copyright 2020-2021 Gentoo Authors
+# Copyright 2020-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import functools
@@ -6,13 +6,41 @@ import subprocess
 
 from _emerge.AsynchronousTask import AsynchronousTask
 
+import portage
 from portage import os
+from portage.proxy.objectproxy import ObjectProxy
 from portage.util import shlex_split
 from portage.util._async.PipeLogger import PipeLogger
 from portage.util._async.PopenProcess import PopenProcess
 from portage.util.futures import asyncio
 
 
+class _file_close_wrapper(ObjectProxy):
+"""
+Prevent fd inheritance via fork, ensuring that we can observe
+EOF on the read end of the pipe (bug 919072).
+"""
+
+__slots__ = ("_file",)
+
+def __init__(self, file):
+ObjectProxy.__init__(self)
+object.__setattr__(self, "_file", file)
+portage.locks._open_fds[file.fileno()] = self
+
+def _get_target(self):
+return object.__getattribute__(self, "_file")
+
+def close(self):
+file = object.__getattribute__(self, "_file")
+if not file.closed:
+# This must only be called if the file is open,
+# which ensures that file.fileno() does not
+# collide with an open lock file descriptor.
+del portage.locks._open_fds[file.fileno()]
+file.close()
+
+
 class BuildLogger(AsynchronousTask):
 """
 Write to a log file, with compression support provided by PipeLogger.
@@ -67,7 +95,7 @@ class BuildLogger(AsynchronousTask):
 os.close(log_input)
 os.close(filter_output)
 else:
-self._stdin = os.fdopen(stdin, "wb", 0)
+self._stdin = _file_close_wrapper(os.fdopen(stdin, "wb", 
0))
 os.close(filter_input)
 os.close(filter_output)
 
@@ -76,7 +104,7 @@ class BuildLogger(AsynchronousTask):
 # that is missing or broken somehow, create a pipe that
 # logs directly to pipe_logger.
 log_input, stdin = os.pipe()
-self._stdin = os.fdopen(stdin, "wb", 0)
+self._stdin = _file_close_wrapper(os.fdopen(stdin, "wb", 0))
 
 # Set background=True so that pipe_logger does not log to stdout.
 pipe_logger = PipeLogger(



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/, lib/portage/tests/process/

2023-10-21 Thread Zac Medico
commit: 6abc969109754ab086db2bac5be1029de1a015c3
Author: Zac Medico  gentoo  org>
AuthorDate: Fri Oct 20 04:11:48 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Oct 22 04:17:48 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=6abc9691

ForkProcess: Implement fd_pipes via send_handle

This new fd_pipes implementation is only enabled
when the multiprocessing start method is not fork,
ensuring backward compatibility with existing
ForkProcess callers that rely on the fork start
method.

Note that the new fd_pipes implementation uses a
thread via run_in_executor, and threads are not
recommended for mixing with the fork start method
due to cpython issue 84559.

Bug: https://bugs.gentoo.org/915896
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/tests/process/test_ForkProcess.py |   7 ++
 lib/portage/util/_async/ForkProcess.py| 142 +-
 2 files changed, 124 insertions(+), 25 deletions(-)

diff --git a/lib/portage/tests/process/test_ForkProcess.py 
b/lib/portage/tests/process/test_ForkProcess.py
index c07c60e9c6..bc0b836f11 100644
--- a/lib/portage/tests/process/test_ForkProcess.py
+++ b/lib/portage/tests/process/test_ForkProcess.py
@@ -4,6 +4,7 @@
 import functools
 import multiprocessing
 import tempfile
+from unittest.mock import patch
 
 from portage import os
 from portage.tests import TestCase
@@ -37,3 +38,9 @@ class ForkProcessTestCase(TestCase):
 
 with open(logfile.name, "rb") as output:
 self.assertEqual(output.read(), test_string.encode("utf-8"))
+
+def test_spawn_logfile_no_send_handle(self):
+with patch(
+"portage.util._async.ForkProcess.ForkProcess._HAVE_SEND_HANDLE", 
new=False
+):
+self.test_spawn_logfile()

diff --git a/lib/portage/util/_async/ForkProcess.py 
b/lib/portage/util/_async/ForkProcess.py
index 09e40a2d3e..6d216a5c43 100644
--- a/lib/portage/util/_async/ForkProcess.py
+++ b/lib/portage/util/_async/ForkProcess.py
@@ -10,6 +10,7 @@ import sys
 
 import portage
 from portage import os
+from portage.cache.mappings import slot_dict_class
 from portage.util.futures import asyncio
 from _emerge.SpawnProcess import SpawnProcess
 
@@ -26,29 +27,36 @@ class ForkProcess(SpawnProcess):
 "_proc_join_task",
 )
 
+_file_names = ("connection", "slave_fd")
+_files_dict = slot_dict_class(_file_names, prefix="")
+
 # Number of seconds between poll attempts for process exit status
 # (after the sentinel has become ready).
 _proc_join_interval = 0.1
 
-def _start(self):
-if self.fd_pipes or self.logfile:
-if self.fd_pipes:
-if multiprocessing.get_start_method() != "fork":
-raise NotImplementedError(
-'fd_pipes only supported with multiprocessing start 
method "fork"'
-)
-super()._start()
-return
+_HAVE_SEND_HANDLE = getattr(multiprocessing.reduction, "HAVE_SEND_HANDLE", 
False)
 
-if self.logfile:
-if multiprocessing.get_start_method() == "fork":
-# Use superclass pty support.
-super()._start()
-return
+def _start(self):
+if multiprocessing.get_start_method() == "fork":
+# Backward compatibility mode.
+super()._start()
+return
+
+# This mode supports multiprocessing start methods
+# other than fork. Note that the fd_pipes implementation
+# uses a thread via run_in_executor, and threads are not
+# recommended for mixing with the fork start method due
+# to cpython issue 84559.
+if self.fd_pipes and not self._HAVE_SEND_HANDLE:
+raise NotImplementedError(
+'fd_pipes only supported with HAVE_SEND_HANDLE or 
multiprocessing start method "fork"'
+)
 
-# Log via multiprocessing.Pipe if necessary.
-pr, pw = multiprocessing.Pipe(duplex=False)
-self._child_connection = pw
+if self.fd_pipes or self.logfile:
+# Log via multiprocessing.Pipe if necessary.
+connection, self._child_connection = multiprocessing.Pipe(
+duplex=self._HAVE_SEND_HANDLE
+)
 
 retval = self._spawn(self.args, fd_pipes=self.fd_pipes)
 
@@ -59,11 +67,71 @@ class ForkProcess(SpawnProcess):
 self._async_waitpid()
 else:
 self._child_connection.close()
+self.fd_pipes = self.fd_pipes or {}
 stdout_fd = None
 if not self.background:
-stdout_fd = os.dup(sys.__stdout__.fileno())
+self.fd_pipes.setdefault(0, portage._get_stdin().fileno())
+self.fd_pipes.setdefault(1, sys.__stdout__.fileno())
+self.fd_pipes.setdefault(2, sys.__stderr__.fileno())
+

[gentoo-commits] proj/portage:master commit in: lib/portage/util/_eventloop/

2023-10-05 Thread Zac Medico
commit: c98240fba21b319e27fe595d70c671c9ddfb7fd0
Author: Zac Medico  gentoo  org>
AuthorDate: Thu Oct  5 08:20:14 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Thu Oct  5 08:21:47 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=c98240fb

AsyncioEventLoop: Put back _ChildWatcherThreadSafetyWrapper

In case there are multiple loops running in different threads,
use _ChildWatcherThreadSafetyWrapper. This partially reverts
commit 690ac6e78c4099e83b84ef11c0b4064b077a8ef0.

Bug: https://bugs.gentoo.org/914873
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_eventloop/asyncio_event_loop.py | 30 ++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/lib/portage/util/_eventloop/asyncio_event_loop.py 
b/lib/portage/util/_eventloop/asyncio_event_loop.py
index fe941b420a..2b21e6dfaf 100644
--- a/lib/portage/util/_eventloop/asyncio_event_loop.py
+++ b/lib/portage/util/_eventloop/asyncio_event_loop.py
@@ -112,7 +112,7 @@ class AsyncioEventLoop(_AbstractEventLoop):
 watcher = ThreadedChildWatcher()
 
 watcher.attach_loop(self._loop)
-self._child_watcher = watcher
+self._child_watcher = _ChildWatcherThreadSafetyWrapper(self, 
watcher)
 
 return self._child_watcher
 
@@ -153,3 +153,31 @@ class AsyncioEventLoop(_AbstractEventLoop):
 except ValueError:
 # This is intended to fail when not called in the main thread.
 pass
+
+
+class _ChildWatcherThreadSafetyWrapper:
+"""
+This class provides safety if multiple loops are running in different 
threads.
+"""
+
+def __init__(self, loop, real_watcher):
+self._loop = loop
+self._real_watcher = real_watcher
+
+def close(self):
+pass
+
+def __enter__(self):
+return self
+
+def __exit__(self, a, b, c):
+pass
+
+def _child_exit(self, pid, status, callback, *args):
+self._loop.call_soon_threadsafe(callback, pid, status, *args)
+
+def add_child_handler(self, pid, callback, *args):
+self._real_watcher.add_child_handler(pid, self._child_exit, callback, 
*args)
+
+def remove_child_handler(self, pid):
+return self._real_watcher.remove_child_handler(pid)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_eventloop/

2023-10-05 Thread Zac Medico
commit: 690ac6e78c4099e83b84ef11c0b4064b077a8ef0
Author: Zac Medico  gentoo  org>
AuthorDate: Thu Oct  5 06:27:27 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Thu Oct  5 06:57:11 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=690ac6e7

Eliminate deprecated asyncio.get_child_watcher() usage

Use PidfdChildWatcher if os.pidfd_open is available and works, and
otherwise use ThreadedChildWatcher which should work in any case.

The _ChildWatcherThreadSafetyWrapper class is not needed because
both PidfdChildWatcher and ThreadedChildWatcher use the running
event loop to invoke the child handler callback, and it is safe
to assume that the current AsyncioEventLoop instance is the
running loop when it is used to obtain a child watcher instance.

Bug: https://bugs.gentoo.org/914873
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_eventloop/asyncio_event_loop.py | 51 +++
 1 file changed, 24 insertions(+), 27 deletions(-)

diff --git a/lib/portage/util/_eventloop/asyncio_event_loop.py 
b/lib/portage/util/_eventloop/asyncio_event_loop.py
index 37b5b2706c..fe941b420a 100644
--- a/lib/portage/util/_eventloop/asyncio_event_loop.py
+++ b/lib/portage/util/_eventloop/asyncio_event_loop.py
@@ -6,6 +6,12 @@ import signal
 
 import asyncio as _real_asyncio
 from asyncio.events import AbstractEventLoop as _AbstractEventLoop
+from asyncio.unix_events import ThreadedChildWatcher
+
+try:
+from asyncio.unix_events import PidfdChildWatcher
+except ImportError:
+PidfdChildWatcher = None
 
 import portage
 
@@ -90,9 +96,24 @@ class AsyncioEventLoop(_AbstractEventLoop):
 @return: the internal event loop's AbstractChildWatcher interface
 """
 if self._child_watcher is None:
-self._child_watcher = _ChildWatcherThreadSafetyWrapper(
-self, _real_asyncio.get_child_watcher()
-)
+pidfd_works = False
+if PidfdChildWatcher is not None and hasattr(os, "pidfd_open"):
+try:
+fd = os.pidfd_open(portage.getpid())
+except Exception:
+pass
+else:
+os.close(fd)
+pidfd_works = True
+
+if pidfd_works:
+watcher = PidfdChildWatcher()
+else:
+watcher = ThreadedChildWatcher()
+
+watcher.attach_loop(self._loop)
+self._child_watcher = watcher
+
 return self._child_watcher
 
 @property
@@ -132,27 +153,3 @@ class AsyncioEventLoop(_AbstractEventLoop):
 except ValueError:
 # This is intended to fail when not called in the main thread.
 pass
-
-
-class _ChildWatcherThreadSafetyWrapper:
-def __init__(self, loop, real_watcher):
-self._loop = loop
-self._real_watcher = real_watcher
-
-def close(self):
-pass
-
-def __enter__(self):
-return self
-
-def __exit__(self, a, b, c):
-pass
-
-def _child_exit(self, pid, status, callback, *args):
-self._loop.call_soon_threadsafe(callback, pid, status, *args)
-
-def add_child_handler(self, pid, callback, *args):
-self._real_watcher.add_child_handler(pid, self._child_exit, callback, 
*args)
-
-def remove_child_handler(self, pid):
-return self._real_watcher.remove_child_handler(pid)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2023-10-05 Thread Zac Medico
commit: ed458fa634c37c13cadd436b38498678f4ee103d
Author: Zac Medico  gentoo  org>
AuthorDate: Thu Oct  5 05:54:40 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Thu Oct  5 05:59:39 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ed458fa6

ForkProcess: Warn if _run method is used

Bug: https://bugs.gentoo.org/915099
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/ForkProcess.py | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/lib/portage/util/_async/ForkProcess.py 
b/lib/portage/util/_async/ForkProcess.py
index 3deaf18fd0..1d2d220ed4 100644
--- a/lib/portage/util/_async/ForkProcess.py
+++ b/lib/portage/util/_async/ForkProcess.py
@@ -4,6 +4,7 @@
 import fcntl
 import functools
 import multiprocessing
+import warnings
 import signal
 import sys
 
@@ -46,6 +47,11 @@ class ForkProcess(SpawnProcess):
 target = self._run
 args = None
 kwargs = None
+warnings.warn(
+'portage.util._async.ForkProcess.ForkProcess._run is 
deprecated in favor of the "target" parameter',
+UserWarning,
+stacklevel=2,
+)
 
 # Since multiprocessing.Process closes sys.__stdin__, create a
 # temporary duplicate of fd_pipes[0] so that sys.__stdin__ can



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2023-10-03 Thread Zac Medico
commit: 73eb44fce683a8cbfca195f01783b94eea6e7eca
Author: Zac Medico  gentoo  org>
AuthorDate: Wed Oct  4 03:42:41 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Oct  4 03:43:18 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=73eb44fc

FileCopier: multiprocessing spawn compat

Bug: https://bugs.gentoo.org/915099
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/FileCopier.py | 18 +++---
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/lib/portage/util/_async/FileCopier.py 
b/lib/portage/util/_async/FileCopier.py
index da0e85ee4e..d53ff08591 100644
--- a/lib/portage/util/_async/FileCopier.py
+++ b/lib/portage/util/_async/FileCopier.py
@@ -1,4 +1,4 @@
-# Copyright 2013-2019 Gentoo Authors
+# Copyright 2013-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import os as _os
@@ -20,16 +20,20 @@ class FileCopier(AsyncTaskFuture):
 
 def _start(self):
 self.future = asyncio.ensure_future(
-self.scheduler.run_in_executor(ForkExecutor(loop=self.scheduler), 
self._run)
+self.scheduler.run_in_executor(
+ForkExecutor(loop=self.scheduler),
+self._target,
+self.src_path,
+self.dest_path,
+)
 )
 super()._start()
 
-def _run(self):
-src_path = _unicode_encode(
-self.src_path, encoding=_encodings["fs"], errors="strict"
-)
+@staticmethod
+def _target(src_path, dest_path):
+src_path = _unicode_encode(src_path, encoding=_encodings["fs"], 
errors="strict")
 dest_path = _unicode_encode(
-self.dest_path, encoding=_encodings["fs"], errors="strict"
+dest_path, encoding=_encodings["fs"], errors="strict"
 )
 copyfile(src_path, dest_path)
 apply_stat_permissions(dest_path, _os.stat(src_path))



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2023-10-03 Thread Zac Medico
commit: 3dfe5e326eaaca877bc7a45ec84d6b39fc8d137a
Author: Zac Medico  gentoo  org>
AuthorDate: Wed Oct  4 02:56:10 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Oct  4 03:07:12 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3dfe5e32

FileDigester: Migrate to AsyncFunction

Bug: https://bugs.gentoo.org/915099
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/FileDigester.py | 71 +
 1 file changed, 11 insertions(+), 60 deletions(-)

diff --git a/lib/portage/util/_async/FileDigester.py 
b/lib/portage/util/_async/FileDigester.py
index ce334ee95a..6491423ae4 100644
--- a/lib/portage/util/_async/FileDigester.py
+++ b/lib/portage/util/_async/FileDigester.py
@@ -1,13 +1,13 @@
-# Copyright 2013 Gentoo Foundation
+# Copyright 2013-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-from portage import os
+import functools
+
 from portage.checksum import perform_multiple_checksums
-from portage.util._async.ForkProcess import ForkProcess
-from _emerge.PipeReader import PipeReader
+from portage.util._async.AsyncFunction import AsyncFunction
 
 
-class FileDigester(ForkProcess):
+class FileDigester(AsyncFunction):
 """
 Asynchronously generate file digests. Pass in file_path and
 hash_names, and after successful execution, the digests
@@ -17,64 +17,15 @@ class FileDigester(ForkProcess):
 
 __slots__ = (
 "file_path",
-"digests",
 "hash_names",
-"_digest_pipe_reader",
-"_digest_pw",
 )
 
 def _start(self):
-pr, pw = os.pipe()
-self.fd_pipes = {}
-self.fd_pipes[pw] = pw
-self._digest_pw = pw
-self._digest_pipe_reader = PipeReader(
-input_files={"input": pr}, scheduler=self.scheduler
+self.target = functools.partial(
+perform_multiple_checksums, self.file_path, hashes=self.hash_names
 )
-self._digest_pipe_reader.addExitListener(self._digest_pipe_reader_exit)
-self._digest_pipe_reader.start()
-ForkProcess._start(self)
-os.close(pw)
-
-def _run(self):
-digests = perform_multiple_checksums(self.file_path, 
hashes=self.hash_names)
-
-buf = "".join("%s=%s\n" % item for item in 
digests.items()).encode("utf_8")
-
-while buf:
-buf = buf[os.write(self._digest_pw, buf) :]
-
-return os.EX_OK
-
-def _parse_digests(self, data):
-digests = {}
-for line in data.decode("utf_8").splitlines():
-parts = line.split("=", 1)
-if len(parts) == 2:
-digests[parts[0]] = parts[1]
-
-self.digests = digests
-
-def _async_waitpid(self):
-# Ignore this event, since we want to ensure that we
-# exit only after _digest_pipe_reader has reached EOF.
-if self._digest_pipe_reader is None:
-ForkProcess._async_waitpid(self)
-
-def _digest_pipe_reader_exit(self, pipe_reader):
-self._parse_digests(pipe_reader.getvalue())
-self._digest_pipe_reader = None
-if self.pid is None:
-self._unregister()
-self._async_wait()
-else:
-self._async_waitpid()
-
-def _unregister(self):
-ForkProcess._unregister(self)
+super()._start()
 
-pipe_reader = self._digest_pipe_reader
-if pipe_reader is not None:
-self._digest_pipe_reader = None
-pipe_reader.removeExitListener(self._digest_pipe_reader_exit)
-pipe_reader.cancel()
+@property
+def digests(self):
+return self.result



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2023-10-03 Thread Zac Medico
commit: 72760ab948047cf1f5b9e1c1fcf9d2c4934afc8c
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Oct  3 06:24:21 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Tue Oct  3 14:47:37 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=72760ab9

ForkProcess: Add target constructor parameter

If the _run method is not implemented, then use a new
"target" constructor parameter like multiprocessing.Process.
Support "args" and "kwargs" constructor parameters as well.

If the _run method is implemented, then behave in a backward
compatible manner, and ignore the "args" and "kwargs" constructor
parameters which are used by the AsyncFunction subclass.

Bug: https://bugs.gentoo.org/915099
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/AsyncFunction.py |  7 +--
 lib/portage/util/_async/ForkProcess.py   | 35 +++-
 2 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/lib/portage/util/_async/AsyncFunction.py 
b/lib/portage/util/_async/AsyncFunction.py
index 8c13b3f5ba..f27b255a55 100644
--- a/lib/portage/util/_async/AsyncFunction.py
+++ b/lib/portage/util/_async/AsyncFunction.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2020 Gentoo Authors
+# Copyright 2015-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import pickle
@@ -16,13 +16,8 @@ class AsyncFunction(ForkProcess):
 "result" attribute after the forked process has exited.
 """
 
-# NOTE: This class overrides the meaning of the SpawnProcess 'args'
-# attribute, and uses it to hold the positional arguments for the
-# 'target' function.
 __slots__ = (
-"kwargs",
 "result",
-"target",
 "_async_func_reader",
 "_async_func_reader_pw",
 )

diff --git a/lib/portage/util/_async/ForkProcess.py 
b/lib/portage/util/_async/ForkProcess.py
index 22a0e0cd85..3deaf18fd0 100644
--- a/lib/portage/util/_async/ForkProcess.py
+++ b/lib/portage/util/_async/ForkProcess.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2021 Gentoo Authors
+# Copyright 2012-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import fcntl
@@ -14,7 +14,15 @@ from _emerge.SpawnProcess import SpawnProcess
 
 
 class ForkProcess(SpawnProcess):
-__slots__ = ("_proc", "_proc_join_task")
+# NOTE: This class overrides the meaning of the SpawnProcess 'args'
+# attribute, and uses it to hold the positional arguments for the
+# 'target' function.
+__slots__ = (
+"kwargs",
+"target",
+"_proc",
+"_proc_join_task",
+)
 
 # Number of seconds between poll attempts for process exit status
 # (after the sentinel has become ready).
@@ -27,6 +35,18 @@ class ForkProcess(SpawnProcess):
 any pre-fork and post-fork interpreter housekeeping that it provides,
 promoting a healthy state for the forked interpreter.
 """
+
+if self.__class__._run is ForkProcess._run:
+# target replaces the deprecated self._run method
+target = self.target
+args = self.args
+kwargs = self.kwargs
+else:
+# _run implementation triggers backward-compatibility mode
+target = self._run
+args = None
+kwargs = None
+
 # Since multiprocessing.Process closes sys.__stdin__, create a
 # temporary duplicate of fd_pipes[0] so that sys.__stdin__ can
 # be restored in the subprocess, in case this is needed for
@@ -41,7 +61,8 @@ class ForkProcess(SpawnProcess):
 )
 fd_pipes[0] = stdin_dup
 self._proc = multiprocessing.Process(
-target=self._bootstrap, args=(fd_pipes,)
+target=self._bootstrap,
+args=(fd_pipes, target, args, kwargs),
 )
 self._proc.start()
 finally:
@@ -122,7 +143,8 @@ class ForkProcess(SpawnProcess):
 self._proc_join_task.cancel()
 self._proc_join_task = None
 
-def _bootstrap(self, fd_pipes):
+@staticmethod
+def _bootstrap(fd_pipes, target, args, kwargs):
 # Use default signal handlers in order to avoid problems
 # killing subprocesses as reported in bug #353239.
 signal.signal(signal.SIGINT, signal.SIG_DFL)
@@ -159,7 +181,10 @@ class ForkProcess(SpawnProcess):
 )
 sys.__stdin__ = sys.stdin
 
-sys.exit(self._run())
+sys.exit(target(*(args or []), **(kwargs or {})))
 
 def _run(self):
+"""
+Deprecated and replaced with the "target" constructor parameter.
+"""
 raise NotImplementedError(self)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2023-10-03 Thread Zac Medico
commit: 04184a03b74669fdb48403cb8002de6395cf8684
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Oct  3 07:33:29 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Tue Oct  3 14:48:01 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=04184a03

AsyncFunction: Migrate to ForkProcess target parameter

Bug: https://bugs.gentoo.org/915099
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/AsyncFunction.py | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/lib/portage/util/_async/AsyncFunction.py 
b/lib/portage/util/_async/AsyncFunction.py
index f27b255a55..e13daaebb0 100644
--- a/lib/portage/util/_async/AsyncFunction.py
+++ b/lib/portage/util/_async/AsyncFunction.py
@@ -1,6 +1,7 @@
 # Copyright 2015-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
+import functools
 import pickle
 import traceback
 
@@ -19,26 +20,27 @@ class AsyncFunction(ForkProcess):
 __slots__ = (
 "result",
 "_async_func_reader",
-"_async_func_reader_pw",
 )
 
 def _start(self):
 pr, pw = os.pipe()
 self.fd_pipes = {} if self.fd_pipes is None else self.fd_pipes
 self.fd_pipes[pw] = pw
-self._async_func_reader_pw = pw
 self._async_func_reader = PipeReader(
 input_files={"input": pr}, scheduler=self.scheduler
 )
 self._async_func_reader.addExitListener(self._async_func_reader_exit)
 self._async_func_reader.start()
+# args and kwargs are passed as additional args by 
ForkProcess._bootstrap.
+self.target = functools.partial(self._target_wrapper, pw, self.target)
 ForkProcess._start(self)
 os.close(pw)
 
-def _run(self):
+@staticmethod
+def _target_wrapper(pw, target, *args, **kwargs):
 try:
-result = self.target(*(self.args or []), **(self.kwargs or {}))
-os.write(self._async_func_reader_pw, pickle.dumps(result))
+result = target(*args, **kwargs)
+os.write(pw, pickle.dumps(result))
 except Exception:
 traceback.print_exc()
 return 1



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, /

2023-10-02 Thread James Le Cuirot
commit: 8008e209d900dc988217ce3721292ba895cd0494
Author: James Le Cuirot  gentoo  org>
AuthorDate: Sun Oct  1 09:32:33 2023 +
Commit: James Le Cuirot  gentoo  org>
CommitDate: Mon Oct  2 21:38:18 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=8008e209

env-update: Write /usr/etc/ld.so.conf to fix bfd in some obscure cases

This is only needed on prefixed systems. bfd currently reads
${EPREFIX}/etc/ld.so.conf and adds the prefix to these paths, but these
paths are already prefixed. We need them to stay prefixed for ldconfig
and the runtime linker. bfd will use ${EPREFIX}/usr/etc/ld.so.conf
instead if that is present, so we can write the unprefixed paths there.

Other linkers do not use these files at all. We tried to patch bfd to
not use them either, as it shouldn't really be necessary, but that
broke some cases, so we are trying this safer approach instead.

env-update does not write the files under /etc/ld.so.conf.d, but we
shouldn't need to handle these in any case, as all known instances are
not affected by this issue.

Bug: https://bugs.gentoo.org/892549
Closes: https://github.com/gentoo/portage/pull/1105
Signed-off-by: James Le Cuirot  gentoo.org>

 NEWS   |  3 +++
 lib/portage/util/env_update.py | 19 +++
 2 files changed, 22 insertions(+)

diff --git a/NEWS b/NEWS
index 75680fce18..c6d0247691 100644
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,9 @@ Bug fixes:
 * emerge: fix application count when listing search results for ambiguous
   packages (bug #915054).
 
+* env-update: Write ${EPREFIX}/usr/etc/ld.so.conf with unprefixed paths on
+  prefixed systems to fix the bfd linker in some obscure cases (bug #892549).
+
 Cleanups:
 * vartree: Remove unused variables and parameters
 

diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index 04fde5a52c..b19a853251 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -221,6 +221,25 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 myfd.write(x + "\n")
 myfd.close()
 
+if eprefix:
+# ldconfig needs ld.so.conf paths to be prefixed, but the bfd 
linker
+# needs them unprefixed, so write an alternative ld.so.conf file 
for
+# the latter. Other linkers do not use these files. See ldelf.c in
+# binutils for precise bfd behavior, as well as bug #892549.
+ldsoconf_path = os.path.join(eroot, "usr", "etc", "ld.so.conf")
+ensure_dirs(os.path.dirname(ldsoconf_path), mode=0o755)
+myfd = atomic_ofstream(ldsoconf_path)
+myfd.write(
+"# ld.so.conf autogenerated by env-update; make all changes 
to\n"
+f"# contents of {eprefix}/etc/env.d directory.\n"
+"# This file is only used by the bfd linker. The paths are 
not\n"
+"# prefixed as this is automatically added by the linker.\n"
+)
+for x in specials["LDPATH"]:
+if x.startswith(eprefix + os.path.sep):
+myfd.write(x[len(eprefix) :] + "\n")
+myfd.close()
+
 potential_lib_dirs = set()
 for lib_dir_glob in ("usr/lib*", "lib*"):
 x = os.path.join(eroot, lib_dir_glob)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2023-10-02 Thread James Le Cuirot
commit: 7ff8f85350ad3bf35cfdac1c471e399a04220ed1
Author: James Le Cuirot  gentoo  org>
AuthorDate: Sun Oct  1 09:15:50 2023 +
Commit: James Le Cuirot  gentoo  org>
CommitDate: Mon Oct  2 21:33:21 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=7ff8f853

env_update: Write prefixed paths to files and terminal where appropriate

This change is entirely cosmetic as it only affects comments and
informational messages.

I wasn't sure what to do in the FreeBSD/DragonFly case because
/var/run/ld-elf.so.hints probably isn't prefixed, so I left it alone.

Signed-off-by: James Le Cuirot  gentoo.org>

 lib/portage/util/env_update.py | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index a827963ab4..04fde5a52c 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -216,7 +216,7 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 # ld.so.conf needs updating and ldconfig needs to be run
 myfd = atomic_ofstream(ldsoconf_path)
 myfd.write("# ld.so.conf autogenerated by env-update; make all changes 
to\n")
-myfd.write("# contents of /etc/env.d directory\n")
+myfd.write(f"# contents of {eprefix}/etc/env.d directory.\n")
 for x in specials["LDPATH"]:
 myfd.write(x + "\n")
 myfd.close()
@@ -242,7 +242,7 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 newprelink.write(
 "# prelink.conf autogenerated by env-update; make all changes to\n"
 )
-newprelink.write("# contents of /etc/env.d directory\n")
+newprelink.write(f"# contents of {eprefix}/etc/env.d directory\n")
 
 for x in sorted(potential_lib_dirs) + ["bin", "sbin"]:
 newprelink.write(f"-l /{x}\n")
@@ -286,7 +286,7 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 == b"# prelink.conf autogenerated by env-update; make all 
changes to\n"
 ):
 f = atomic_ofstream(prelink_conf)
-f.write("-c /etc/prelink.conf.d/*.conf\n")
+f.write(f"-c {eprefix}/etc/prelink.conf.d/*.conf\n")
 f.close()
 except OSError as e:
 if e.errno != errno.ENOENT:
@@ -361,7 +361,7 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 # an older package installed ON TOP of a newer version will cause 
ldconfig
 # to overwrite the symlinks we just made. -X means no links. After 
'clean'
 # we can safely create links.
-writemsg_level(_(f">>> Regenerating 
{target_root}etc/ld.so.cache...\n"))
+writemsg_level(_(f">>> Regenerating {eroot}etc/ld.so.cache...\n"))
 ret = subprocess.run(
 [ldconfig, "-X", "-r", target_root], cwd="/"
 ).returncode
@@ -392,8 +392,8 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 notice += "# DO NOT EDIT THIS FILE."
 penvnotice = notice + " CHANGES TO STARTUP PROFILES\n"
 cenvnotice = penvnotice[:]
-penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
-cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"
+penvnotice += f"# GO INTO {eprefix}/etc/profile NOT 
{eprefix}/etc/profile.env\n\n"
+cenvnotice += f"# GO INTO {eprefix}/etc/csh.cshrc NOT 
{eprefix}/etc/csh.env\n\n"
 
 # create /etc/profile.env for bash support
 profile_env_path = os.path.join(eroot, "etc", "profile.env")



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_eventloop/

2023-09-25 Thread Zac Medico
commit: 34e4d5655360d135dbf2cd3a073d07d96e23cf74
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Sep 26 05:09:53 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Tue Sep 26 05:14:21 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=34e4d565

Remove deprecated AbstractChildWatcher usage

Fixes this DeprecationWarning triggered by
lib/portage/tests/util/futures/asyncio/test_event_loop_in_fork.py:

lib/portage/util/_eventloop/asyncio_event_loop.py:138: DeprecationWarning: 
'AbstractChildWatcher' is deprecated as of Python 3.12 and will be removed in 
Python 3.14.
  class _ChildWatcherThreadSafetyWrapper(_AbstractChildWatcher):

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_eventloop/asyncio_event_loop.py | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/lib/portage/util/_eventloop/asyncio_event_loop.py 
b/lib/portage/util/_eventloop/asyncio_event_loop.py
index 88933af9d2..37b5b2706c 100644
--- a/lib/portage/util/_eventloop/asyncio_event_loop.py
+++ b/lib/portage/util/_eventloop/asyncio_event_loop.py
@@ -1,4 +1,4 @@
-# Copyright 2018-2021 Gentoo Authors
+# Copyright 2018-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import os
@@ -6,7 +6,6 @@ import signal
 
 import asyncio as _real_asyncio
 from asyncio.events import AbstractEventLoop as _AbstractEventLoop
-from asyncio.unix_events import AbstractChildWatcher as _AbstractChildWatcher
 
 import portage
 
@@ -135,7 +134,7 @@ class AsyncioEventLoop(_AbstractEventLoop):
 pass
 
 
-class _ChildWatcherThreadSafetyWrapper(_AbstractChildWatcher):
+class _ChildWatcherThreadSafetyWrapper:
 def __init__(self, loop, real_watcher):
 self._loop = loop
 self._real_watcher = real_watcher



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, /, lib/portage/dbapi/

2023-09-01 Thread Mike Gilbert
commit: 1d3b22621d332331da6e48ae653e983406f44e5f
Author: gcarq  protonmail  com>
AuthorDate: Fri Sep  1 16:46:23 2023 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Fri Sep  1 19:13:27 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=1d3b2262

emerge: ensure paths are UTF-8 encoded in _needs_move()

Bug: https://bugs.gentoo.org/913103
Closes: https://github.com/gentoo/portage/pull/1086
Signed-off-by: Michael Egger  protonmail.com>
Signed-off-by: Mike Gilbert  gentoo.org>

 NEWS | 2 ++
 lib/portage/dbapi/vartree.py | 7 +--
 lib/portage/util/movefile.py | 5 +++--
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/NEWS b/NEWS
index aa7ffd2652..65e75759bf 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ Features:
 Bug fixes:
 * Prevent gpg from removing /dev/null when unlocking signing key (bug #912808).
 
+* emerge: ensure paths are UTF-8 encoded in _needs_move() (bug #913103).
+
 portage-3.0.51 (2023-08-20)
 --
 

diff --git a/lib/portage/dbapi/vartree.py b/lib/portage/dbapi/vartree.py
index dac3508801..7d1bba712e 100644
--- a/lib/portage/dbapi/vartree.py
+++ b/lib/portage/dbapi/vartree.py
@@ -6273,12 +6273,15 @@ class dblink:
 if mydmode is None or not stat.S_ISREG(mydmode) or mymode != mydmode:
 return True
 
+src_bytes = _unicode_encode(mysrc, encoding=_encodings["fs"], 
errors="strict")
+dest_bytes = _unicode_encode(mydest, encoding=_encodings["fs"], 
errors="strict")
+
 if "xattr" in self.settings.features:
 excluded_xattrs = self.settings.get("PORTAGE_XATTR_EXCLUDE", "")
-if not _cmpxattr(mysrc, mydest, exclude=excluded_xattrs):
+if not _cmpxattr(src_bytes, dest_bytes, exclude=excluded_xattrs):
 return True
 
-return not filecmp.cmp(mysrc, mydest, shallow=False)
+return not filecmp.cmp(src_bytes, dest_bytes, shallow=False)
 
 
 def merge(

diff --git a/lib/portage/util/movefile.py b/lib/portage/util/movefile.py
index e2f19ba92b..75100a3acd 100644
--- a/lib/portage/util/movefile.py
+++ b/lib/portage/util/movefile.py
@@ -105,10 +105,11 @@ def _copyxattr(src, dest, exclude=None):
 )
 
 
-def _cmpxattr(src, dest, exclude=None):
+def _cmpxattr(src: bytes, dest: bytes, exclude=None) -> bool:
 """
 Compares extended attributes between |src| and |dest| and returns True
-if they are equal or xattrs are not supported, False otherwise
+if they are equal or xattrs are not supported, False otherwise.
+Assumes all given paths are UTF-8 encoded.
 """
 try:
 src_attrs = xattr.list(src)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, /

2023-08-02 Thread Sam James
commit: 19c27a2471c78d5e17b14325477fee60ead791e5
Author: James Le Cuirot  gentoo  org>
AuthorDate: Sun Jul 30 13:19:10 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Wed Aug  2 06:31:20 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=19c27a24

Use the correct library path when launching scripts directly from a venv

It's not clear what bin_entry_point.sh was trying to do before. The
regular expression didn't appear to match any likely shebang. The
wrapper already runs under the desired Python, so we only need to use
sys.executable, which points to the venv's python symlink.

We don't need to worry about handling non-Python scripts any more either
as the new Meson-based build system just installs these directly to bin
rather than creating an entrypoint for them. Any Python-based Portage
scripts they execute are now tried from the same directory first and
will therefore use the correct environment, as above.

Signed-off-by: James Le Cuirot  gentoo.org>
Signed-off-by: Sam James  gentoo.org>

 NEWS|  3 +++
 lib/portage/util/bin_entry_point.py | 18 +-
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/NEWS b/NEWS
index 0e3541af4..53db165e8 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,9 @@ Bug fixes:
 * Ensure non-Python (s)bin scripts launch other Python-based Portage scripts
   using the same environment.
 
+* Use the correct Python library path when launching scripts directly from a
+  virtual environment.
+
 portage-3.0.49 (2023-06-21)
 --
 

diff --git a/lib/portage/util/bin_entry_point.py 
b/lib/portage/util/bin_entry_point.py
index bb012b6b7..efa8b17b7 100644
--- a/lib/portage/util/bin_entry_point.py
+++ b/lib/portage/util/bin_entry_point.py
@@ -1,9 +1,8 @@
-# Copyright 2021 Gentoo Authors
+# Copyright 2021-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 __all__ = ["bin_entry_point"]
 
-import re
 import sys
 
 from portage.const import PORTAGE_BIN_PATH
@@ -18,17 +17,10 @@ def bin_entry_point():
 """
 script_path = os.path.join(PORTAGE_BIN_PATH, os.path.basename(sys.argv[0]))
 if os.access(script_path, os.X_OK):
-with open(script_path) as f:
-shebang = f.readline()
-python_match = re.search(r"/python[\d\.]*\s+([^/]*)\s+$", shebang)
-if python_match:
-sys.argv = [
-os.path.join(os.path.dirname(sys.argv[0]), "python"),
-python_match.group(1),
-script_path,
-] + sys.argv[1:]
-os.execvp(sys.argv[0], sys.argv)
-sys.argv[0] = script_path
+sys.argv = [
+sys.executable,
+script_path,
+] + sys.argv[1:]
 os.execvp(sys.argv[0], sys.argv)
 else:
 print("File not found:", script_path, file=sys.stderr)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2023-07-26 Thread Mike Gilbert
commit: 581f923b9f888efc3313b6e06ba8a3cf84641d75
Author: Mike Gilbert  gentoo  org>
AuthorDate: Wed Jul 26 14:27:48 2023 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Wed Jul 26 14:27:48 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=581f923b

env_update: drop os.waitstatus_to_exitcode

The subprocess.run() function does this translation already.

Fixes: 3bba408e214ae27bdf924ba90ad4b0919a85f3c8
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/util/env_update.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index 9d3b5bb25..a827963ab 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -381,7 +381,6 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 cwd="/",
 ).returncode
 
-ret = os.waitstatus_to_exitcode(ret)
 if ret > 0:
 writemsg(f"!!! ldconfig failed with exit status {ret}\n", 
noiselevel=-1)
 if ret < 0:



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, /

2023-07-26 Thread Sam James
commit: 3da0ff3d2dd47469becd80e744c0c3ced448a516
Author: Sam James  gentoo  org>
AuthorDate: Sat Jul 15 08:16:45 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Wed Jul 26 07:58:30 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3da0ff3d

lib: env_update: check ldconfig exit code

Bug: https://bugs.gentoo.org/910376
Signed-off-by: Sam James  gentoo.org>

 NEWS   |  2 ++
 lib/portage/util/env_update.py | 13 ++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index fcbbdb2a5..4c54ba382 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ Bug fixes:
 * install-qa-check.d/05prefix: Fix prefixifying shebang for >= EAPI 7 ebuilds
   (bug #909147).
 
+* env-update: Check exit code from ldconfig (bug #910376).
+
 * emerge: Fix 'no ebuilds available' message always mentioning binpkgs
   (bug #909853).
 

diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index d76042a6b..5c2b2fdd5 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2020 Gentoo Authors
+# Copyright 2010-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 __all__ = ["env_update"]
@@ -6,6 +6,7 @@ __all__ = ["env_update"]
 import errno
 import glob
 import stat
+import sys
 import time
 
 import portage
@@ -363,12 +364,12 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 writemsg_level(
 _(">>> Regenerating %setc/ld.so.cache...\n") % (target_root,)
 )
-os.system(f"cd / ; {ldconfig} -X -r '{target_root}'")
+ret = os.system(f"cd / ; {ldconfig} -X -r '{target_root}'")
 elif ostype in ("FreeBSD", "DragonFly"):
 writemsg_level(
 _(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % 
target_root
 )
-os.system(
+ret = os.system(
 (
 "cd / ; %s -elf -i "
 + "-f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'"
@@ -376,6 +377,12 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 % (ldconfig, target_root, target_root)
 )
 
+ret = os.waitstatus_to_exitcode(ret)
+if ret > 0:
+writemsg(f"!!! ldconfig failed with exit status {ret}\n", 
noiselevel=-1)
+if ret < 0:
+writemsg(f"!!! ldconfig was killed with signal {-ret}\n", 
noiselevel=-1)
+
 del specials["LDPATH"]
 
 notice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2023-07-26 Thread Sam James
commit: a777662890a7552927ee794506a92ddffc43523e
Author: Sam James  gentoo  org>
AuthorDate: Tue Jul 25 03:19:14 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Wed Jul 26 07:58:31 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a7776628

lib: env_update: use more f-strings

Signed-off-by: Sam James  gentoo.org>

 lib/portage/util/env_update.py | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index a7015669e..9d3b5bb25 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -361,19 +361,17 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 # an older package installed ON TOP of a newer version will cause 
ldconfig
 # to overwrite the symlinks we just made. -X means no links. After 
'clean'
 # we can safely create links.
-writemsg_level(
-_(">>> Regenerating %setc/ld.so.cache...\n") % (target_root,)
-)
+writemsg_level(_(f">>> Regenerating 
{target_root}etc/ld.so.cache...\n"))
 ret = subprocess.run(
-[f"{ldconfig}", "-X", "-r", f"{target_root}"], cwd="/"
+[ldconfig, "-X", "-r", target_root], cwd="/"
 ).returncode
 elif ostype in ("FreeBSD", "DragonFly"):
 writemsg_level(
-_(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % 
target_root
+_(f">>> Regenerating 
{target_root}var/run/ld-elf.so.hints...\n")
 )
 ret = subprocess.run(
 [
-f"{ldconfig}",
+ldconfig,
 "-elf",
 "-i",
 "-f",



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2023-07-26 Thread Sam James
commit: 3bba408e214ae27bdf924ba90ad4b0919a85f3c8
Author: Sam James  gentoo  org>
AuthorDate: Tue Jul 25 03:16:36 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Wed Jul 26 07:58:30 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3bba408e

lib: env_update: port to subprocess

os.system is a bit janky here, let's use subprocess so we're not injecting
multiple commands.

Thanks to mgorny for the suggestion.

Bug: https://bugs.gentoo.org/910376
Signed-off-by: Sam James  gentoo.org>

 lib/portage/util/env_update.py | 24 +++-
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index 5c2b2fdd5..a7015669e 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -6,7 +6,7 @@ __all__ = ["env_update"]
 import errno
 import glob
 import stat
-import sys
+import subprocess
 import time
 
 import portage
@@ -364,18 +364,24 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 writemsg_level(
 _(">>> Regenerating %setc/ld.so.cache...\n") % (target_root,)
 )
-ret = os.system(f"cd / ; {ldconfig} -X -r '{target_root}'")
+ret = subprocess.run(
+[f"{ldconfig}", "-X", "-r", f"{target_root}"], cwd="/"
+).returncode
 elif ostype in ("FreeBSD", "DragonFly"):
 writemsg_level(
 _(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % 
target_root
 )
-ret = os.system(
-(
-"cd / ; %s -elf -i "
-+ "-f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'"
-)
-% (ldconfig, target_root, target_root)
-)
+ret = subprocess.run(
+[
+f"{ldconfig}",
+"-elf",
+"-i",
+"-f",
+f"{target_root}var/run/ld-elf.so.hints",
+f"{target_root}etc/ld.so.conf",
+],
+cwd="/",
+).returncode
 
 ret = os.waitstatus_to_exitcode(ret)
 if ret > 0:



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2023-06-29 Thread Sam James
commit: f95d78c1636d081b906e613a0f26e2c318c80c5d
Author: Berin Aniesh  gmail  com>
AuthorDate: Sun Jun 18 04:53:01 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Thu Jun 29 08:19:28 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=f95d78c1

ExtractKernelVersion.py: Remove repeated/unreachable code

Signed-off-by: Berin Aniesh  gmail.com>
Signed-off-by: Sam James  gentoo.org>

 lib/portage/util/ExtractKernelVersion.py | 4 
 1 file changed, 4 deletions(-)

diff --git a/lib/portage/util/ExtractKernelVersion.py 
b/lib/portage/util/ExtractKernelVersion.py
index 5914dd020..6a6501b5d 100644
--- a/lib/portage/util/ExtractKernelVersion.py
+++ b/lib/portage/util/ExtractKernelVersion.py
@@ -31,16 +31,12 @@ def ExtractKernelVersion(base_dir):
 )
 except OSError as details:
 return (None, str(details))
-except OSError as details:
-return (None, str(details))
 
 try:
 for i in range(4):
 lines.append(f.readline())
 except OSError as details:
 return (None, str(details))
-except OSError as details:
-return (None, str(details))
 finally:
 f.close()
 



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/, lib/portage/tests/process/, lib/_emerge/, ...

2023-06-13 Thread Sam James
commit: efbc9c8d38b742a37968fc3b33d3dffdaf3be9f2
Author: Berin Aniesh  gmail  com>
AuthorDate: Fri Jun  9 02:00:45 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Wed Jun 14 01:44:02 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=efbc9c8d

Remove dummy_threading

Portage's MSV is python 3.7 and dummy threading is deprecated
since python 3.7. So everything dummy_threading is removed.

Signed-off-by: Berin Aniesh  gmail.com>
Closes: https://github.com/gentoo/portage/pull/1052
Signed-off-by: Sam James  gentoo.org>

 lib/_emerge/AsynchronousLock.py| 29 
 lib/_emerge/PollScheduler.py   |  7 ++---
 lib/portage/_emirrordist/MirrorDistTask.py |  6 +
 lib/portage/debug.py   |  8 ++
 lib/portage/locks.py   |  7 +++--
 lib/portage/proxy/lazyimport.py|  8 ++
 lib/portage/tests/locks/test_asynchronous_lock.py  | 31 --
 .../tests/process/test_PopenProcessBlockingIO.py   | 14 +-
 lib/portage/tests/util/futures/test_retry.py   |  7 ++---
 lib/portage/util/_async/PipeReaderBlockingIO.py|  8 ++
 lib/portage/util/futures/_asyncio/__init__.py  |  5 +---
 11 files changed, 34 insertions(+), 96 deletions(-)

diff --git a/lib/_emerge/AsynchronousLock.py b/lib/_emerge/AsynchronousLock.py
index 1a69d0847..c9c8e7f3c 100644
--- a/lib/_emerge/AsynchronousLock.py
+++ b/lib/_emerge/AsynchronousLock.py
@@ -1,19 +1,10 @@
-# Copyright 2010-2020 Gentoo Authors
+# Copyright 2010-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import fcntl
 import logging
 import sys
-
-try:
-import dummy_threading
-except ImportError:
-dummy_threading = None
-
-try:
-import threading
-except ImportError:
-threading = dummy_threading
+import threading
 
 import portage
 from portage import os
@@ -39,7 +30,6 @@ class AsynchronousLock(AsynchronousTask):
 __slots__ = ("path",) + (
 "_imp",
 "_force_async",
-"_force_dummy",
 "_force_process",
 "_force_thread",
 "_unlock_future",
@@ -61,14 +51,11 @@ class AsynchronousLock(AsynchronousTask):
 return
 
 if self._force_process or (
-not self._force_thread
-and (self._use_process_by_default or threading is dummy_threading)
+not self._force_thread and self._use_process_by_default
 ):
 self._imp = _LockProcess(path=self.path, scheduler=self.scheduler)
 else:
-self._imp = _LockThread(
-path=self.path, scheduler=self.scheduler, 
_force_dummy=self._force_dummy
-)
+self._imp = _LockThread(path=self.path, scheduler=self.scheduler)
 
 self._imp.addExitListener(self._imp_exit)
 self._imp.start()
@@ -115,19 +102,13 @@ class _LockThread(AbstractPollTask):
 using a background thread. After the lock is acquired, the thread
 writes to a pipe in order to notify a poll loop running in the main
 thread.
-
-If the threading module is unavailable then the dummy_threading
-module will be used, and the lock will be acquired synchronously
-(before the start() method returns).
 """
 
-__slots__ = ("path",) + ("_force_dummy", "_lock_obj", "_thread", 
"_unlock_future")
+__slots__ = ("path",) + ("_lock_obj", "_thread", "_unlock_future")
 
 def _start(self):
 self._registered = True
 threading_mod = threading
-if self._force_dummy:
-threading_mod = dummy_threading
 self._thread = threading_mod.Thread(target=self._run_lock)
 self._thread.daemon = True
 self._thread.start()

diff --git a/lib/_emerge/PollScheduler.py b/lib/_emerge/PollScheduler.py
index 73f2affde..e5dffd8af 100644
--- a/lib/_emerge/PollScheduler.py
+++ b/lib/_emerge/PollScheduler.py
@@ -1,10 +1,7 @@
-# Copyright 1999-2020 Gentoo Authors
+# Copyright 1999-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-try:
-import threading
-except ImportError:
-import dummy_threading as threading
+import threading
 
 from portage.util.futures import asyncio
 from portage.util._async.SchedulerInterface import SchedulerInterface

diff --git a/lib/portage/_emirrordist/MirrorDistTask.py 
b/lib/portage/_emirrordist/MirrorDistTask.py
index 5b2543c13..2925394a8 100644
--- a/lib/portage/_emirrordist/MirrorDistTask.py
+++ b/lib/portage/_emirrordist/MirrorDistTask.py
@@ -4,11 +4,7 @@
 import errno
 import logging
 import time
-
-try:
-import threading
-except ImportError:
-import dummy_threading as threading
+import threading
 
 import portage
 from portage import os

diff --git a/lib/portage/debug.py b/lib/portage/debug.py
index b7106b799..ee2dc13e7 100644
--- a/lib/portage/debug.py
+++ b/lib/portage/debug.py
@@ -1,13 +1,9 @@
-# Copyright 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2023-06-06 Thread Sam James
commit: 0911ea932d81020abe87774ff4819499c0cb891a
Author: Berin Aniesh  gmail  com>
AuthorDate: Tue Jun  6 06:16:35 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Tue Jun  6 06:52:40 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=0911ea93

portage.util.writemsg_level: Add return type type annotation

Signed-off-by: Berin Aniesh  gmail.com>
Closes: https://github.com/gentoo/portage/pull/1048
Signed-off-by: Sam James  gentoo.org>

 lib/portage/util/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/portage/util/__init__.py b/lib/portage/util/__init__.py
index f0115aea3..1f8c9e94f 100644
--- a/lib/portage/util/__init__.py
+++ b/lib/portage/util/__init__.py
@@ -130,7 +130,7 @@ def writemsg_stdout(mystr: str, noiselevel: int = 0) -> 
None:
 writemsg(mystr, noiselevel=noiselevel, fd=sys.stdout)
 
 
-def writemsg_level(msg: str, level: int = 0, noiselevel: int = 0):
+def writemsg_level(msg: str, level: int = 0, noiselevel: int = 0) -> None:
 """
 Show a message for the given level as defined by the logging module
 (default is 0).



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/_emerge/

2023-06-06 Thread Sam James
commit: 1ed0fd5f7c76f8c099a7f5978f1745e029e5e489
Author: Berin Aniesh  gmail  com>
AuthorDate: Tue Jun  6 05:54:33 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Tue Jun  6 06:52:40 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=1ed0fd5f

portage.util: Fix types and add add more details to docstring

Signed-off-by: Berin Aniesh  gmail.com>
Signed-off-by: Sam James  gentoo.org>

 lib/_emerge/main.py  |  7 ---
 lib/portage/util/__init__.py | 17 -
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/lib/_emerge/main.py b/lib/_emerge/main.py
index ec8d21b96..e471ac413 100644
--- a/lib/_emerge/main.py
+++ b/lib/_emerge/main.py
@@ -21,6 +21,7 @@ portage.proxy.lazyimport.lazyimport(
 from portage import os
 from portage.sync import _SUBMODULE_PATH_MAP
 
+from typing import Optional, List
 
 options = [
 "--alphabetical",
@@ -1161,12 +1162,12 @@ def profile_check(trees, myaction):
 return os.EX_OK
 
 
-def emerge_main(args=None):
+def emerge_main(args: Optional[List[str]] = None):
 """
 Entry point of emerge
 
-Processes command line arguments and decides what the current run of emerge
-should by creating `emerge_config`
+Processes command line arguments (default: sys.argv[1:]) and decides
+what the current run of emerge should by creating `emerge_config`
 """
 if args is None:
 args = sys.argv[1:]

diff --git a/lib/portage/util/__init__.py b/lib/portage/util/__init__.py
index e446a54f0..f0115aea3 100644
--- a/lib/portage/util/__init__.py
+++ b/lib/portage/util/__init__.py
@@ -72,7 +72,7 @@ import string
 import sys
 import traceback
 import glob
-from typing import Optional
+from typing import Optional, TextIO
 
 import portage
 
@@ -97,8 +97,15 @@ def initialize_logger(level=logging.WARNING) -> None:
 logging.basicConfig(level=level, format="[%(levelname)-4s] %(message)s")
 
 
-def writemsg(mystr: str, noiselevel: int = 0, fd=None) -> None:
-"""Prints out warning and debug messages based on the noiselimit setting"""
+def writemsg(mystr: str, noiselevel: int = 0, fd: Optional[TextIO] = None) -> 
None:
+"""
+Prints out warning and debug messages based on the noiselimit setting
+
+Takes three arguments
+1. mystr: The message to write
+2. noiselevel: The noiselevel of the message
+3. fd: file descriptor - where to write the message to
+"""
 global noiselimit
 if fd is None:
 fd = sys.stderr
@@ -126,8 +133,8 @@ def writemsg_stdout(mystr: str, noiselevel: int = 0) -> 
None:
 def writemsg_level(msg: str, level: int = 0, noiselevel: int = 0):
 """
 Show a message for the given level as defined by the logging module
-(default is 0). 
-
+(default is 0).
+
 When level >= logging.WARNING then the message is
 sent to stderr, otherwise it is sent to stdout. The noiselevel is
 passed directly to writemsg().



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, /, lib/_emerge/

2023-06-06 Thread Sam James
commit: 15fefd7e2e9b400a8a48d59badad632fe290aa5a
Author: Berin Aniesh  gmail  com>
AuthorDate: Mon Jun  5 14:06:24 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Tue Jun  6 06:52:40 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=15fefd7e

main.py, portage.util: Add docstrings and type annotations

Signed-off-by: Berin Aniesh  gmail.com>
Signed-off-by: Sam James  gentoo.org>

 .gitignore   |  4 
 lib/_emerge/main.py  |  6 --
 lib/portage/util/__init__.py | 25 -
 3 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7c6acadbe..03ae933b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,7 @@ __pycache__/
 setup.cfg
 .*.swp
 *.vim
+.mypy_cache
+dist
+*.egg-info/
+MANIFEST

diff --git a/lib/_emerge/main.py b/lib/_emerge/main.py
index 850487d36..ec8d21b96 100644
--- a/lib/_emerge/main.py
+++ b/lib/_emerge/main.py
@@ -1163,8 +1163,10 @@ def profile_check(trees, myaction):
 
 def emerge_main(args=None):
 """
-@param args: command arguments (default: sys.argv[1:])
-@type args: list
+Entry point of emerge
+
+Processes command line arguments and decides what the current run of emerge
+should by creating `emerge_config`
 """
 if args is None:
 args = sys.argv[1:]

diff --git a/lib/portage/util/__init__.py b/lib/portage/util/__init__.py
index 31aba6702..e446a54f0 100644
--- a/lib/portage/util/__init__.py
+++ b/lib/portage/util/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2004-2020 Gentoo Authors
+# Copyright 2004-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from portage.cache.mappings import UserDict
@@ -87,7 +87,7 @@ portage.proxy.lazyimport.lazyimport(
 noiselimit = 0
 
 
-def initialize_logger(level=logging.WARNING):
+def initialize_logger(level=logging.WARNING) -> None:
 """Sets up basic logging of portage activities
 Args:
 level: the level to emit messages at ('info', 'debug', 'warning' 
...)
@@ -97,7 +97,7 @@ def initialize_logger(level=logging.WARNING):
 logging.basicConfig(level=level, format="[%(levelname)-4s] %(message)s")
 
 
-def writemsg(mystr, noiselevel=0, fd=None):
+def writemsg(mystr: str, noiselevel: int = 0, fd=None) -> None:
 """Prints out warning and debug messages based on the noiselimit setting"""
 global noiselimit
 if fd is None:
@@ -118,24 +118,23 @@ def writemsg(mystr, noiselevel=0, fd=None):
 fd.flush()
 
 
-def writemsg_stdout(mystr, noiselevel=0):
+def writemsg_stdout(mystr: str, noiselevel: int = 0) -> None:
 """Prints messages stdout based on the noiselimit setting"""
 writemsg(mystr, noiselevel=noiselevel, fd=sys.stdout)
 
 
-def writemsg_level(msg, level=0, noiselevel=0):
+def writemsg_level(msg: str, level: int = 0, noiselevel: int = 0):
 """
 Show a message for the given level as defined by the logging module
-(default is 0). When level >= logging.WARNING then the message is
+(default is 0). 
+
+When level >= logging.WARNING then the message is
 sent to stderr, otherwise it is sent to stdout. The noiselevel is
 passed directly to writemsg().
-
-@type msg: str
-@param msg: a message string, including newline if appropriate
-@type level: int
-@param level: a numeric logging level (see the logging module)
-@type noiselevel: int
-@param noiselevel: passed directly to writemsg
+Takes three parameters
+1. msg  - the message to output
+2. level - the numeric logging level (see python's logging module)
+3. noiselevel - portage's logging level, passed directly to writemsg
 """
 if level >= logging.WARNING:
 fd = sys.stderr



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/dbapi/

2023-05-22 Thread Sam James
commit: 5572b73744121f67c4e55040966bfe91a0e5fb6c
Author: gcarq  protonmail  com>
AuthorDate: Tue Mar 21 16:19:13 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Tue May 23 00:22:09 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=5572b737

mergeme: Consider file mode and xattr for comparison

Implements dblink._needs_move(...) to take care of file equality
checks which consist of file mode, extended attributes and
file content.

Signed-off-by: gcarq  protonmail.com>
Signed-off-by: Sam James  gentoo.org>

 lib/portage/dbapi/vartree.py | 32 +---
 lib/portage/util/movefile.py | 29 +
 2 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/lib/portage/dbapi/vartree.py b/lib/portage/dbapi/vartree.py
index 327b72bed..317cf327a 100644
--- a/lib/portage/dbapi/vartree.py
+++ b/lib/portage/dbapi/vartree.py
@@ -3,8 +3,6 @@
 
 __all__ = ["vardbapi", "vartree", "dblink"] + ["write_contents", 
"tar_contents"]
 
-import filecmp
-
 import portage
 
 portage.proxy.lazyimport.lazyimport(
@@ -34,7 +32,7 @@ portage.proxy.lazyimport.lazyimport(
 "portage.util.env_update:env_update",
 "portage.util.install_mask:install_mask_dir,InstallMask,_raise_exc",
 "portage.util.listdir:dircache,listdir",
-"portage.util.movefile:movefile",
+"portage.util.movefile:movefile,_cmpxattr",
 "portage.util.path:first_existing,iter_parents",
 "portage.util.writeable_check:get_ro_checker",
 "portage.util._xattr:xattr",
@@ -95,6 +93,7 @@ from ._ContentsCaseSensitivityManager import 
ContentsCaseSensitivityManager
 
 import argparse
 import errno
+import filecmp
 import fnmatch
 import functools
 import gc
@@ -5803,10 +5802,7 @@ class dblink:
 # same way.  Unless moveme=0 (blocking directory)
 if moveme:
 # only replace the existing file if it differs, see #722270
-already_merged = os.path.exists(mydest)
-if already_merged and filecmp.cmp(mysrc, mydest, 
shallow=False):
-zing = "==="
-else:
+if self._needs_move(mysrc, mydest, mymode, mydmode):
 # Create hardlinks only for source files that already 
exist
 # as hardlinks (having identical st_dev and st_ino).
 hardlink_key = (mystat.st_dev, mystat.st_ino)
@@ -5829,6 +5825,8 @@ class dblink:
 return 1
 hardlink_candidates.append(mydest)
 zing = ">>>"
+else:
+zing = "==="
 
 try:
 self._merged_path(mydest, os.lstat(mydest))
@@ -6254,6 +6252,26 @@ class dblink:
 finally:
 self.unlockdb()
 
+def _needs_move(self, mysrc, mydest, mymode, mydmode):
+"""
+Checks whether the given file at |mysrc| needs to be moved to |mydest| 
or if
+they are identical.
+
+Takes file mode and extended attributes into account.
+Should only be used for regular files.
+"""
+if not os.path.exists(mydest):
+return True
+
+if mymode != mydmode:
+return True
+
+excluded_xattrs = self.settings.get("PORTAGE_XATTR_EXCLUDE", "")
+if not _cmpxattr(mysrc, mydest, exclude=excluded_xattrs):
+return True
+
+return not filecmp.cmp(mysrc, mydest, shallow=False)
+
 
 def merge(
 mycat,

diff --git a/lib/portage/util/movefile.py b/lib/portage/util/movefile.py
index d46c56ade..e2f19ba92 100644
--- a/lib/portage/util/movefile.py
+++ b/lib/portage/util/movefile.py
@@ -105,6 +105,35 @@ def _copyxattr(src, dest, exclude=None):
 )
 
 
+def _cmpxattr(src, dest, exclude=None):
+"""
+Compares extended attributes between |src| and |dest| and returns True
+if they are equal or xattrs are not supported, False otherwise
+"""
+try:
+src_attrs = xattr.list(src)
+dest_attrs = xattr.list(dest)
+except OSError as e:
+if e.errno != OperationNotSupported.errno:
+raise
+return True
+
+if src_attrs:
+if exclude is not None and isinstance(src_attrs[0], bytes):
+exclude = exclude.encode(_encodings["fs"])
+exclude = _get_xattr_excluder(exclude)
+
+src_attrs = {attr for attr in src_attrs if not exclude(attr)}
+dest_attrs = {attr for attr in dest_attrs if not exclude(attr)}
+if src_attrs != dest_attrs:
+return False
+
+for attr in src_attrs:
+if xattr.get(src, attr) != xattr.get(dest, attr):
+return False
+return True
+
+
 def movefile(
 src,
 dest,



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2022-12-31 Thread Sam James
commit: 118df436abd49eecfeaf95df8a052861d463a896
Author: Michał Górny  gentoo  org>
AuthorDate: Fri Dec 30 10:57:12 2022 +
Commit: Sam James  gentoo  org>
CommitDate: Sat Dec 31 13:33:04 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=118df436

Report a warning when unaccelerated Whirlpool is being used

The warning serves two purposes: it informs the user that they should
expect very slow hashing (i.e. Portage did not hang) and that they
should inform the repository owner about the problem. Far from ideal
but probably good enough given how rare Whirlpool-only ebuilds are.

Signed-off-by: Michał Górny  gentoo.org>
Closes: https://github.com/gentoo/portage/pull/967
Signed-off-by: Sam James  gentoo.org>

 lib/portage/util/whirlpool.py | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/lib/portage/util/whirlpool.py b/lib/portage/util/whirlpool.py
index 8454a874a..d26780604 100644
--- a/lib/portage/util/whirlpool.py
+++ b/lib/portage/util/whirlpool.py
@@ -30,6 +30,10 @@
 
 # pylint: disable=mixed-indentation
 
+import warnings
+
+from portage.localization import _
+
 try:
 from ._whirlpool import Whirlpool as WhirlpoolExt
 except ImportError:
@@ -47,6 +51,13 @@ class PyWhirlpool:
 hashed."""
 
 def __init__(self, arg=b""):
+warnings.warn(
+_(
+"The last-resort unaccelerated Whirlpool implementation is "
+"being used. It is known to be absurdly slow. Please report "
+"that the Whirlpool hash is deprecated to the repository 
owner."
+)
+)
 self.ctx = WhirlpoolStruct()
 self.update(arg)
 



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/tests/util/

2022-12-31 Thread Sam James
commit: 98f984875251f86d3a5c367765c7d6e249277a26
Author: Michał Górny  gentoo  org>
AuthorDate: Fri Dec 30 10:44:10 2022 +
Commit: Sam James  gentoo  org>
CommitDate: Sat Dec 31 13:33:04 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=98f98487

Test C whirlpool implementation separately from Python impl

Signed-off-by: Michał Górny  gentoo.org>
Signed-off-by: Sam James  gentoo.org>

 lib/portage/tests/util/test_whirlpool.py | 17 +++--
 lib/portage/util/whirlpool.py|  2 ++
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/lib/portage/tests/util/test_whirlpool.py 
b/lib/portage/tests/util/test_whirlpool.py
index d93467b21..ac156abf3 100644
--- a/lib/portage/tests/util/test_whirlpool.py
+++ b/lib/portage/tests/util/test_whirlpool.py
@@ -2,26 +2,31 @@
 # Distributed under the terms of the GNU General Public License v2
 
 from portage.tests import TestCase
-from portage.util.whirlpool import Whirlpool
+from portage.util.whirlpool import CWhirlpool, PyWhirlpool
 
 
 class WhirlpoolTestCase(TestCase):
-def testBundledWhirlpool(self):
+def testBundledWhirlpool(self, cls=PyWhirlpool):
 self.assertEqual(
-Whirlpool(b"The quick brown fox jumps over the lazy 
dog").hexdigest(),
+cls(b"The quick brown fox jumps over the lazy dog").hexdigest(),
 
"b97de512e91e3828b40d2b0fdce9ceb3c4a71f9bea8d88e75c4fa854df36725fd2b52eb6544edcacd6f8beddfea403cb55ae31f03ad62a5ef54e42ee82c3fb35",
 )
 self.assertEqual(
-Whirlpool(b"The quick brown fox jumps over the lazy 
eog").hexdigest(),
+cls(b"The quick brown fox jumps over the lazy eog").hexdigest(),
 
"c27ba124205f72e6847f3e19834f925cc666d0974167af915bb462420ed40cc50900d85a1f923219d832357750492d5c143011a76988344c2635e69d06f2d38c",
 )
 self.assertEqual(
-Whirlpool(b"").hexdigest(),
+cls(b"").hexdigest(),
 
"19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3",
 )
-w = Whirlpool()
+w = cls()
 w.update(b"")
 self.assertEqual(
 w.hexdigest(),
 
"19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3",
 )
+
+def testCWhirlpool(self):
+if not CWhirlpool.is_available:
+self.skipTest("C Whirlpool extension is not importable")
+self.testBundledWhirlpool(CWhirlpool)

diff --git a/lib/portage/util/whirlpool.py b/lib/portage/util/whirlpool.py
index 1431c18fb..7caa20f6e 100644
--- a/lib/portage/util/whirlpool.py
+++ b/lib/portage/util/whirlpool.py
@@ -83,6 +83,8 @@ class CWhirlpool:
 may be provided; if present, this string will be automatically
 hashed."""
 
+is_available = WhirlpoolExt is not None
+
 def __init__(self, arg=b""):
 self.obj = WhirlpoolExt()
 self.dig = None



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, /, src/

2022-12-29 Thread Sam James
commit: 45f2da735a473d8b800861f97d7be1ba7850187f
Author: Michał Górny  gentoo  org>
AuthorDate: Thu Dec 29 17:04:24 2022 +
Commit: Sam James  gentoo  org>
CommitDate: Thu Dec 29 19:34:36 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=45f2da73

portage.util: Add C implementation of Whirlpool hash

Add an extension module providing Whirlpool hash based on the reference
C implementation.  This is necessary since Python hashlib no longer
provides Whirlpool by default with OpenSSL 3, and the Python
implementation used by Portage is unusably slow.

Signed-off-by: Michał Górny  gentoo.org>
Closes: https://github.com/gentoo/portage/pull/966
Signed-off-by: Sam James  gentoo.org>

 lib/portage/util/whirlpool.py |   44 +-
 setup.py  |3 +
 src/portage_util__whirlpool.c | 1141 +
 3 files changed, 1187 insertions(+), 1 deletion(-)

diff --git a/lib/portage/util/whirlpool.py b/lib/portage/util/whirlpool.py
index e478922ef..b62191d91 100644
--- a/lib/portage/util/whirlpool.py
+++ b/lib/portage/util/whirlpool.py
@@ -27,12 +27,18 @@
 
 # pylint: disable=mixed-indentation
 
+try:
+from ._whirlpool import Whirlpool as WhirlpoolExt
+except ImportError:
+WhirlpoolExt = None
+
+
 # block_size = 64
 digest_size = 64
 digestsize = 64
 
 
-class Whirlpool:
+class PyWhirlpool:
 """Return a new Whirlpool object. An optional string argument
 may be provided; if present, this string will be automatically
 hashed."""
@@ -69,6 +75,42 @@ class Whirlpool:
 return copy.deepcopy(self)
 
 
+class CWhirlpool:
+"""Return a new Whirlpool object. An optional string argument
+may be provided; if present, this string will be automatically
+hashed."""
+
+def __init__(self, arg=b""):
+self.obj = WhirlpoolExt()
+self.dig = None
+self.update(arg)
+
+def update(self, arg):
+if self.dig is not None:
+raise RuntimeError("Whirlpool object already finalized")
+self.obj.update(arg)
+
+def digest(self):
+if self.dig is None:
+self.dig = self.obj.digest()
+return self.dig
+
+def hexdigest(self):
+"""hexdigest()"""
+dig = self.digest()
+tempstr = ""
+for d in dig:
+xxx = "%02x" % (d,)
+tempstr = tempstr + xxx
+return tempstr
+
+
+if WhirlpoolExt is not None:
+Whirlpool = CWhirlpool
+else:
+Whirlpool = PyWhirlpool
+
+
 def new(init=b""):
 """Return a new Whirlpool object. An optional string argument
 may be provided; if present, this string will be automatically

diff --git a/setup.py b/setup.py
index 9f189cc6f..e6d64874b 100755
--- a/setup.py
+++ b/setup.py
@@ -86,6 +86,9 @@ x_c_helpers = {
 "portage.util.libc": [
 "src/portage_util_libc.c",
 ],
+"portage.util._whirlpool": [
+"src/portage_util__whirlpool.c",
+],
 }
 
 if platform.system() == "Linux":

diff --git a/src/portage_util__whirlpool.c b/src/portage_util__whirlpool.c
new file mode 100644
index 0..6c9421e56
--- /dev/null
+++ b/src/portage_util__whirlpool.c
@@ -0,0 +1,1141 @@
+/* Copyright 2022 Gentoo Authors
+ * Distributed under the terms of the GNU General Public License v2
+ */
+
+/**
+ * Based on the reference implementation
+ * by: Paulo S.L.M. Barreto and Vincent Rijmen.
+ *
+ * The reference implementation has been placed in public domain, with
+ * the following disclaimer:
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define PY_SSIZE_T_CLEAN
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+typedef uint8_t u8;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+#define DIGESTBYTES 64
+#define DIGESTBITS  (8*DIGESTBYTES) /* 512 */
+
+#define WBLOCKBYTES 64
+#define WBLOCKBITS  (8*WBLOCKBYTES) /* 512 */
+
+#define LENGTHBYTES 32
+#define LENGTHBITS  (8*LENGTHBYTES) /* 256 */
+
+typedef struct NESSIEstruct {
+   u8  bitLength[LENGTHBYTES]; /* global number of hashed bits (256-bit 
counter) */
+   u8  buffer[WBLOCKBYTES];/* buffer of data to hash */
+   int bufferBits; /* current number of bits on the buffer 
*/
+   int bufferPos;  /* current 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/, /

2022-11-30 Thread Sam James
commit: f99ddf5659d143dd876ab05c5ff2ce425ffde672
Author: Florian Schmaus  gentoo  org>
AuthorDate: Sun Nov 27 19:12:53 2022 +
Commit: Sam James  gentoo  org>
CommitDate: Wed Nov 30 22:28:58 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=f99ddf56

Revert "env-update: skip PATH in systemd user environment definition"

This reverts commit 21739ea1e0a793e207b7ae28d524e45582d9b2ca, as it
was appearantly not necessary. Not sure what drove me into believing
that this was needed…

Thanks to Arsen for pointing this out.

Closes: https://bugs.gentoo.org/883307
Reported-by: Arsen Arsenović  aarsen.me>
Signed-off-by: Florian Schmaus  gentoo.org>
Closes: https://github.com/gentoo/portage/pull/949
Signed-off-by: Sam James  gentoo.org>

 NEWS   | 3 +++
 lib/portage/util/env_update.py | 5 -
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/NEWS b/NEWS
index 6fd185fcb..57d9c92ee 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,9 @@ Bug fixes:
   in different ways, but one example was a rebuild in / causing the same 
package
   to be added to ROOT, even when it had no other reason to be.
 
+* env-update: Also generate PATH definition in systemd user environment file
+  /etc/environment.d/10-gentoo-env.conf
+
 portage-3.0.39 (2022-11-20)
 --
 

diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index bb0ebf84c..bac5b6e7a 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -417,11 +417,6 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env, writemsg_lev
 systemd_gentoo_env.write(senvnotice)
 
 for env_key in env_keys:
-# Skip PATH since this makes it impossible to use
-# "systemctl --user import-environment PATH".
-if env_key == "PATH":
-continue
-
 env_key_value = env[env_key]
 
 # Skip variables with the empty string



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, bin/ebuild-helpers/, bin/

2022-10-17 Thread Sam James
commit: 800e09a4a1a630548ea8316e5c906c6f48af3105
Author: Sam James  gentoo  org>
AuthorDate: Tue Oct 18 00:11:24 2022 +
Commit: Sam James  gentoo  org>
CommitDate: Tue Oct 18 00:14:25 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=800e09a4

info: support more info compression suffixes

Bug: https://bugs.gentoo.org/757525
Signed-off-by: Sam James  gentoo.org>

 bin/ebuild-helpers/prepinfo | 6 +++---
 bin/misc-functions.sh   | 2 +-
 lib/portage/util/_info_files.py | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/bin/ebuild-helpers/prepinfo b/bin/ebuild-helpers/prepinfo
index 9e509e8ca..4d200d0d3 100755
--- a/bin/ebuild-helpers/prepinfo
+++ b/bin/ebuild-helpers/prepinfo
@@ -1,10 +1,10 @@
 #!/usr/bin/env bash
-# Copyright 1999-2018 Gentoo Foundation
+# Copyright 1999-2022 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1
 
-if ! ___eapi_has_prefix_variables; then
+if ! ___eapi_has_prefix_variables ; then
ED=${D}
 fi
 
@@ -32,7 +32,7 @@ find "${ED%/}/${infodir#/}" -type d -print0 | while read -r 
-d $'\0' x ; do
[[ -e ${f} ]] && continue 2
done
 
-   rm -f "${x}"/dir{,.info}{,.gz,.bz2}
+   rm -f "${x}"/dir{,.info}{,.gz,.bz2,.xz,.lz,.zst,.lzma,.lz4}
 done
 
 exit 0

diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
index 170e60d1c..2fa61cf37 100755
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
@@ -253,7 +253,7 @@ install_qa_check() {
fi
 
# Portage regenerates this on the installed system.
-   rm -f "${ED%/}"/usr/share/info/dir{,.gz,.bz2} || die "rm failed!"
+   rm -f "${ED%/}"/usr/share/info/dir{,.gz,.bz2,.xz,.lz,.zst,.lzma,.lz4} 
|| die "rm failed!"
 }
 
 __dyn_instprep() {

diff --git a/lib/portage/util/_info_files.py b/lib/portage/util/_info_files.py
index 528b273d9..4cea4f657 100644
--- a/lib/portage/util/_info_files.py
+++ b/lib/portage/util/_info_files.py
@@ -36,7 +36,7 @@ def chk_updated_info_files(root, infodirs, prev_mtimes):
 if portage.util.noiselimit >= 0:
 out.einfo("Regenerating GNU info directory index...")
 
-dir_extensions = ("", ".gz", ".bz2")
+dir_extensions = ("", ".gz", ".bz2", ".xz", ".lz", ".lz4", ".zst", 
".lzma")
 icount = 0
 badcount = 0
 errmsg = ""



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, bin/

2022-10-17 Thread Sam James
commit: 6a47cc7bcf49b7c17fdca31969b6d6aeff84332c
Author: Sam James  gentoo  org>
AuthorDate: Mon Oct 17 18:37:03 2022 +
Commit: Sam James  gentoo  org>
CommitDate: Mon Oct 17 18:37:54 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=6a47cc7b

xz: add workaround for < xz 5.3.3_alpha 32-bit issue

With older versions of xz, xz -T0 will on 32-bit systems
try to allocate too much memory and bail out.

After discussing with upstream, we set --memlimit-compress=50% as a
way to make things work with both older & newer versions. This limiting
is essentially already present with >= 5.3.3_alpha as -T0 includes it.

Note that we don't need to do this for decompression as it's automatic
there for newer versions and older versions -Tn a no-op.

Signed-off-by: Sam James  gentoo.org>

 bin/ecompress | 2 +-
 lib/portage/util/compression_probe.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bin/ecompress b/bin/ecompress
index 977f8d7b4..e78d6931f 100755
--- a/bin/ecompress
+++ b/bin/ecompress
@@ -128,7 +128,7 @@ if [[ ${PORTAGE_COMPRESS_FLAGS+set} != "set" ]] ; then
# See: https://bugs.gentoo.org/672916
# Setting '--rm' will remove the source files after a 
successful compression.
lz4)  PORTAGE_COMPRESS_FLAGS="-m --rm";;
-   xz)   PORTAGE_COMPRESS_FLAGS="-9 -T$(___makeopts_jobs)";;
+   xz)   PORTAGE_COMPRESS_FLAGS="-9 -T$(___makeopts_jobs) 
--memlimit-compress=50%";;
zstd) PORTAGE_COMPRESS_FLAGS="-q --rm -T$(___makeopts_jobs)";;
esac
 fi

diff --git a/lib/portage/util/compression_probe.py 
b/lib/portage/util/compression_probe.py
index bbff5a3c6..ddd8cf9ad 100644
--- a/lib/portage/util/compression_probe.py
+++ b/lib/portage/util/compression_probe.py
@@ -37,7 +37,7 @@ _compressors = {
 "package": "app-arch/lzop",
 },
 "xz": {
-"compress": "xz -T{JOBS} ${BINPKG_COMPRESS_FLAGS}",
+"compress": "xz -T{JOBS} --memlimit-compress=50% 
${BINPKG_COMPRESS_FLAGS}",
 "decompress": "xz -T{JOBS} -d",
 "package": "app-arch/xz-utils",
 },



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/tests/util/

2022-06-07 Thread Mike Gilbert
commit: e22cf80ec99c52c1192ecf99f6b66d1d892f3f86
Author: David Palao  gmail  com>
AuthorDate: Fri Jun  3 09:13:17 2022 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Tue Jun  7 23:47:56 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=e22cf80e

improvement(pylint/black): some formatting issues fixed

Signed-off-by: David Palao  gmail.com>
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/tests/util/test_mtimedb.py | 126 ++---
 lib/portage/util/mtimedb.py|  14 ++--
 2 files changed, 59 insertions(+), 81 deletions(-)

diff --git a/lib/portage/tests/util/test_mtimedb.py 
b/lib/portage/tests/util/test_mtimedb.py
index 09d72049f..d80b4f1da 100644
--- a/lib/portage/tests/util/test_mtimedb.py
+++ b/lib/portage/tests/util/test_mtimedb.py
@@ -9,7 +9,6 @@ from portage.tests import TestCase
 import portage
 from portage.data import portage_gid, uid
 from portage.util.mtimedb import MtimeDB, _MTIMEDBKEYS
-from portage.exception import DigestException
 
 
 # Some data for the fixtures:
@@ -210,15 +209,12 @@ class MtimeDBTestCase(TestCase):
 _TWO_RESUME_LISTS_JSON,
 )
 for contents in all_fixtures:
-with patch(
-"portage.util.mtimedb.open", mock_open(read_data=contents)
-):
+with patch("portage.util.mtimedb.open", 
mock_open(read_data=contents)):
 mtimedb = MtimeDB("/path/to/mtimedb")
 self.assertLessEqual(set(mtimedb.keys()), _MTIMEDBKEYS)
 
 def test_default_values(self):
-with patch("portage.util.mtimedb.open",
-   mock_open(read_data=_EMPTY_FILE)):
+with patch("portage.util.mtimedb.open", 
mock_open(read_data=_EMPTY_FILE)):
 mtimedb = MtimeDB("/some/path/mtimedb")
 self.assertEqual(mtimedb["starttime"], 0)
 self.assertEqual(mtimedb["version"], "")
@@ -227,88 +223,75 @@ class MtimeDBTestCase(TestCase):
 self.assertEqual(mtimedb["updates"], {})
 
 def test_instances_keep_a_deepcopy_of_clean_data(self):
-with patch("portage.util.mtimedb.open",
-   mock_open(read_data=_ONE_RESUME_LIST_JSON)):
+with patch(
+"portage.util.mtimedb.open", 
mock_open(read_data=_ONE_RESUME_LIST_JSON)
+):
 mtimedb = MtimeDB("/some/path/mtimedb")
 self.assertEqual(dict(mtimedb), dict(mtimedb._clean_data))
 self.assertIsNot(mtimedb, mtimedb._clean_data)
 
 def test_load_data_called_at_instance_creation_time(self):
-with patch("portage.util.mtimedb.open",
-   mock_open(read_data=_ONE_RESUME_LIST_JSON)):
+with patch(
+"portage.util.mtimedb.open", 
mock_open(read_data=_ONE_RESUME_LIST_JSON)
+):
 mtimedb = MtimeDB("/some/path/mtimedb")
 self.assertEqual(
 mtimedb["info"],
 {
-   "/usr/share/binutils-data/x86_64-pc-linux-gnu/2.37/info": (
-1711787325),
-   "/usr/share/gcc-data/x86_64-pc-linux-gnu/11.2.0/info": (
-1735158257),
-   "/usr/share/info": 1650633847
-   }
+"/usr/share/binutils-data/x86_64-pc-linux-gnu/2.37/info": 
(1711787325),
+"/usr/share/gcc-data/x86_64-pc-linux-gnu/11.2.0/info": 
(1735158257),
+"/usr/share/info": 1650633847,
+},
 )
 self.assertEqual(
 mtimedb["ldpath"],
 {
-   "/lib": 1748456830,
-   "/lib64": 1750523381,
-   "/usr/lib": 1750461195,
-   "/usr/lib/llvm/13/lib64": 1747003135,
-   "/usr/lib/rust/lib": 1750461173,
-   "/usr/lib64": 1750881821,
-   "/usr/local/lib": 1711784303,
-   "/usr/local/lib64": 1711784303
-   }
+"/lib": 1748456830,
+"/lib64": 1750523381,
+"/usr/lib": 1750461195,
+"/usr/lib/llvm/13/lib64": 1747003135,
+"/usr/lib/rust/lib": 1750461173,
+"/usr/lib64": 1750881821,
+"/usr/local/lib": 1711784303,
+"/usr/local/lib64": 1711784303,
+},
 )
 self.assertEqual(
 mtimedb["resume"],
 {
-   "favorites": [
-   "@world"
-   ],
-   "mergelist": [
-   [
-   "ebuild",
-   "/",
-   "some-cat/some-package-1.2.3-r4",
-   "merge"
-   ],
-   [
-   "ebuild",
-   "/",
-   "another-cat/another-package-4.3.2-r1",
-   "merge"
-   ]
-   ],
-   

[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/tests/util/

2022-06-07 Thread Mike Gilbert
commit: 4540f2b0a6529705343f493abb478370c15f101f
Author: David Palao  gmail  com>
AuthorDate: Mon May 30 07:00:32 2022 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Tue Jun  7 23:47:55 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=4540f2b0

improvement(mtimedb): class has better API

New attribute ``is_readonly`` and  new method ``make_readonly`` added.

Signed-off-by: David Palao  gmail.com>
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/tests/util/test_mtimedb.py | 28 +---
 lib/portage/util/mtimedb.py| 10 ++
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/lib/portage/tests/util/test_mtimedb.py 
b/lib/portage/tests/util/test_mtimedb.py
index a65a6be91..ecc0e7135 100644
--- a/lib/portage/tests/util/test_mtimedb.py
+++ b/lib/portage/tests/util/test_mtimedb.py
@@ -9,6 +9,8 @@ from portage.util.mtimedb import MtimeDB, _MTIMEDBKEYS
 from portage.exception import DigestException
 
 
+# Some random data for the fixtures:
+
 _ONE_RESUME_LIST_JSON = b"""{
"info": {

"/tmp/stage1root/usr/share/binutils-data/x86_64-pc-linux-gnu/2.34/info": 
1711785090,
@@ -213,7 +215,7 @@ _TWO_RESUME_LISTS_JSON = b"""{
 class MtimeDBTestCase(TestCase):
 text = b"Unit tests for MtimeDB"
 
-def test_instance_created_with_only_expected_keys(self):
+def test_instances_are_created_with_only_expected_keys(self):
 all_fixtures = (
 _ONE_RESUME_LIST_JSON,
 _EMPTY_FILE,
@@ -227,7 +229,7 @@ class MtimeDBTestCase(TestCase):
 mtimedb = MtimeDB("/path/to/mtimedb")
 self.assertLessEqual(set(mtimedb.keys()), _MTIMEDBKEYS)
 
-def test_instance_has_default_values(self):
+def test_instances_have_default_values(self):
 with patch("portage.util.mtimedb.open",
mock_open(read_data=_EMPTY_FILE)):
 mtimedb = MtimeDB("/some/path/mtimedb")
@@ -237,7 +239,7 @@ class MtimeDBTestCase(TestCase):
 self.assertEqual(mtimedb["ldpath"], {})
 self.assertEqual(mtimedb["updates"], {})
 
-def test_instance_has_a_deepcopy_of_clean_data(self):
+def test_instances_keep_a_deepcopy_of_clean_data(self):
 with patch("portage.util.mtimedb.open",
mock_open(read_data=_ONE_RESUME_LIST_JSON)):
 mtimedb = MtimeDB("/some/path/mtimedb")
@@ -274,3 +276,23 @@ class MtimeDBTestCase(TestCase):
 mtimedb = MtimeDB("/some/path/mtimedb")
 mtimedb.commit()
 pwrite2disk.assert_not_called()
+
+def test_is_readonly_attribute(self):
+with patch("portage.util.mtimedb.open",
+   mock_open(read_data=_ONE_RESUME_LIST_JSON)):
+mtimedb = MtimeDB("/some/path/mtimedb")
+self.assertFalse(mtimedb.is_readonly)
+
+mtimedb.filename = None
+self.assertTrue(mtimedb.is_readonly)
+
+mtimedb.filename = "/what/ever/mtimedb"
+self.assertFalse(mtimedb.is_readonly)
+
+def test_make_readonly(self):
+with patch("portage.util.mtimedb.open",
+   mock_open(read_data=_ONE_RESUME_LIST_JSON)):
+mtimedb = MtimeDB("/some/path/mtimedb")
+mtimedb.make_readonly()
+self.assertTrue(mtimedb.is_readonly)
+self.assertIs(mtimedb.filename, None)

diff --git a/lib/portage/util/mtimedb.py b/lib/portage/util/mtimedb.py
index a6566e3f8..95da2235f 100644
--- a/lib/portage/util/mtimedb.py
+++ b/lib/portage/util/mtimedb.py
@@ -51,6 +51,16 @@ class MtimeDB(dict):
 self.filename = filename
 self._load(filename)
 
+@property
+def is_readonly(self):
+if self.filename is None:
+return True
+else:
+return False
+
+def make_readonly(self):
+self.filename = None
+
 def _load(self, filename):
 f = None
 content = None



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2022-06-07 Thread Mike Gilbert
commit: f4fd289c7e3cbbd1a17a1510b1b126d314eea053
Author: David Palao  gmail  com>
AuthorDate: Tue May 31 15:52:56 2022 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Tue Jun  7 23:47:56 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=f4fd289c

improvement(mtimedb): using is_readonly instead "if not self.filename"

Signed-off-by: David Palao  gmail.com>
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/util/mtimedb.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/portage/util/mtimedb.py b/lib/portage/util/mtimedb.py
index 9884746f3..497c01e05 100644
--- a/lib/portage/util/mtimedb.py
+++ b/lib/portage/util/mtimedb.py
@@ -124,7 +124,7 @@ class MtimeDB(dict):
 self._clean_data = copy.deepcopy(d)
 
 def commit(self):
-if not self.filename:
+if self.is_readonly:
 return
 d = {}
 d.update(self)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/tests/util/

2022-06-07 Thread Mike Gilbert
commit: c79c8898dc4ccd85829d00e7104b8e69ae8aa7f4
Author: David Palao  gmail  com>
AuthorDate: Wed May 25 15:23:20 2022 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Tue Jun  7 23:47:55 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=c79c8898

refactor(mtimedb): MtimeDB.commit splitted into two methods

- commit itself handles only the logic of when to write to disk
- __write_to_disk performs the actual writing

Signed-off-by: David Palao  gmail.com>
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/tests/util/test_mtimedb.py | 37 +++---
 lib/portage/util/mtimedb.py| 41 ++
 2 files changed, 56 insertions(+), 22 deletions(-)

diff --git a/lib/portage/tests/util/test_mtimedb.py 
b/lib/portage/tests/util/test_mtimedb.py
index e6ddf5b80..a65a6be91 100644
--- a/lib/portage/tests/util/test_mtimedb.py
+++ b/lib/portage/tests/util/test_mtimedb.py
@@ -222,13 +222,13 @@ class MtimeDBTestCase(TestCase):
 )
 for contents in all_fixtures:
 with patch(
-'portage.util.mtimedb.open', mock_open(read_data=contents)
+"portage.util.mtimedb.open", mock_open(read_data=contents)
 ):
 mtimedb = MtimeDB("/path/to/mtimedb")
 self.assertLessEqual(set(mtimedb.keys()), _MTIMEDBKEYS)
 
 def test_instance_has_default_values(self):
-with patch('portage.util.mtimedb.open',
+with patch("portage.util.mtimedb.open",
mock_open(read_data=_EMPTY_FILE)):
 mtimedb = MtimeDB("/some/path/mtimedb")
 self.assertEqual(mtimedb["starttime"], 0)
@@ -238,8 +238,39 @@ class MtimeDBTestCase(TestCase):
 self.assertEqual(mtimedb["updates"], {})
 
 def test_instance_has_a_deepcopy_of_clean_data(self):
-with patch('portage.util.mtimedb.open',
+with patch("portage.util.mtimedb.open",
mock_open(read_data=_ONE_RESUME_LIST_JSON)):
 mtimedb = MtimeDB("/some/path/mtimedb")
 self.assertEqual(dict(mtimedb), dict(mtimedb._clean_data))
 self.assertIsNot(mtimedb, mtimedb._clean_data)
+
+@patch("portage.util.mtimedb.MtimeDB._MtimeDB__write_to_disk")
+def test_commit_writes_to_disk_if_needed_and_possible(self, pwrite2disk):
+with patch("portage.util.mtimedb.open",
+   mock_open(read_data=_EMPTY_FILE)):
+mtimedb = MtimeDB("/some/path/mtimedb")
+mtimedb.commit()
+pwrite2disk.assert_not_called()
+mtimedb["updates"]["/long/path/1Q-2021"] = 1739992409
+d = {}
+d.update(mtimedb)
+mtimedb.commit()
+pwrite2disk.assert_called_once_with(d)
+
+@patch("portage.util.mtimedb.MtimeDB._MtimeDB__write_to_disk")
+def test_commit_does_not_write_to_disk_if_no_file(self, pwrite2disk):
+with patch("portage.util.mtimedb.open",
+   mock_open(read_data=_EMPTY_FILE)):
+mtimedb = MtimeDB("/some/path/mtimedb")
+mtimedb["updates"]["/long/path/1Q-2021"] = 1739992409
+mtimedb.filename = None
+mtimedb.commit()
+pwrite2disk.assert_not_called()
+
+@patch("portage.util.mtimedb.MtimeDB._MtimeDB__write_to_disk")
+def test_commit_does_not_write_to_disk_if_no_changes(self, pwrite2disk):
+with patch("portage.util.mtimedb.open",
+   mock_open(read_data=_EMPTY_FILE)):
+mtimedb = MtimeDB("/some/path/mtimedb")
+mtimedb.commit()
+pwrite2disk.assert_not_called()

diff --git a/lib/portage/util/mtimedb.py b/lib/portage/util/mtimedb.py
index 3aab0b90b..a6566e3f8 100644
--- a/lib/portage/util/mtimedb.py
+++ b/lib/portage/util/mtimedb.py
@@ -120,24 +120,27 @@ class MtimeDB(dict):
 d.update(self)
 # Only commit if the internal state has changed.
 if d != self._clean_data:
-d["version"] = str(portage.VERSION)
-try:
-f = atomic_ofstream(self.filename, mode="wb")
-except EnvironmentError:
-pass
-else:
-if self._json_write:
-f.write(
-_unicode_encode(
-json.dumps(d, **self._json_write_opts),
-encoding=_encodings["repo.content"],
-errors="strict",
-)
+self.__write_to_disk(d)
+
+def __write_to_disk(self, d):
+d["version"] = str(portage.VERSION)
+try:
+f = atomic_ofstream(self.filename, mode="wb")
+except EnvironmentError:
+pass
+else:
+if self._json_write:
+f.write(
+_unicode_encode(
+json.dumps(d, **self._json_write_opts),
+encoding=_encodings["repo.content"],
+errors="strict",

[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/tests/util/

2022-06-07 Thread Mike Gilbert
commit: 8a0a42ceb530b277e17220614f8c34bc8d0e503c
Author: David Palao  gmail  com>
AuthorDate: Tue May 31 15:30:48 2022 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Tue Jun  7 23:47:55 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=8a0a42ce

test(MtimeDB): added some unit tests for __write_to_disk and for _load

Signed-off-by: David Palao  gmail.com>
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/tests/util/test_mtimedb.py | 122 +++--
 lib/portage/util/mtimedb.py|   1 +
 2 files changed, 102 insertions(+), 21 deletions(-)

diff --git a/lib/portage/tests/util/test_mtimedb.py 
b/lib/portage/tests/util/test_mtimedb.py
index ecc0e7135..09d72049f 100644
--- a/lib/portage/tests/util/test_mtimedb.py
+++ b/lib/portage/tests/util/test_mtimedb.py
@@ -2,31 +2,28 @@
 # Distributed under the terms of the GNU General Public License v2
 
 from unittest.mock import patch, mock_open
+import json
 
 from portage.tests import TestCase
 
+import portage
+from portage.data import portage_gid, uid
 from portage.util.mtimedb import MtimeDB, _MTIMEDBKEYS
 from portage.exception import DigestException
 
 
-# Some random data for the fixtures:
+# Some data for the fixtures:
 
 _ONE_RESUME_LIST_JSON = b"""{
"info": {
-   
"/tmp/stage1root/usr/share/binutils-data/x86_64-pc-linux-gnu/2.34/info": 
1711785090,
-   
"/tmp/stage1root/usr/share/gcc-data/x86_64-pc-linux-gnu/9.3.0/info": 1711785090,
-   "/tmp/stage1root/usr/share/info": 1611785090,
-   "/usr/share/binutils-data/x86_64-pc-linux-gnu/2.34/info": 
1711787325,
+   "/usr/share/binutils-data/x86_64-pc-linux-gnu/2.37/info": 
1711787325,
"/usr/share/gcc-data/x86_64-pc-linux-gnu/11.2.0/info": 
1735158257,
-   "/usr/share/gcc-data/x86_64-pc-linux-gnu/9.3.0/info": 
1711787325,
"/usr/share/info": 1650633847
},
"ldpath": {
"/lib": 1748456830,
"/lib64": 1750523381,
"/usr/lib": 1750461195,
-   "/usr/lib/llvm/11/lib64": 1723048948,
-   "/usr/lib/llvm/12/lib64": 1730499781,
"/usr/lib/llvm/13/lib64": 1747003135,
"/usr/lib/rust/lib": 1750461173,
"/usr/lib64": 1750881821,
@@ -66,12 +63,8 @@ _ONE_RESUME_LIST_JSON = b"""{
},
"starttime": 0,
"updates": {
-   "/var/db/repos/gentoo/profiles/updates/1Q-2021": 1739992409,
"/var/db/repos/gentoo/profiles/updates/1Q-2022": 1747854791,
-   "/var/db/repos/gentoo/profiles/updates/2Q-2021": 1724404379,
"/var/db/repos/gentoo/profiles/updates/2Q-2022": 1752846209,
-   "/var/db/repos/gentoo/profiles/updates/3Q-2021": 1741119203,
-   "/var/db/repos/gentoo/profiles/updates/4Q-2020": 1709167362,
"/var/db/repos/gentoo/profiles/updates/4Q-2021": 1742787797
},
"version": "3.0.30"
@@ -85,8 +78,6 @@ _PARTIAL_FILE_JSON = b"""{
"/lib": 1748456830,
"/lib64": 1750523381,
"/usr/lib": 1750461195,
-   "/usr/lib/llvm/11/lib64": 1723048948,
-   "/usr/lib/llvm/12/lib64": 1730499781,
"/usr/lib/llvm/13/lib64": 1747003135,
"/usr/lib/rust/lib": 1750461173,
"/usr/lib64": 1750881821,
@@ -130,7 +121,7 @@ _PARTIAL_FILE_JSON = b"""{
 
 _TWO_RESUME_LISTS_JSON = b"""{
"info": {
-   "/usr/share/binutils-data/x86_64-pc-linux-gnu/2.34/info": 
1711787325,
+   "/usr/share/binutils-data/x86_64-pc-linux-gnu/2.37/info": 
1711787325,
"/usr/share/gcc-data/x86_64-pc-linux-gnu/11.2.0/info": 
1735158257,
"/usr/share/info": 1650633847
},
@@ -199,12 +190,8 @@ _TWO_RESUME_LISTS_JSON = b"""{
},
"starttime": 0,
"updates": {
-   "/var/db/repos/gentoo/profiles/updates/1Q-2021": 1739992409,
"/var/db/repos/gentoo/profiles/updates/1Q-2022": 1747854791,
-   "/var/db/repos/gentoo/profiles/updates/2Q-2021": 1724404379,
"/var/db/repos/gentoo/profiles/updates/2Q-2022": 1752846209,
-   "/var/db/repos/gentoo/profiles/updates/3Q-2021": 1741119203,
-   "/var/db/repos/gentoo/profiles/updates/4Q-2020": 1709167362,
"/var/db/repos/gentoo/profiles/updates/4Q-2021": 1742787797
},
"version": "3.0.30"
@@ -215,7 +202,7 @@ _TWO_RESUME_LISTS_JSON = b"""{
 class MtimeDBTestCase(TestCase):
 text = b"Unit tests for MtimeDB"
 
-def test_instances_are_created_with_only_expected_keys(self):
+def test_instances_created_with_only_expected_keys(self):
 all_fixtures = (
 _ONE_RESUME_LIST_JSON,
 _EMPTY_FILE,
@@ -229,7 +216,7 @@ class MtimeDBTestCase(TestCase):
 mtimedb = 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2022-06-07 Thread Mike Gilbert
commit: 92c63ef74039e2361a4912ead5416b08cdfa8ac8
Author: David Palao  gmail  com>
AuthorDate: Sun May 22 09:40:45 2022 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Tue Jun  7 23:47:54 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=92c63ef7

refactor(mtimedb): some little changes:

- interpolated strings (%...) replaced by f-strings
- some little simplifications
- factor out some constants to prepare for unittesting

Signed-off-by: David Palao  gmail.com>
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/util/mtimedb.py | 44 ++--
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/lib/portage/util/mtimedb.py b/lib/portage/util/mtimedb.py
index 7a7fe6784..df9bd494c 100644
--- a/lib/portage/util/mtimedb.py
+++ b/lib/portage/util/mtimedb.py
@@ -23,7 +23,23 @@ from portage.localization import _
 from portage.util import apply_secpass_permissions, atomic_ofstream, writemsg
 
 
+_MTIMEDBKEYS = {
+"info",
+"ldpath",
+"resume",
+"resume_backup",
+"starttime",
+"updates",
+"version",
+}
+
+
 class MtimeDB(dict):
+"""The MtimeDB class is used to interact with a file storing the
+current resume lists.
+It is a subclass of ``dict`` and it reads from/writes to JSON, by
+default, althouth it can be configured to use ``pickle``.
+"""
 
 # JSON read support has been available since portage-2.1.10.49.
 _json_write = True
@@ -46,13 +62,13 @@ class MtimeDB(dict):
 pass
 else:
 writemsg(
-_("!!! Error loading '%s': %s\n") % (filename, e), 
noiselevel=-1
+_(f"!!! Error loading '{filename}': {e}\n"), noiselevel=-1
 )
 finally:
 if f is not None:
 f.close()
 
-d = None
+d = {}
 if content:
 try:
 d = json.loads(
@@ -75,12 +91,9 @@ class MtimeDB(dict):
 raise
 except Exception:
 writemsg(
-_("!!! Error loading '%s': %s\n") % (filename, e), 
noiselevel=-1
+_(f"!!! Error loading '{filename}': {e}\n"), 
noiselevel=-1
 )
 
-if d is None:
-d = {}
-
 if "old" in d:
 d["updates"] = d["old"]
 del d["old"]
@@ -92,22 +105,9 @@ class MtimeDB(dict):
 for k in ("info", "ldpath", "updates"):
 d.setdefault(k, {})
 
-mtimedbkeys = set(
-(
-"info",
-"ldpath",
-"resume",
-"resume_backup",
-"starttime",
-"updates",
-"version",
-)
-)
-
-for k in list(d):
-if k not in mtimedbkeys:
-writemsg(_("Deleting invalid mtimedb key: %s\n") % str(k))
-del d[k]
+for k in (d.keys()-_MTIMEDBKEYS):
+writemsg(_(f"Deleting invalid mtimedb key: {k}\n"))
+del d[k]
 self.update(d)
 self._clean_data = copy.deepcopy(d)
 



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2022-05-21 Thread Michał Górny
commit: 1f33f97b9e9c132d77d586d10bfe6ba0d3123050
Author: Thomas Bracht Laumann Jespersen  laumann  xyz>
AuthorDate: Thu May 19 09:50:05 2022 +
Commit: Michał Górny  gentoo  org>
CommitDate: Sat May 21 10:11:50 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=1f33f97b

lib/portage/util: fix bundled whirlpool on empty bytestring input

The WhirlpoolAdd function did not consider zero-length input, so calls
to update(b'') would produce out-of-bounds errors. This was not covered
by any tests, because the constructor implicitly skipped the call to
update on zero-length input.

Add check for zero-length input to WhirlpoolAdd, and have the Whirlpool
constructor skip calling update() only if arg is None.

Closes: https://bugs.gentoo.org/846389
Signed-off-by: Thomas Bracht Laumann Jespersen  laumann.xyz>
Closes: https://github.com/gentoo/portage/pull/832
Signed-off-by: Michał Górny  gentoo.org>

 lib/portage/util/whirlpool.py | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/lib/portage/util/whirlpool.py b/lib/portage/util/whirlpool.py
index de344d8eb..9178d70c7 100644
--- a/lib/portage/util/whirlpool.py
+++ b/lib/portage/util/whirlpool.py
@@ -37,11 +37,9 @@ class Whirlpool:
 may be provided; if present, this string will be automatically
 hashed."""
 
-def __init__(self, arg=None):
+def __init__(self, arg=b""):
 self.ctx = WhirlpoolStruct()
-if arg:
-self.update(arg)
-self.digest_status = 0
+self.update(arg)
 
 def update(self, arg):
 """update(arg)"""
@@ -71,7 +69,7 @@ class Whirlpool:
 return copy.deepcopy(self)
 
 
-def new(init=None):
+def new(init=b""):
 """Return a new Whirlpool object. An optional string argument
 may be provided; if present, this string will be automatically
 hashed."""
@@ -2183,6 +2181,8 @@ def WhirlpoolInit(ctx):
 def WhirlpoolAdd(source, sourceBits, ctx):
 if not isinstance(source, bytes):
 raise TypeError("Expected %s, got %s" % (bytes, type(source)))
+if sourceBits == 0:
+return
 
 carry = 0
 value = sourceBits
@@ -2350,3 +2350,9 @@ if __name__ == "__main__":
 Whirlpool(b"").hexdigest()
 == 
"19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3"
 )
+w = Whirlpool()
+w.update(b"")
+assert (
+w.hexdigest()
+== 
"19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3"
+)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2022-04-14 Thread Sam James
commit: fa82725ba03ffa5edf0b82db7307c87fc97e83f2
Author: Mike Frysinger  chromium  org>
AuthorDate: Wed Mar 30 06:32:07 2022 +
Commit: Sam James  gentoo  org>
CommitDate: Fri Apr 15 02:46:19 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=fa82725b

movefile: merge symlinks atomically

Since POSIX allows renaming symlinks with symlinks, use that to get
atomic updates.  This is faster and less flaky to parallel processes:
removing a live symlink and then recreating it leaves a small window
where other things might try to use it but fail.

[sam: cherry-picked from chromiumos' third_party/portage_tool repo]
(cherry picked from commit cherry-pick 80ed2dac95db81acac8043e6685d0a853a08d268)
Bug: https://bugs.gentoo.org/836400
Signed-off-by: Sam James  gentoo.org>
Closes: https://github.com/gentoo/portage/pull/816
Signed-off-by: Sam James  gentoo.org>

 lib/portage/util/movefile.py | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/lib/portage/util/movefile.py b/lib/portage/util/movefile.py
index ddafe5571..4dc08af26 100644
--- a/lib/portage/util/movefile.py
+++ b/lib/portage/util/movefile.py
@@ -171,7 +171,7 @@ def movefile(
 bsd_chflags.chflags(os.path.dirname(dest), 0)
 
 if destexists:
-if stat.S_ISLNK(dstat[stat.ST_MODE]):
+if not stat.S_ISLNK(sstat[stat.ST_MODE]) and 
stat.S_ISLNK(dstat[stat.ST_MODE]):
 try:
 os.unlink(dest)
 destexists = 0
@@ -185,8 +185,18 @@ def movefile(
 target = os.readlink(src)
 if mysettings and "D" in mysettings and 
target.startswith(mysettings["D"]):
 target = target[len(mysettings["D"]) - 1 :]
-if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
-os.unlink(dest)
+# Atomically update the path if it exists.
+try:
+os.rename(src, dest)
+return sstat.st_mtime_ns
+except OSError:
+# If it failed due to cross-link device, fallthru below.
+# Clear the target first so we can create it.
+try:
+os.unlink(dest)
+except FileNotFoundError:
+pass
+
 try:
 if selinux_enabled:
 selinux.symlink(target, dest, src)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, bin/, lib/portage/tests/

2022-03-09 Thread Mike Gilbert
commit: 781aefd8be33c3bd699e5a665225013c5f76b531
Author: John Helmert III  gentoo  org>
AuthorDate: Wed Mar  9 19:48:11 2022 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Wed Mar  9 19:57:34 2022 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=781aefd8

Drop -b from shebangs

The switch to using '/usr/bin/env python' shebangs doesn't naively
work with arguments after 'python', so the shebangs were broken. '-b'
is of dubious necessity anyway, so let's just drop it.

Fixes: 41f4f6d25019c4f944b8d9576d96482f92231fda
Signed-off-by: John Helmert III  gentoo.org>
Signed-off-by: Mike Gilbert  gentoo.org>

 bin/archive-conf| 2 +-
 bin/binhost-snapshot| 2 +-
 bin/check-implicit-pointer-usage.py | 2 +-
 bin/chmod-lite.py   | 2 +-
 bin/chpathtool.py   | 2 +-
 bin/clean_locks | 2 +-
 bin/dispatch-conf   | 2 +-
 bin/dohtml.py   | 2 +-
 bin/doins.py| 2 +-
 bin/ebuild  | 2 +-
 bin/ebuild-ipc.py   | 2 +-
 bin/egencache   | 2 +-
 bin/emaint  | 2 +-
 bin/emerge  | 2 +-
 bin/emirrordist | 2 +-
 bin/env-update  | 2 +-
 bin/filter-bash-environment.py  | 2 +-
 bin/fixpackages | 2 +-
 bin/glsa-check  | 2 +-
 bin/gpkg-helper.py  | 2 +-
 bin/install.py  | 2 +-
 bin/lock-helper.py  | 2 +-
 bin/portageq| 2 +-
 bin/quickpkg| 2 +-
 bin/regenworld  | 2 +-
 bin/shelve-utils| 2 +-
 bin/xattr-helper.py | 2 +-
 bin/xpak-helper.py  | 2 +-
 lib/portage/tests/runTests.py   | 2 +-
 lib/portage/util/changelog.py   | 2 +-
 30 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/bin/archive-conf b/bin/archive-conf
index beb4fcd23..3f7d186fe 100755
--- a/bin/archive-conf
+++ b/bin/archive-conf
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 # Copyright 1999-2020 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 

diff --git a/bin/binhost-snapshot b/bin/binhost-snapshot
index 3461a301c..4022cb32c 100755
--- a/bin/binhost-snapshot
+++ b/bin/binhost-snapshot
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 # Copyright 2010-2014 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 

diff --git a/bin/check-implicit-pointer-usage.py 
b/bin/check-implicit-pointer-usage.py
index 61eecd65b..06b666c88 100755
--- a/bin/check-implicit-pointer-usage.py
+++ b/bin/check-implicit-pointer-usage.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 
 # Ripped from HP and updated from Debian
 # Update by Gentoo to support unicode output

diff --git a/bin/chmod-lite.py b/bin/chmod-lite.py
index 602b3600b..517a55bd9 100755
--- a/bin/chmod-lite.py
+++ b/bin/chmod-lite.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 # Copyright 2015 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 

diff --git a/bin/chpathtool.py b/bin/chpathtool.py
index 2d4993716..d658e5012 100755
--- a/bin/chpathtool.py
+++ b/bin/chpathtool.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 # Copyright 2011-2014 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 

diff --git a/bin/clean_locks b/bin/clean_locks
index 88e1b3325..b80213911 100755
--- a/bin/clean_locks
+++ b/bin/clean_locks
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 # Copyright 1999-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 

diff --git a/bin/dispatch-conf b/bin/dispatch-conf
index c0e7ffc1e..9490197d3 100755
--- a/bin/dispatch-conf
+++ b/bin/dispatch-conf
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 # Copyright 1999-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 

diff --git a/bin/dohtml.py b/bin/dohtml.py
index e7cfa591e..86cda72aa 100755
--- a/bin/dohtml.py
+++ b/bin/dohtml.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 # Copyright 1999-2020 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 

diff --git a/bin/doins.py b/bin/doins.py
index 42ea25078..087756218 100644
--- a/bin/doins.py
+++ b/bin/doins.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 # Copyright 2017-2020 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 #

diff --git a/bin/ebuild b/bin/ebuild
index bdedab9cb..bab8d52ad 100755
--- a/bin/ebuild
+++ b/bin/ebuild
@@ -1,4 +1,4 @@
-#!/usr/bin/env python -b
+#!/usr/bin/env python
 # Copyright 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/, lib/portage/util/, lib/portage/

2021-12-08 Thread Michał Górny
commit: a5092f11f31b6a9d54a34423088a7bb8e70bc1c6
Author: Michał Górny  gentoo  org>
AuthorDate: Wed Dec  8 21:16:19 2021 +
Commit: Michał Górny  gentoo  org>
CommitDate: Wed Dec  8 21:16:19 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a5092f11

Reformat with black 21.12b0

Signed-off-by: Michał Górny  gentoo.org>

 lib/portage/process.py  | 2 --
 lib/portage/util/_xattr.py  | 1 -
 lib/portage/util/futures/unix_events.py | 1 -
 3 files changed, 4 deletions(-)

diff --git a/lib/portage/process.py b/lib/portage/process.py
index e1bd2314e..84e09f8ec 100644
--- a/lib/portage/process.py
+++ b/lib/portage/process.py
@@ -84,7 +84,6 @@ if _fd_dir is not None:
 raise
 return range(max_fd_limit)
 
-
 elif os.path.isdir("/proc/%s/fd" % portage.getpid()):
 # In order for this function to work in forked subprocesses,
 # os.getpid() must be called from inside the function.
@@ -95,7 +94,6 @@ elif os.path.isdir("/proc/%s/fd" % portage.getpid()):
 if fd.isdigit()
 )
 
-
 else:
 
 def get_open_fds():

diff --git a/lib/portage/util/_xattr.py b/lib/portage/util/_xattr.py
index ff0a7d8c5..f4d3ad733 100644
--- a/lib/portage/util/_xattr.py
+++ b/lib/portage/util/_xattr.py
@@ -169,7 +169,6 @@ if hasattr(os, "getxattr"):
 def list(item, nofollow=False, namespace=None):
 return os.listxattr(item, follow_symlinks=not nofollow)
 
-
 else:
 try:
 # Maybe we have the xattr module.

diff --git a/lib/portage/util/futures/unix_events.py 
b/lib/portage/util/futures/unix_events.py
index f2f01f0c6..c9855aefb 100644
--- a/lib/portage/util/futures/unix_events.py
+++ b/lib/portage/util/futures/unix_events.py
@@ -23,7 +23,6 @@ if hasattr(os, "set_blocking"):
 def _set_nonblocking(fd):
 os.set_blocking(fd, False)
 
-
 else:
 
 def _set_nonblocking(fd):



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_dyn_libs/

2021-11-24 Thread Mike Gilbert
commit: 3b3503bb2769b390e22a4fea42fa56fe4db4ddec
Author: Mike Gilbert  gentoo  org>
AuthorDate: Tue Nov 23 22:39:24 2021 +
Commit: Mike Gilbert  gentoo  org>
CommitDate: Tue Nov 23 23:22:32 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3b3503bb

portage/util/_dyn_libs/dyn_libs.py: fix symlink recursion issue

Python's glob.glob() function follows symlinks recursively. Use
os.walk() instead.

Also re-order the operands to short-circuit the directory walk when
PROVIDES is not empty.

Bug: https://bugs.gentoo.org/826982
Fixes: cba2156dba89a22f2858238013469b4d80208854
Signed-off-by: Mike Gilbert  gentoo.org>

 lib/portage/util/_dyn_libs/dyn_libs.py | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/lib/portage/util/_dyn_libs/dyn_libs.py 
b/lib/portage/util/_dyn_libs/dyn_libs.py
index 34b4bc926..ee28e8839 100644
--- a/lib/portage/util/_dyn_libs/dyn_libs.py
+++ b/lib/portage/util/_dyn_libs/dyn_libs.py
@@ -1,7 +1,15 @@
 # Copyright 2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-import glob
+import os
+
+
+def installed_dynlibs(directory):
+for _dirpath, _dirnames, filenames in os.walk(directory):
+for filename in filenames:
+if filename.endswith(".so"):
+return True
+return False
 
 
 def check_dyn_libs_inconsistent(directory, provides):
@@ -17,5 +25,4 @@ def check_dyn_libs_inconsistent(directory, provides):
 # but this doesn't gain us anything. We're interested in failure
 # to properly parse the installed files at all, which should really
 # be a global problem (e.g. bug #811462)
-installed_dynlibs = glob.glob(directory + "/**/*.so", recursive=True)
-return installed_dynlibs and not provides
+return not provides and installed_dynlibs(directory)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_dyn_libs/

2021-10-27 Thread Sam James
commit: dcf6de8aa115cfe1ca5474b3c98efa8f75f8f47b
Author: Sam James  gentoo  org>
AuthorDate: Thu Oct 28 04:59:20 2021 +
Commit: Sam James  gentoo  org>
CommitDate: Thu Oct 28 05:00:10 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=dcf6de8a

lib/portage/util/_dyn_libs/dyn_libs.py: drop unused import

Signed-off-by: Sam James  gentoo.org>

 lib/portage/util/_dyn_libs/dyn_libs.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lib/portage/util/_dyn_libs/dyn_libs.py 
b/lib/portage/util/_dyn_libs/dyn_libs.py
index 2a014812c..34b4bc926 100644
--- a/lib/portage/util/_dyn_libs/dyn_libs.py
+++ b/lib/portage/util/_dyn_libs/dyn_libs.py
@@ -3,8 +3,6 @@
 
 import glob
 
-from portage.output import colorize
-
 
 def check_dyn_libs_inconsistent(directory, provides):
 """Checks directory for whether any dynamic libraries were installed and



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_dyn_libs/

2021-10-27 Thread Sam James
commit: cba2156dba89a22f2858238013469b4d80208854
Author: Sam James  gentoo  org>
AuthorDate: Thu Oct 28 04:40:09 2021 +
Commit: Sam James  gentoo  org>
CommitDate: Thu Oct 28 04:52:18 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=cba2156d

portage/util/_dyn_libs/dyn_libs.py: add helper

Needed for binpkg/image verification commits coming...

Bug: https://bugs.gentoo.org/811462
Signed-off-by: Sam James  gentoo.org>

 lib/portage/util/_dyn_libs/dyn_libs.py | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/lib/portage/util/_dyn_libs/dyn_libs.py 
b/lib/portage/util/_dyn_libs/dyn_libs.py
new file mode 100644
index 0..2a014812c
--- /dev/null
+++ b/lib/portage/util/_dyn_libs/dyn_libs.py
@@ -0,0 +1,23 @@
+# Copyright 2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import glob
+
+from portage.output import colorize
+
+
+def check_dyn_libs_inconsistent(directory, provides):
+"""Checks directory for whether any dynamic libraries were installed and
+if PROVIDES corresponds."""
+
+# Let's check if we've got inconsistent results.
+# If we're installing dynamic libraries (.so files), we should
+# really have a PROVIDES.
+# (This is a complementary check at the point of ingestion for the
+# creation check in doebuild.py)
+# Note: we could check a non-empty PROVIDES against the list of .sos,
+# but this doesn't gain us anything. We're interested in failure
+# to properly parse the installed files at all, which should really
+# be a global problem (e.g. bug #811462)
+installed_dynlibs = glob.glob(directory + "/**/*.so", recursive=True)
+return installed_dynlibs and not provides



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2021-09-20 Thread Zac Medico
commit: 3f2ba95a960ed66dde1a0e4cea99f5d54b018d0f
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Sep 21 04:49:23 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Tue Sep 21 04:49:45 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3f2ba95a

ForkProcess: convert compat coroutine to async

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/ForkProcess.py | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/lib/portage/util/_async/ForkProcess.py 
b/lib/portage/util/_async/ForkProcess.py
index 674336935..e70238705 100644
--- a/lib/portage/util/_async/ForkProcess.py
+++ b/lib/portage/util/_async/ForkProcess.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2020 Gentoo Authors
+# Copyright 2012-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import fcntl
@@ -10,7 +10,6 @@ import sys
 import portage
 from portage import os
 from portage.util.futures import asyncio
-from portage.util.futures.compat_coroutine import coroutine
 from _emerge.SpawnProcess import SpawnProcess
 
 
@@ -73,15 +72,14 @@ class ForkProcess(SpawnProcess):
 if self._proc_join_task is None:
 super(ForkProcess, self)._async_waitpid()
 
-@coroutine
-def _proc_join(self, proc, loop=None):
+async def _proc_join(self, proc, loop=None):
 sentinel_reader = self.scheduler.create_future()
 self.scheduler.add_reader(
 proc.sentinel,
 lambda: sentinel_reader.done() or sentinel_reader.set_result(None),
 )
 try:
-yield sentinel_reader
+await sentinel_reader
 finally:
 # If multiprocessing.Process supports the close method, then
 # access to proc.sentinel will raise ValueError if the
@@ -101,7 +99,7 @@ class ForkProcess(SpawnProcess):
 proc.join(0)
 if proc.exitcode is not None:
 break
-yield asyncio.sleep(self._proc_join_interval, loop=loop)
+await asyncio.sleep(self._proc_join_interval, loop=loop)
 
 def _proc_join_done(self, proc, future):
 future.cancelled() or future.result()



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/

2021-09-20 Thread Zac Medico
commit: 2f474767eaf3b042bea31bc524281e0841cb271b
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Sep 20 06:44:36 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Sep 20 07:07:22 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=2f474767

ExtendedFuture: Fix python3.10 DeprecationWarning

DeprecationWarning: There is no current event loop

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/extendedfutures.py | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/lib/portage/util/futures/extendedfutures.py 
b/lib/portage/util/futures/extendedfutures.py
index 6aa3ebbe8..c23feafb5 100644
--- a/lib/portage/util/futures/extendedfutures.py
+++ b/lib/portage/util/futures/extendedfutures.py
@@ -10,7 +10,13 @@ __all__ = (
 "InvalidStateError",
 )
 
-from portage.util.futures.futures import Future, InvalidStateError, 
CancelledError
+import concurrent.futures
+from concurrent.futures import Future, CancelledError
+
+try:
+from concurrent.futures import InvalidStateError
+except ImportError:
+from portage.util.futures.futures import InvalidStateError
 
 # Create our one time settable unset constant
 UNSET_CONST = Future()
@@ -62,9 +68,21 @@ class ExtendedFuture(Future):
 default = self.default_result
 if default is not UNSET_CONST.result():
 try:
-data = super(ExtendedFuture, self).result()
+data = self.result()
 except InvalidStateError:
 data = default
 else:
-data = super(ExtendedFuture, self).result()
+data = self.result()
 return data
+
+def exception(self):
+try:
+return super(ExtendedFuture, self).exception(timeout=0)
+except concurrent.futures.TimeoutError:
+raise InvalidStateError
+
+def result(self):
+try:
+return super(ExtendedFuture, self).result(timeout=0)
+except concurrent.futures.TimeoutError:
+raise InvalidStateError



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/

2021-09-19 Thread Zac Medico
commit: 631bedffe29124d693de3b539fc908d9feec1420
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Sep 20 05:05:38 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Sep 20 05:08:47 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=631bedff

_safe_loop: fix python3.10 DeprecationWarning

DeprecationWarning: There is no current event loop

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/_asyncio/__init__.py | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/lib/portage/util/futures/_asyncio/__init__.py 
b/lib/portage/util/futures/_asyncio/__init__.py
index c1229528a..ccf800c66 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -280,10 +280,14 @@ def _safe_loop():
 loop = _thread_weakrefs.loops[thread_key]
 except KeyError:
 try:
-_real_asyncio.get_event_loop()
+try:
+_loop = _real_asyncio.get_running_loop()
+except AttributeError:
+_loop = _real_asyncio.get_event_loop()
 except RuntimeError:
-_real_asyncio.set_event_loop(_real_asyncio.new_event_loop())
-loop = _thread_weakrefs.loops[thread_key] = _AsyncioEventLoop()
+_loop = _real_asyncio.new_event_loop()
+_real_asyncio.set_event_loop(_loop)
+loop = _thread_weakrefs.loops[thread_key] = 
_AsyncioEventLoop(loop=_loop)
 
 if (
 _thread_weakrefs.mainloop is None



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_dyn_libs/, lib/_emerge/

2021-09-03 Thread Michał Górny
commit: 1ae727e997e2c7915a4384a27c9362e59d8dd074
Author: Michał Górny  gentoo  org>
AuthorDate: Tue Aug 31 12:05:41 2021 +
Commit: Michał Górny  gentoo  org>
CommitDate: Fri Sep  3 11:26:28 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=1ae727e9

post_emerge: Display all preserved libs with --verbose

Signed-off-by: Michał Górny  gentoo.org>
Closes: https://github.com/gentoo/portage/pull/742
Signed-off-by: Michał Górny  gentoo.org>

 lib/_emerge/post_emerge.py   |  2 +-
 lib/portage/util/_dyn_libs/display_preserved_libs.py | 11 +++
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/lib/_emerge/post_emerge.py b/lib/_emerge/post_emerge.py
index 0c4df0d32..c540308d3 100644
--- a/lib/_emerge/post_emerge.py
+++ b/lib/_emerge/post_emerge.py
@@ -140,7 +140,7 @@ def post_emerge(myaction, myopts, myfiles,
else:
print()
print(colorize("WARN", "!!!") + " existing preserved 
libs:")
-   display_preserved_libs(vardbapi)
+   display_preserved_libs(vardbapi, verbose="--verbose" in 
myopts)
print("Use " + colorize("GOOD", "emerge 
@preserved-rebuild") +
" to rebuild packages using these libraries")
 

diff --git a/lib/portage/util/_dyn_libs/display_preserved_libs.py 
b/lib/portage/util/_dyn_libs/display_preserved_libs.py
index 8deafc25e..5818501bb 100644
--- a/lib/portage/util/_dyn_libs/display_preserved_libs.py
+++ b/lib/portage/util/_dyn_libs/display_preserved_libs.py
@@ -6,7 +6,7 @@ import portage
 
 from portage.output import colorize
 
-def display_preserved_libs(vardb):
+def display_preserved_libs(vardb, verbose=False):
 
MAX_DISPLAY = 3
 
@@ -36,7 +36,8 @@ def display_preserved_libs(vardb):
consumers.append(c)
consumers.sort()
consumer_map[f] = consumers
-   
search_for_owners.update(consumers[:MAX_DISPLAY+1])
+   max_search = None if verbose else MAX_DISPLAY + 
1
+   search_for_owners.update(consumers[:max_search])
 
owners = {}
for f in search_for_owners:
@@ -75,7 +76,9 @@ def display_preserved_libs(vardb):
# they don't need to be rebuilt (see bug 
#461908).
consumers = consumers_non_preserved
 
-   if len(consumers) == MAX_DISPLAY + 1:
+   if verbose:
+   max_display = None
+   elif len(consumers) == MAX_DISPLAY + 1:
# Display 1 extra consumer, instead of 
displaying
# "used by 1 other files".
max_display = MAX_DISPLAY + 1
@@ -91,6 +94,6 @@ def display_preserved_libs(vardb):
owners_desc = ", ".join(x.mycpv for x 
in owners.get(c, []))
print(colorize("WARN", " * ") + " used by 
%s (%s)" % \
(c, owners_desc))
-   if len(consumers) > max_display:
+   if not verbose and len(consumers) > max_display:
print(colorize("WARN", " * ") + " used by 
%d other files" %
(len(consumers) - max_display))



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/, lib/portage/sync/

2021-08-22 Thread Michał Górny
commit: a48532754eae8ea3dfa491968000313872b18241
Author: Florian Schmaus  geekplace  eu>
AuthorDate: Tue Aug 18 19:48:34 2020 +
Commit: Michał Górny  gentoo  org>
CommitDate: Sun Aug 22 15:32:06 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a4853275

util: add portage.util.hooks.get_hooks_from_dir()

Signed-off-by: Florian Schmaus  geekplace.eu>
Signed-off-by: Michał Górny  gentoo.org>

 lib/portage/dispatch_conf.py   |  1 +
 lib/portage/sync/controller.py | 16 ++--
 lib/portage/util/hooks.py  | 31 +++
 3 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/lib/portage/dispatch_conf.py b/lib/portage/dispatch_conf.py
index 0356ba7bc..3ef659852 100644
--- a/lib/portage/dispatch_conf.py
+++ b/lib/portage/dispatch_conf.py
@@ -18,6 +18,7 @@ from portage import _encodings, os, shutil
 from portage.env.loaders import KeyValuePairFileLoader
 from portage.localization import _
 from portage.util import shlex_split, varexpand
+from portage.util.hooks import perform_hooks
 from portage.util.path import iter_parents
 
 RCS_BRANCH = '1.1.1'

diff --git a/lib/portage/sync/controller.py b/lib/portage/sync/controller.py
index 0f42b1da9..f1d706d7e 100644
--- a/lib/portage/sync/controller.py
+++ b/lib/portage/sync/controller.py
@@ -7,8 +7,6 @@ import grp
 import pwd
 import warnings
 
-from collections import OrderedDict
-
 import portage
 from portage import os
 from portage.progress import ProgressBar
@@ -20,9 +18,9 @@ bad = create_color_func("BAD")
 warn = create_color_func("WARN")
 from portage.package.ebuild.doebuild import _check_temp_dir
 from portage.metadata import action_metadata
+from portage.util.hooks import get_hooks_from_dir
 from portage.util._async.AsyncFunction import AsyncFunction
 from portage import _unicode_decode
-from portage import util
 from _emerge.CompositeTask import CompositeTask
 
 
@@ -93,17 +91,7 @@ class SyncManager:
self.module_names = self.module_controller.module_names
self.hooks = {}
for _dir in ["repo.postsync.d", "postsync.d"]:
-   postsync_dir = 
os.path.join(self.settings["PORTAGE_CONFIGROOT"],
-   portage.USER_CONFIG_PATH, _dir)
-   hooks = OrderedDict()
-   for filepath in util._recursive_file_list(postsync_dir):
-   name = 
filepath.split(postsync_dir)[1].lstrip(os.sep)
-   if os.access(filepath, os.X_OK):
-   hooks[filepath] = name
-   else:
-   writemsg_level(" %s %s hook: '%s' is 
not executable\n"
-   % (warn("*"), _dir, 
_unicode_decode(name),),
-   level=logging.WARN, 
noiselevel=2)
+   hooks = get_hooks_from_dir(_dir, 
prefix=self.settings["PORTAGE_CONFIGROOT"])
self.hooks[_dir] = hooks
 
def __getattr__(self, name):

diff --git a/lib/portage/util/hooks.py b/lib/portage/util/hooks.py
new file mode 100644
index 0..d10ec7a59
--- /dev/null
+++ b/lib/portage/util/hooks.py
@@ -0,0 +1,31 @@
+# Copyright 2014-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import logging
+
+from collections import OrderedDict
+
+import portage
+
+from portage import os
+from portage.output import create_color_func
+from portage.util import writemsg_level, _recursive_file_list
+from warnings import warn
+
+warn = create_color_func("WARN")
+
+
+def get_hooks_from_dir(rel_directory, prefix="/"):
+   directory = os.path.join(prefix, portage.USER_CONFIG_PATH, 
rel_directory)
+
+   hooks = OrderedDict()
+   for filepath in _recursive_file_list(directory):
+   name = filepath.split(directory)[1].lstrip(portage.os.sep)
+   if portage.os.access(filepath, portage.os.X_OK):
+   hooks[filepath] = name
+   else:
+   writemsg_level(" %s %s hook: '%s' is not executable\n" 
% \
+   (warn("*"), directory, 
portage._unicode_decode(name),),
+   level=logging.WARN, noiselevel=2)
+
+   return hooks



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2021-05-24 Thread Zac Medico
commit: 21739ea1e0a793e207b7ae28d524e45582d9b2ca
Author: Florian Schmaus  geekplace  eu>
AuthorDate: Tue Apr 27 11:02:56 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon May 24 06:13:07 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=21739ea1

env-update: skip PATH in systemd user environment definition

Having PATH in the systemd user environment created by env-update
makes it impossible to use "systemctl --user import-environment PATH"
to set PATH in systemd user units according to the current value of
PATH. Using "systemctl --user import-environment PATH" is a well known
idiom, and hence should work. Therefore, we skip the creation of the
PATH entry by env-update.

Closes: https://github.com/gentoo/portage/pull/701
Signed-off-by: Florian Schmaus  geekplace.eu>
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/env_update.py | 5 +
 1 file changed, 5 insertions(+)

diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index 5588931a8..abf261fbc 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -367,6 +367,11 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env,
systemd_gentoo_env.write(senvnotice)
 
for env_key in env_keys:
+   # Skip PATH since this makes it impossible to use
+   # "systemctl --user import-environment PATH".
+   if env_key == 'PATH':
+   continue
+
env_key_value = env[env_key]
 
# Skip variables with the empty string



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2021-05-01 Thread Zac Medico
commit: bfe550f69ac4e0126412bc83f7e6f6f0d1c6dc1f
Author: Zac Medico  gentoo  org>
AuthorDate: Sat May  1 23:38:50 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sat May  1 23:49:07 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=bfe550f6

PipeLogger: handle FileNotFoundError when cancelled during _start

Bug: https://bugs.gentoo.org/787542
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/PipeLogger.py | 35 +--
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/lib/portage/util/_async/PipeLogger.py 
b/lib/portage/util/_async/PipeLogger.py
index b7c03043f..a335ce96f 100644
--- a/lib/portage/util/_async/PipeLogger.py
+++ b/lib/portage/util/_async/PipeLogger.py
@@ -33,16 +33,31 @@ class PipeLogger(AbstractPollTask):
self._log_file = log_file_path
_set_nonblocking(self._log_file.fileno())
elif log_file_path is not None:
-   self._log_file = open(_unicode_encode(log_file_path,
-   encoding=_encodings['fs'], errors='strict'), 
mode='ab')
-   if log_file_path.endswith('.gz'):
-   self._log_file_real = self._log_file
-   self._log_file = gzip.GzipFile(filename='', 
mode='ab',
-   fileobj=self._log_file)
-
-   portage.util.apply_secpass_permissions(log_file_path,
-   uid=portage.portage_uid, 
gid=portage.portage_gid,
-   mode=0o660)
+   try:
+   self._log_file = open(
+   _unicode_encode(
+   log_file_path, 
encoding=_encodings["fs"], errors="strict"
+   ),
+   mode="ab",
+   )
+
+   if log_file_path.endswith(".gz"):
+   self._log_file_real = self._log_file
+   self._log_file = gzip.GzipFile(
+   filename="", mode="ab", 
fileobj=self._log_file
+   )
+
+   portage.util.apply_secpass_permissions(
+   log_file_path,
+   uid=portage.portage_uid,
+   gid=portage.portage_gid,
+   mode=0o660,
+   )
+   except FileNotFoundError:
+   if self._was_cancelled():
+   self._async_wait()
+   return
+   raise
 
if isinstance(self.input_fd, int):
self.input_fd = os.fdopen(self.input_fd, 'rb', 0)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2021-03-07 Thread Zac Medico
commit: b08e21e5a7e07da02a2d64dac80635ca82a12979
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 16:00:54 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 16:01:47 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=b08e21e5

bin_entry_point: fix sys.argv[0] for non-python programs

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/bin_entry_point.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/portage/util/bin_entry_point.py 
b/lib/portage/util/bin_entry_point.py
index 7d359052e..3ead95d98 100644
--- a/lib/portage/util/bin_entry_point.py
+++ b/lib/portage/util/bin_entry_point.py
@@ -28,6 +28,7 @@ def bin_entry_point():
script_path,
] + sys.argv[1:]
os.execvp(sys.argv[0], sys.argv)
+   sys.argv[0] = script_path
os.execvp(sys.argv[0], sys.argv)
else:
print("File not found:", script_path, file=sys.stderr)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2021-03-07 Thread Zac Medico
commit: ce2247b4de0342d7802d4744904bb82870cac1ac
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 14:35:57 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 14:37:54 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ce2247b4

PipeLogger: Use async and await syntax

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/PipeLogger.py | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/lib/portage/util/_async/PipeLogger.py 
b/lib/portage/util/_async/PipeLogger.py
index e8203268c..b7c03043f 100644
--- a/lib/portage/util/_async/PipeLogger.py
+++ b/lib/portage/util/_async/PipeLogger.py
@@ -1,4 +1,4 @@
-# Copyright 2008-2020 Gentoo Authors
+# Copyright 2008-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import fcntl
@@ -9,7 +9,6 @@ import portage
 from portage import os, _encodings, _unicode_encode
 from portage.util.futures import asyncio
 from portage.util.futures._asyncio.streams import _writer
-from portage.util.futures.compat_coroutine import coroutine
 from portage.util.futures.unix_events import _set_nonblocking
 from _emerge.AbstractPollTask import AbstractPollTask
 
@@ -53,7 +52,7 @@ class PipeLogger(AbstractPollTask):
fcntl.fcntl(fd, fcntl.F_SETFL,
fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
 
-   self._io_loop_task = 
asyncio.ensure_future(self._io_loop(self.input_fd, loop=self.scheduler), 
loop=self.scheduler)
+   self._io_loop_task = 
asyncio.ensure_future(self._io_loop(self.input_fd), loop=self.scheduler)
self._io_loop_task.add_done_callback(self._io_loop_done)
self._registered = True
 
@@ -62,8 +61,7 @@ class PipeLogger(AbstractPollTask):
if self.returncode is None:
self.returncode = self._cancelled_returncode
 
-   @coroutine
-   def _io_loop(self, input_file, loop=None):
+   async def _io_loop(self, input_file):
background = self.background
stdout_fd = self.stdout_fd
log_file = self._log_file
@@ -77,7 +75,7 @@ class PipeLogger(AbstractPollTask):
future = self.scheduler.create_future()
self.scheduler.add_reader(fd, 
future.set_result, None)
try:
-   yield future
+   await future
finally:
# The loop and input file may have been 
closed.
if not self.scheduler.is_closed():
@@ -130,7 +128,7 @@ class PipeLogger(AbstractPollTask):
if self._log_file_nb:
# Use the _writer function which uses 
os.write, since the
# log_file.write method looses data 
when an EAGAIN occurs.
-   yield _writer(log_file, buf, 
loop=self.scheduler)
+   await _writer(log_file, buf)
else:
# For gzip.GzipFile instances, the 
above _writer function
# will not work because data written 
directly to the file



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2021-03-07 Thread Zac Medico
commit: 03b4af7b288589d0fa475af2a2c9f66022203649
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 14:43:59 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 14:44:16 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=03b4af7b

BuildLogger: Use async and await syntax

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/BuildLogger.py | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/lib/portage/util/_async/BuildLogger.py 
b/lib/portage/util/_async/BuildLogger.py
index 5a9c076b6..896e4d7b5 100644
--- a/lib/portage/util/_async/BuildLogger.py
+++ b/lib/portage/util/_async/BuildLogger.py
@@ -1,4 +1,4 @@
-# Copyright 2020 Gentoo Authors
+# Copyright 2020-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import functools
@@ -11,7 +11,6 @@ from portage.util import shlex_split
 from portage.util._async.PipeLogger import PipeLogger
 from portage.util._async.PopenProcess import PopenProcess
 from portage.util.futures import asyncio
-from portage.util.futures.compat_coroutine import coroutine
 
 class BuildLogger(AsynchronousTask):
"""
@@ -78,16 +77,15 @@ class BuildLogger(AsynchronousTask):
pipe_logger.start()
 
self._main_task_cancel = functools.partial(self._main_cancel, 
filter_proc, pipe_logger)
-   self._main_task = asyncio.ensure_future(self._main(filter_proc, 
pipe_logger, loop=self.scheduler), loop=self.scheduler)
+   self._main_task = asyncio.ensure_future(self._main(filter_proc, 
pipe_logger), loop=self.scheduler)
self._main_task.add_done_callback(self._main_exit)
 
-   @coroutine
-   def _main(self, filter_proc, pipe_logger, loop=None):
+   async def _main(self, filter_proc, pipe_logger):
try:
if pipe_logger.poll() is None:
-   yield pipe_logger.async_wait()
+   await pipe_logger.async_wait()
if filter_proc is not None and filter_proc.poll() is 
None:
-   yield filter_proc.async_wait()
+   await filter_proc.async_wait()
except asyncio.CancelledError:
self._main_cancel(filter_proc, pipe_logger)
raise



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/

2021-03-07 Thread Zac Medico
commit: 9eea2af22c9e51475a4adba57fdded3a2a88c886
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 14:18:44 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 14:37:46 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=9eea2af2

_writer: Use async and await syntax

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/_asyncio/streams.py | 13 +
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/lib/portage/util/futures/_asyncio/streams.py 
b/lib/portage/util/futures/_asyncio/streams.py
index ea5882dd3..7a8d4a3e0 100644
--- a/lib/portage/util/futures/_asyncio/streams.py
+++ b/lib/portage/util/futures/_asyncio/streams.py
@@ -1,4 +1,4 @@
-# Copyright 2018-2020 Gentoo Authors
+# Copyright 2018-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import errno
@@ -9,7 +9,6 @@ portage.proxy.lazyimport.lazyimport(globals(),
'_emerge.PipeReader:PipeReader',
'portage.util.futures:asyncio',
 )
-from portage.util.futures.compat_coroutine import coroutine
 
 
 def _reader(input_file, loop=None):
@@ -55,8 +54,7 @@ class _Reader:
self._pipe_reader = None
 
 
-@coroutine
-def _writer(output_file, content, loop=None):
+async def _writer(output_file, content, loop=DeprecationWarning):
"""
Asynchronously write bytes to output file. The output file is
assumed to be in non-blocking mode. If an EnvironmentError
@@ -68,10 +66,9 @@ def _writer(output_file, content, loop=None):
@type output_file: file object
@param content: content to write
@type content: bytes
-   @param loop: asyncio.AbstractEventLoop (or compatible)
-   @type loop: event loop
+   @param loop: deprecated
"""
-   loop = asyncio._wrap_loop(loop)
+   loop = asyncio.get_event_loop()
fd = output_file.fileno()
while content:
try:
@@ -82,7 +79,7 @@ def _writer(output_file, content, loop=None):
waiter = loop.create_future()
loop.add_writer(fd, lambda: waiter.done() or 
waiter.set_result(None))
try:
-   yield waiter
+   await waiter
finally:
# The loop and output file may have been closed.
if not loop.is_closed():



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_eventloop/

2021-03-07 Thread Zac Medico
commit: e0b6fbdf6543c19c63bbca007278d48003b807ad
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 09:28:08 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 09:28:37 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=e0b6fbdf

AsyncioEventLoop: remove obsolete supports_multiprocessing attribute

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_eventloop/asyncio_event_loop.py | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/lib/portage/util/_eventloop/asyncio_event_loop.py 
b/lib/portage/util/_eventloop/asyncio_event_loop.py
index b77728088..6dfac3569 100644
--- a/lib/portage/util/_eventloop/asyncio_event_loop.py
+++ b/lib/portage/util/_eventloop/asyncio_event_loop.py
@@ -1,4 +1,4 @@
-# Copyright 2018-2020 Gentoo Authors
+# Copyright 2018-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import os
@@ -17,11 +17,6 @@ class AsyncioEventLoop(_AbstractEventLoop):
event loop and is minimally compatible with _PortageEventLoop.
"""
 
-   # Use portage's internal event loop in subprocesses, as a workaround
-   # for https://bugs.python.org/issue22087, and also
-   # https://bugs.python.org/issue29703 which affects pypy3-5.10.1.
-   supports_multiprocessing = False
-
def __init__(self, loop=None):
loop = loop or _real_asyncio.get_event_loop()
self._loop = loop



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/

2021-03-07 Thread Zac Medico
commit: 20204fd8c29f3060da9891879721a54486247b0c
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 07:44:49 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 07:45:11 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=20204fd8

Remove unused _PortageEventLoop and _PortageChildWatcher

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/unix_events.py | 112 
 1 file changed, 112 deletions(-)

diff --git a/lib/portage/util/futures/unix_events.py 
b/lib/portage/util/futures/unix_events.py
index 030070b1b..4feee0a3b 100644
--- a/lib/portage/util/futures/unix_events.py
+++ b/lib/portage/util/futures/unix_events.py
@@ -18,61 +18,6 @@ from portage.util._eventloop.global_event_loop import (
 )
 
 
-class _PortageEventLoop(events.AbstractEventLoop):
-   """
-   Implementation of asyncio.AbstractEventLoop which wraps portage's
-   internal event loop.
-   """
-
-   def __init__(self, loop):
-   """
-   @type loop: EventLoop
-   @param loop: an instance of portage's internal event loop
-   """
-   self._loop = loop
-   self.run_until_complete = loop.run_until_complete
-   self.call_soon = loop.call_soon
-   self.call_soon_threadsafe = loop.call_soon_threadsafe
-   self.call_later = loop.call_later
-   self.call_at = loop.call_at
-   self.is_running = loop.is_running
-   self.is_closed = loop.is_closed
-   self.close = loop.close
-   self.create_future = loop.create_future
-   self.add_reader = loop.add_reader
-   self.remove_reader = loop.remove_reader
-   self.add_writer = loop.add_writer
-   self.remove_writer = loop.remove_writer
-   self.run_in_executor = loop.run_in_executor
-   self.time = loop.time
-   self.default_exception_handler = loop.default_exception_handler
-   self.call_exception_handler = loop.call_exception_handler
-   self.set_debug = loop.set_debug
-   self.get_debug = loop.get_debug
-
-   @property
-   def _asyncio_child_watcher(self):
-   """
-   In order to avoid accessing the internal _loop attribute, 
portage
-   internals should use this property when possible.
-
-   @rtype: asyncio.AbstractChildWatcher
-   @return: the internal event loop's AbstractChildWatcher 
interface
-   """
-   return self._loop._asyncio_child_watcher
-
-   @property
-   def _asyncio_wrapper(self):
-   """
-   In order to avoid accessing the internal _loop attribute, 
portage
-   internals should use this property when possible.
-
-   @rtype: asyncio.AbstractEventLoop
-   @return: the internal event loop's AbstractEventLoop interface
-   """
-   return self
-
-
 if hasattr(os, 'set_blocking'):
def _set_nonblocking(fd):
os.set_blocking(fd, False)
@@ -83,63 +28,6 @@ else:
fcntl.fcntl(fd, fcntl.F_SETFL, flags)
 
 
-class _PortageChildWatcher(AbstractChildWatcher):
-   def __init__(self, loop):
-   """
-   @type loop: EventLoop
-   @param loop: an instance of portage's internal event loop
-   """
-   self._loop = loop
-   self._callbacks = {}
-
-   def close(self):
-   pass
-
-   def __enter__(self):
-   return self
-
-   def __exit__(self, a, b, c):
-   pass
-
-   def _child_exit(self, pid, status, data):
-   self._callbacks.pop(pid)
-   callback, args = data
-   callback(pid, self._compute_returncode(status), *args)
-
-   def _compute_returncode(self, status):
-   if os.WIFSIGNALED(status):
-   return -os.WTERMSIG(status)
-   if os.WIFEXITED(status):
-   return os.WEXITSTATUS(status)
-   return status
-
-   def add_child_handler(self, pid, callback, *args):
-   """
-   Register a new child handler.
-
-   Arrange for callback(pid, returncode, *args) to be called when
-   process 'pid' terminates. Specifying another callback for the 
same
-   process replaces the previous handler.
-   """
-   source_id = self._callbacks.get(pid)
-   if source_id is not None:
-   self._loop.source_remove(source_id)
-   self._callbacks[pid] = self._loop.child_watch_add(
-   pid, self._child_exit, data=(callback, args))
-
-   def remove_child_handler(self, pid):
-   """
-   Removes the handler for 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/

2021-03-06 Thread Zac Medico
commit: b4f6a5126437afc5bb07ed0a42a0eb8a5745ef90
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 07:18:58 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 07:32:04 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=b4f6a512

Removed unused portage.util.futures.events

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/events.py  | 186 
 lib/portage/util/futures/unix_events.py |  26 +
 2 files changed, 3 insertions(+), 209 deletions(-)

diff --git a/lib/portage/util/futures/events.py 
b/lib/portage/util/futures/events.py
deleted file mode 100644
index 85032fcdf..0
--- a/lib/portage/util/futures/events.py
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright 2018 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-__all__ = (
-   'AbstractEventLoopPolicy',
-   'AbstractEventLoop',
-)
-
-import socket
-import subprocess
-
-from asyncio.events import (
-   AbstractEventLoop as _AbstractEventLoop,
-   AbstractEventLoopPolicy as _AbstractEventLoopPolicy,
-)
-
-
-class AbstractEventLoopPolicy(_AbstractEventLoopPolicy):
-   """Abstract policy for accessing the event loop."""
-
-   def get_event_loop(self):
-   raise NotImplementedError
-
-   def set_event_loop(self, loop):
-   raise NotImplementedError
-
-   def new_event_loop(self):
-   raise NotImplementedError
-
-   def get_child_watcher(self):
-   raise NotImplementedError
-
-   def set_child_watcher(self, watcher):
-   raise NotImplementedError
-
-
-class AbstractEventLoop(_AbstractEventLoop):
-   """Abstract event loop."""
-
-   def run_forever(self):
-   raise NotImplementedError
-
-   def run_until_complete(self, future):
-   raise NotImplementedError
-
-   def stop(self):
-   raise NotImplementedError
-
-   def is_running(self):
-   raise NotImplementedError
-
-   def is_closed(self):
-   raise NotImplementedError
-
-   def close(self):
-   raise NotImplementedError
-
-   def shutdown_asyncgens(self):
-   raise NotImplementedError
-
-   def _timer_handle_cancelled(self, handle):
-   raise NotImplementedError
-
-   def call_soon(self, callback, *args):
-   return self.call_later(0, callback, *args)
-
-   def call_later(self, delay, callback, *args):
-   raise NotImplementedError
-
-   def call_at(self, when, callback, *args):
-   raise NotImplementedError
-
-   def time(self):
-   raise NotImplementedError
-
-   def create_future(self):
-   raise NotImplementedError
-
-   def create_task(self, coro):
-   raise NotImplementedError
-
-   def call_soon_threadsafe(self, callback, *args):
-   raise NotImplementedError
-
-   def run_in_executor(self, executor, func, *args):
-   raise NotImplementedError
-
-   def set_default_executor(self, executor):
-   raise NotImplementedError
-
-   def getaddrinfo(self, host, port, family=0, type=0, proto=0, flags=0): 
# pylint: disable=redefined-builtin
-   raise NotImplementedError
-
-   def getnameinfo(self, sockaddr, flags=0):
-   raise NotImplementedError
-
-   def create_connection(self, protocol_factory, host=None, port=None,
- ssl=None, family=0, proto=0, 
flags=0, sock=None,
- local_addr=None, 
server_hostname=None):
-   raise NotImplementedError
-
-   def create_server(self, protocol_factory, host=None, port=None,
- family=socket.AF_UNSPEC, 
flags=socket.AI_PASSIVE,
- sock=None, backlog=100, ssl=None, 
reuse_address=None,
- reuse_port=None):
-   raise NotImplementedError
-
-   def create_unix_connection(self, protocol_factory, path,
-  ssl=None, sock=None,
-  
server_hostname=None):
-   raise NotImplementedError
-
-   def create_unix_server(self, protocol_factory, path,
-  sock=None, backlog=100, 
ssl=None):
-   raise NotImplementedError
-
-   def create_datagram_endpoint(self, protocol_factory,
-
local_addr=None, remote_addr=None,
-family=0, 
proto=0, flags=0,
-
reuse_address=None, reuse_port=None,
-   

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/

2021-03-06 Thread Zac Medico
commit: a8e0ddccf90a4f6dd0b4c0ae0832b4abb1f35b04
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 07:29:35 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 07:31:11 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a8e0ddcc

Remove unused _EventLoopFuture class

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/futures.py | 156 +---
 1 file changed, 1 insertion(+), 155 deletions(-)

diff --git a/lib/portage/util/futures/futures.py 
b/lib/portage/util/futures/futures.py
index 839c767a7..3f239890a 100644
--- a/lib/portage/util/futures/futures.py
+++ b/lib/portage/util/futures/futures.py
@@ -1,4 +1,4 @@
-# Copyright 2016-2018 Gentoo Foundation
+# Copyright 2016-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 #
 # For compatibility with python versions which do not have the
@@ -19,157 +19,3 @@ from asyncio import (
InvalidStateError,
TimeoutError,
 )
-# pylint: enable=redefined-builtin
-
-import portage
-portage.proxy.lazyimport.lazyimport(globals(),
-   
'portage.util._eventloop.global_event_loop:global_event_loop@_global_event_loop',
-)
-
-_PENDING = 'PENDING'
-_CANCELLED = 'CANCELLED'
-_FINISHED = 'FINISHED'
-
-class _EventLoopFuture:
-   """
-   This class provides (a subset of) the asyncio.Future interface, for
-   use with the EventLoop class, because EventLoop is currently
-   missing some of the asyncio.AbstractEventLoop methods that
-   asyncio.Future requires.
-   """
-
-   # Class variables serving as defaults for instance variables.
-   _state = _PENDING
-   _result = None
-   _exception = None
-   _loop = None
-
-   def __init__(self, loop=None):
-   """Initialize the future.
-
-   The optional loop argument allows explicitly setting the event
-   loop object used by the future. If it's not provided, the 
future uses
-   the default event loop.
-   """
-   if loop is None:
-   self._loop = _global_event_loop()
-   else:
-   self._loop = loop
-   self._callbacks = []
-
-   def cancel(self):
-   """Cancel the future and schedule callbacks.
-
-   If the future is already done or cancelled, return False.  
Otherwise,
-   change the future's state to cancelled, schedule the callbacks 
and
-   return True.
-   """
-   if self._state != _PENDING:
-   return False
-   self._state = _CANCELLED
-   self._schedule_callbacks()
-   return True
-
-   def _schedule_callbacks(self):
-   """Internal: Ask the event loop to call all callbacks.
-
-   The callbacks are scheduled to be called as soon as possible. 
Also
-   clears the callback list.
-   """
-   callbacks = self._callbacks[:]
-   if not callbacks:
-   return
-
-   self._callbacks[:] = []
-   for callback in callbacks:
-   self._loop.call_soon(callback, self)
-
-   def cancelled(self):
-   """Return True if the future was cancelled."""
-   return self._state == _CANCELLED
-
-   def done(self):
-   """Return True if the future is done.
-
-   Done means either that a result / exception are available, or 
that the
-   future was cancelled.
-   """
-   return self._state != _PENDING
-
-   def result(self):
-   """Return the result this future represents.
-
-   If the future has been cancelled, raises CancelledError.  If the
-   future's result isn't yet available, raises InvalidStateError.  
If
-   the future is done and has an exception set, this exception is 
raised.
-   """
-   if self._state == _CANCELLED:
-   raise CancelledError()
-   if self._state != _FINISHED:
-   raise InvalidStateError('Result is not ready.')
-   if self._exception is not None:
-   raise self._exception
-   return self._result
-
-   def exception(self):
-   """Return the exception that was set on this future.
-
-   The exception (or None if no exception was set) is returned 
only if
-   the future is done.  If the future has been cancelled, raises
-   CancelledError.  If the future isn't done yet, raises
-   InvalidStateError.
-   """
-   if self._state == _CANCELLED:
-   raise CancelledError
-   if self._state != _FINISHED:
-   raise InvalidStateError('Exception is 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/

2021-03-06 Thread Zac Medico
commit: ed685eb659fccf6e4031d12fa8a59c3829ef1155
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 06:56:36 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 07:01:44 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ed685eb6

Removed unused portage.util.futures.transports

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/transports.py  |  87 --
 lib/portage/util/futures/unix_events.py | 492 +---
 2 files changed, 2 insertions(+), 577 deletions(-)

diff --git a/lib/portage/util/futures/transports.py 
b/lib/portage/util/futures/transports.py
deleted file mode 100644
index 016ecbef8..0
--- a/lib/portage/util/futures/transports.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright 2018 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-from asyncio.transports import Transport as _Transport
-
-
-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': 'protocol.pause_writing() 
failed',
-   'exception': exc,
-   'transport': self,
-   'protocol': self._protocol,
-   })
-
-   def _maybe_resume_protocol(self):
-   if (self._protocol_paused and
-   self.get_write_buffer_size() <= self._low_water):
-   self._protocol_paused = False
-   try:
-   self._protocol.resume_writing()
-   except Exception as exc:
-   self._loop.call_exception_handler({
-   'message': 'protocol.resume_writing() 
failed',
-   'exception': exc,
-   'transport': self,
-   'protocol': self._protocol,
-   })
-
-   def get_write_buffer_limits(self):
-   return (self._low_water, self._high_water)
-
-   def _set_write_buffer_limits(self, high=None, low=None):
-   if high is None:
-   if low is None:
-   high = 64*1024
-   else:
-   high = 4*low
-   if low is None:
-   low = high // 4
-   if not high >= low >= 0:
-   raise ValueError('high (%r) must be >= low (%r) must be 
>= 0' %
-(high, low))
-   self._high_water = high
-   self._low_water = low
-
-   def set_write_buffer_limits(self, high=None, low=None):
-   self._set_write_buffer_limits(high=high, low=low)
-   self._maybe_pause_protocol()
-
-   def get_write_buffer_size(self):
-   raise NotImplementedError

diff --git a/lib/portage/util/futures/unix_events.py 
b/lib/portage/util/futures/unix_events.py
index 16a9e12b7..9d5445943 100644
--- a/lib/portage/util/futures/unix_events.py
+++ b/lib/portage/util/futures/unix_events.py
@@ -1,4 +1,4 @@
-# Copyright 2018 Gentoo Foundation
+# Copyright 2018-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 __all__ = (
@@ -7,32 +7,15 @@ __all__ = (
 )
 
 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/

2021-03-06 Thread Zac Medico
commit: 15049a041909f85b02a52f5b1938c6dd4171c9e3
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 03:03:40 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 05:12:48 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=15049a04

Removed unused portage.util.futures._asyncio.tasks

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/_asyncio/__init__.py | 46 ++---
 lib/portage/util/futures/_asyncio/tasks.py| 96 ---
 2 files changed, 19 insertions(+), 123 deletions(-)

diff --git a/lib/portage/util/futures/_asyncio/__init__.py 
b/lib/portage/util/futures/_asyncio/__init__.py
index 207e7205d..4643697e0 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -25,7 +25,16 @@ import types
 import weakref
 
 import asyncio as _real_asyncio
-from asyncio.subprocess import Process
+# pylint: disable=redefined-builtin
+from asyncio import (
+   ALL_COMPLETED,
+   CancelledError,
+   FIRST_COMPLETED,
+   FIRST_EXCEPTION,
+   Future,
+   InvalidStateError,
+   TimeoutError,
+)
 
 try:
import threading
@@ -38,20 +47,6 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.util.futures:compat_coroutine@_compat_coroutine',
 )
 from portage.util._eventloop.asyncio_event_loop import AsyncioEventLoop as 
_AsyncioEventLoop
-# pylint: disable=redefined-builtin
-from portage.util.futures.futures import (
-   CancelledError,
-   Future,
-   InvalidStateError,
-   TimeoutError,
-)
-# pylint: enable=redefined-builtin
-from portage.util.futures._asyncio.tasks import (
-   ALL_COMPLETED,
-   FIRST_COMPLETED,
-   FIRST_EXCEPTION,
-   wait,
-)
 
 
 _lock = threading.Lock()
@@ -131,20 +126,17 @@ def create_subprocess_exec(*args, **kwargs):
# Python 3.4 and later implement PEP 446, which makes newly
# created file descriptors non-inheritable by default.
kwargs.setdefault('close_fds', False)
-   if isinstance(loop._asyncio_wrapper, _AsyncioEventLoop):
-   # Use the real asyncio create_subprocess_exec (loop argument
-   # is deprecated since since Python 3.8).
-   return _real_asyncio.create_subprocess_exec(*args, **kwargs)
-
-   result = loop.create_future()
+   # Use the real asyncio create_subprocess_exec (loop argument
+   # is deprecated since since Python 3.8).
+   return ensure_future(_real_asyncio.create_subprocess_exec(*args, 
**kwargs), loop=loop)
 
-   result.set_result(Process(subprocess.Popen(
-   args,
-   stdin=kwargs.pop('stdin', None),
-   stdout=kwargs.pop('stdout', None),
-   stderr=kwargs.pop('stderr', None), **kwargs), loop))
 
-   return result
+def wait(futures, loop=None, timeout=None, return_when=ALL_COMPLETED):
+   """
+   Wraps asyncio.wait() and omits the loop argument which is not
+   supported since python 3.10.
+   """
+   return _real_asyncio.wait(futures, timeout=timeout, 
return_when=return_when)
 
 
 def iscoroutinefunction(func):

diff --git a/lib/portage/util/futures/_asyncio/tasks.py 
b/lib/portage/util/futures/_asyncio/tasks.py
deleted file mode 100644
index c9db3146e..0
--- a/lib/portage/util/futures/_asyncio/tasks.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright 2018-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-___all___ = (
-   'ALL_COMPLETED',
-   'FIRST_COMPLETED',
-   'FIRST_EXCEPTION',
-   'wait',
-)
-
-from asyncio import ALL_COMPLETED, FIRST_COMPLETED, FIRST_EXCEPTION
-
-import portage
-portage.proxy.lazyimport.lazyimport(globals(),
-   'portage.util.futures:asyncio',
-)
-
-def wait(futures, loop=None, timeout=None, return_when=ALL_COMPLETED):
-   """
-   Use portage's internal EventLoop to emulate asyncio.wait:
-   https://docs.python.org/3/library/asyncio-task.html#asyncio.wait
-
-   @param futures: futures to wait for
-   @type futures: asyncio.Future (or compatible)
-   @param timeout: number of seconds to wait (wait indefinitely if
-   not specified)
-   @type timeout: int or float
-   @param return_when: indicates when this function should return, must
-   be one of the constants ALL_COMPLETED, FIRST_COMPLETED, or
-   FIRST_EXCEPTION (default is ALL_COMPLETED)
-   @type return_when: object
-   @param loop: event loop
-   @type loop: EventLoop
-   @return: tuple of (done, pending).
-   @rtype: asyncio.Future (or compatible)
-   """
-   loop = asyncio._wrap_loop(loop)
-   result_future = loop.create_future()
-   _Waiter(futures, timeout, return_when, result_future, loop)
-   return result_future
-
-
-class _Waiter:
-   def __init__(self, futures, timeout, return_when, result_future, loop):
-   

[gentoo-commits] proj/portage:master commit in: lib/portage/util/_eventloop/

2021-03-06 Thread Zac Medico
commit: 4cf221840bb980305b48a329c693dd1a310d5248
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Mar  7 02:48:57 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Mar  7 02:49:34 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=4cf22184

Remove unused PollSelectAdapter and PollConstants classes

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_eventloop/PollConstants.py | 17 --
 lib/portage/util/_eventloop/PollSelectAdapter.py | 74 
 2 files changed, 91 deletions(-)

diff --git a/lib/portage/util/_eventloop/PollConstants.py 
b/lib/portage/util/_eventloop/PollConstants.py
deleted file mode 100644
index c5700d108..0
--- a/lib/portage/util/_eventloop/PollConstants.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 1999-2009 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-import select
-class PollConstants:
-
-   """
-   Provides POLL* constants that are equivalent to those from the
-   select module, for use by PollSelectAdapter.
-   """
-
-   names = ("POLLIN", "POLLPRI", "POLLOUT", "POLLERR", "POLLHUP", 
"POLLNVAL")
-   v = 1
-   for k in names:
-   locals()[k] = getattr(select, k, v)
-   v *= 2
-   del k, v

diff --git a/lib/portage/util/_eventloop/PollSelectAdapter.py 
b/lib/portage/util/_eventloop/PollSelectAdapter.py
deleted file mode 100644
index c4637a352..0
--- a/lib/portage/util/_eventloop/PollSelectAdapter.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright 1999-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-import select
-
-from .PollConstants import PollConstants
-
-class PollSelectAdapter:
-
-   """
-   Use select to emulate a poll object, for
-   systems that don't support poll().
-   """
-
-   def __init__(self):
-   self._registered = {}
-   self._select_args = [[], [], []]
-
-   def register(self, fd, *args):
-   """
-   Only POLLIN is currently supported!
-   """
-   if len(args) > 1:
-   raise TypeError(
-   "register expected at most 2 arguments, got " + 
\
-   repr(1 + len(args)))
-
-   eventmask = PollConstants.POLLIN | \
-   PollConstants.POLLPRI | PollConstants.POLLOUT
-   if args:
-   eventmask = args[0]
-
-   self._registered[fd] = eventmask
-   self._select_args = None
-
-   def unregister(self, fd):
-   self._select_args = None
-   del self._registered[fd]
-
-   def poll(self, *args):
-   if len(args) > 1:
-   raise TypeError(
-   "poll expected at most 2 arguments, got " + \
-   repr(1 + len(args)))
-
-   timeout = None
-   if args:
-   timeout = args[0]
-
-   select_args = self._select_args
-   if select_args is None:
-   select_args = [list(self._registered), [], []]
-
-   if timeout is not None:
-   select_args = select_args[:]
-   # Translate poll() timeout args to select() timeout 
args:
-   #
-   #  | units| value(s) for indefinite 
block
-   # 
-|--|--
-   #   poll   | milliseconds | omitted, negative, or None
-   # 
-|--|--
-   #   select | seconds  | omitted
-   # 
-|--|--
-
-   if timeout is not None and timeout < 0:
-   timeout = None
-   if timeout is not None:
-   select_args.append(timeout / 1000)
-
-   select_events = select.select(*select_args)
-   poll_events = []
-   for fd in select_events[0]:
-   poll_events.append((fd, PollConstants.POLLIN))
-   return poll_events



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2021-03-06 Thread Zac Medico
commit: 4f60b68fca342cc92ed7729d241e2c60132876e8
Author: Zac Medico  gentoo  org>
AuthorDate: Sat Mar  6 20:20:30 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sat Mar  6 20:20:46 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=4f60b68f

bin_entry_point: handle versioned python shebangs

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/bin_entry_point.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/portage/util/bin_entry_point.py 
b/lib/portage/util/bin_entry_point.py
index ce95231eb..7d359052e 100644
--- a/lib/portage/util/bin_entry_point.py
+++ b/lib/portage/util/bin_entry_point.py
@@ -20,7 +20,7 @@ def bin_entry_point():
if os.access(script_path, os.X_OK):
with open(script_path, "rt") as f:
shebang = f.readline()
-   python_match = re.search(r"/python\s+([^/]*)\s+$", shebang)
+   python_match = re.search(r"/python[\d\.]*\s+([^/]*)\s+$", 
shebang)
if python_match:
sys.argv = [
os.path.join(os.path.dirname(sys.argv[0]), 
"python"),



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_eventloop/

2021-03-06 Thread Zac Medico
commit: 05e9b76523569f17c3cbf7465758656c3beb0be8
Author: Zac Medico  gentoo  org>
AuthorDate: Sat Mar  6 10:39:31 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sat Mar  6 10:41:06 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=05e9b765

Remove unused EventLoop class

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_eventloop/EventLoop.py | 1153 --
 1 file changed, 1153 deletions(-)

diff --git a/lib/portage/util/_eventloop/EventLoop.py 
b/lib/portage/util/_eventloop/EventLoop.py
deleted file mode 100644
index ff2b73255..0
--- a/lib/portage/util/_eventloop/EventLoop.py
+++ /dev/null
@@ -1,1153 +0,0 @@
-# Copyright 1999-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-import asyncio as _real_asyncio
-import collections
-import errno
-import functools
-import logging
-import os
-import select
-import signal
-import time
-import traceback
-
-try:
-   import fcntl
-except ImportError:
-   #  http://bugs.jython.org/issue1074
-   fcntl = None
-
-try:
-   import threading
-except ImportError:
-   import dummy_threading as threading
-
-import portage
-portage.proxy.lazyimport.lazyimport(globals(),
-   'portage.util.futures:asyncio',
-   'portage.util.futures.executor.fork:ForkExecutor',
-   
'portage.util.futures.unix_events:_PortageEventLoop,_PortageChildWatcher',
-)
-
-from portage.util import writemsg_level
-from ..SlotObject import SlotObject
-from .PollConstants import PollConstants
-from .PollSelectAdapter import PollSelectAdapter
-
-class EventLoop:
-   """
-   An event loop, intended to be compatible with the GLib event loop.
-   Call the iteration method in order to execute one iteration of the
-   loop. The idle_add and timeout_add methods serve as thread-safe
-   means to interact with the loop's thread.
-   """
-
-   supports_multiprocessing = True
-
-   # TODO: Find out why SIGCHLD signals aren't delivered during poll
-   # calls, forcing us to wakeup in order to receive them.
-   _sigchld_interval = 250
-
-   class _child_callback_class(SlotObject):
-   __slots__ = ("callback", "data", "pid", "source_id")
-
-   class _idle_callback_class(SlotObject):
-   __slots__ = ("_args", "_callback", "_cancelled")
-
-   class _io_handler_class(SlotObject):
-   __slots__ = ("args", "callback", "f", "source_id")
-
-   class _timeout_handler_class(SlotObject):
-   __slots__ = ("args", "function", "calling", "interval", 
"source_id",
-   "timestamp")
-
-   class _handle:
-   """
-   A callback wrapper object, compatible with asyncio.Handle.
-   """
-   __slots__ = ("_callback_id", "_loop")
-
-   def __init__(self, callback_id, loop):
-   self._callback_id = callback_id
-   self._loop = loop
-
-   def cancel(self):
-   """
-   Cancel the call. If the callback is already canceled or 
executed,
-   this method has no effect.
-   """
-   self._loop.source_remove(self._callback_id)
-
-   class _call_soon_callback:
-   """
-   Wraps a call_soon callback, and always returns False, since 
these
-   callbacks are only supposed to run once.
-   """
-   __slots__ = ("_args", "_callback")
-
-   def __init__(self, callback, args):
-   self._callback = callback
-   self._args = args
-
-   def __call__(self):
-   self._callback(*self._args)
-   return False
-
-   class _selector_callback:
-   """
-   Wraps an callback, and always returns True, for callbacks that
-   are supposed to run repeatedly.
-   """
-   __slots__ = ("_args", "_callbacks")
-
-   def __init__(self, callbacks):
-   self._callbacks = callbacks
-
-   def __call__(self, fd, event):
-   for callback, mask in self._callbacks:
-   if event & mask:
-   callback()
-   return True
-
-   def __init__(self, main=True):
-   """
-   @param main: If True then this is a singleton instance for use
-   in the main thread, otherwise it is a local instance 
which
-   can safely be use in a non-main thread (default is 
True, so
-   that global_event_loop does not need constructor 
arguments)
-   @type main: bool
-   """
-   self._use_signal = main and fcntl is not None
-   

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/

2021-03-06 Thread Zac Medico
commit: 1e843f853a9afe82d599e6ab09064147ddc1d271
Author: Matt Turner  gentoo  org>
AuthorDate: Thu Mar  4 19:24:58 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sat Mar  6 09:06:53 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=1e843f85

Use asyncio.subprocess.Process directly

With no need to support Python 2, we can remove our private
implementation.

Signed-off-by: Matt Turner  gentoo.org>
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/_asyncio/__init__.py |   8 +-
 lib/portage/util/futures/_asyncio/process.py  | 116 --
 2 files changed, 4 insertions(+), 120 deletions(-)

diff --git a/lib/portage/util/futures/_asyncio/__init__.py 
b/lib/portage/util/futures/_asyncio/__init__.py
index 5590963f1..207e7205d 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -25,6 +25,7 @@ import types
 import weakref
 
 import asyncio as _real_asyncio
+from asyncio.subprocess import Process
 
 try:
import threading
@@ -45,7 +46,6 @@ from portage.util.futures.futures import (
TimeoutError,
 )
 # pylint: enable=redefined-builtin
-from portage.util.futures._asyncio.process import _Process
 from portage.util.futures._asyncio.tasks import (
ALL_COMPLETED,
FIRST_COMPLETED,
@@ -124,8 +124,8 @@ def create_subprocess_exec(*args, **kwargs):
@type loop: event loop
@type kwargs: varies
@param kwargs: subprocess.Popen parameters
-   @rtype: asyncio.Future (or compatible)
-   @return: subset of asyncio.subprocess.Process interface
+   @rtype: asyncio.subprocess.Process (or compatible)
+   @return: asyncio.subprocess.Process interface
"""
loop = _wrap_loop(kwargs.pop('loop', None))
# Python 3.4 and later implement PEP 446, which makes newly
@@ -138,7 +138,7 @@ def create_subprocess_exec(*args, **kwargs):
 
result = loop.create_future()
 
-   result.set_result(_Process(subprocess.Popen(
+   result.set_result(Process(subprocess.Popen(
args,
stdin=kwargs.pop('stdin', None),
stdout=kwargs.pop('stdout', None),

diff --git a/lib/portage/util/futures/_asyncio/process.py 
b/lib/portage/util/futures/_asyncio/process.py
deleted file mode 100644
index 275c9031a..0
--- a/lib/portage/util/futures/_asyncio/process.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright 2018-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-import os
-
-import portage
-portage.proxy.lazyimport.lazyimport(globals(),
-   'portage.util.futures:asyncio',
-   'portage.util.futures.unix_events:_set_nonblocking',
-)
-from portage.util.futures._asyncio.streams import _reader, _writer
-from portage.util.futures.compat_coroutine import coroutine, coroutine_return
-
-
-class _Process:
-   """
-   Emulate a subset of the asyncio.subprocess.Process interface,
-   for python2.
-   """
-   def __init__(self, proc, loop):
-   """
-   @param proc: process instance
-   @type proc: subprocess.Popen
-   @param loop: asyncio.AbstractEventLoop (or compatible)
-   @type loop: event loop
-   """
-   self._proc = proc
-   self._loop = loop
-   self.terminate = proc.terminate
-   self.kill = proc.kill
-   self.send_signal = proc.send_signal
-   self.pid = proc.pid
-   self._waiters = []
-   loop._asyncio_child_watcher.\
-   add_child_handler(self.pid, self._proc_exit)
-
-   @property
-   def returncode(self):
-   return self._proc.returncode
-
-   @coroutine
-   def communicate(self, input=None, loop=None): # pylint: 
disable=redefined-builtin
-   """
-   Read data from stdout and stderr, until end-of-file is reached.
-   Wait for process to terminate.
-
-   @param input: stdin content to write
-   @type input: bytes
-   @return: tuple (stdout_data, stderr_data)
-   @rtype: asyncio.Future (or compatible)
-   """
-   loop = asyncio._wrap_loop(loop or self._loop)
-   futures = []
-   for input_file in (self._proc.stdout, self._proc.stderr):
-   if input_file is None:
-   future = loop.create_future()
-   future.set_result(None)
-   else:
-   future = _reader(input_file, loop=loop)
-   futures.append(future)
-
-   writer = None
-   if input is not None:
-   if self._proc.stdin is None:
-   raise TypeError('communicate: expected file or 
int, got 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2021-03-03 Thread Zac Medico
commit: ce86ddecf168af06926f95092f29fa19c1f3885a
Author: Zac Medico  gentoo  org>
AuthorDate: Wed Mar  3 10:46:02 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Mar  3 12:09:58 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ce86ddec

bin_entry_point: rewrite python shebangs for venv

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/bin_entry_point.py | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/lib/portage/util/bin_entry_point.py 
b/lib/portage/util/bin_entry_point.py
index 7f2ee3849..ce95231eb 100644
--- a/lib/portage/util/bin_entry_point.py
+++ b/lib/portage/util/bin_entry_point.py
@@ -3,6 +3,7 @@
 
 __all__ = ["bin_entry_point"]
 
+import re
 import sys
 
 from portage.const import PORTAGE_BIN_PATH
@@ -17,7 +18,16 @@ def bin_entry_point():
"""
script_path = os.path.join(PORTAGE_BIN_PATH, 
os.path.basename(sys.argv[0]))
if os.access(script_path, os.X_OK):
-   sys.argv[0] = script_path
+   with open(script_path, "rt") as f:
+   shebang = f.readline()
+   python_match = re.search(r"/python\s+([^/]*)\s+$", shebang)
+   if python_match:
+   sys.argv = [
+   os.path.join(os.path.dirname(sys.argv[0]), 
"python"),
+   python_match.group(1),
+   script_path,
+   ] + sys.argv[1:]
+   os.execvp(sys.argv[0], sys.argv)
os.execvp(sys.argv[0], sys.argv)
else:
print("File not found:", script_path, file=sys.stderr)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, /

2021-02-28 Thread Zac Medico
commit: 695be424d3ef3bba6cf26f6ff70df066e1cd248c
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Feb 28 07:34:13 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Feb 28 09:49:05 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=695be424

setup.py: add entry_points when installed with pip

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/bin_entry_point.py | 24 
 setup.py| 27 +--
 2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/lib/portage/util/bin_entry_point.py 
b/lib/portage/util/bin_entry_point.py
new file mode 100644
index 0..7f2ee3849
--- /dev/null
+++ b/lib/portage/util/bin_entry_point.py
@@ -0,0 +1,24 @@
+# Copyright 2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+__all__ = ["bin_entry_point"]
+
+import sys
+
+from portage.const import PORTAGE_BIN_PATH
+from portage import os
+
+
+def bin_entry_point():
+   """
+   Adjust sys.argv[0] to point to a script in PORTAGE_BIN_PATH, and
+   then execute the script, in order to implement entry_points when
+   portage has been installed by pip.
+   """
+   script_path = os.path.join(PORTAGE_BIN_PATH, 
os.path.basename(sys.argv[0]))
+   if os.access(script_path, os.X_OK):
+   sys.argv[0] = script_path
+   os.execvp(sys.argv[0], sys.argv)
+   else:
+   print("File not found:", script_path, file=sys.stderr)
+   return 127

diff --git a/setup.py b/setup.py
index 96d9932e0..7d6fb6609 100755
--- a/setup.py
+++ b/setup.py
@@ -2,6 +2,7 @@
 # Copyright 1998-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
+from distutils import sysconfig
 from distutils.core import setup, Command, Extension
 from distutils.command.build import build
 from distutils.command.build_ext import build_ext as _build_ext
@@ -19,6 +20,7 @@ from distutils.util import change_root, subst_vars
 import codecs
 import collections
 import glob
+import itertools
 import os
 import os.path
 import platform
@@ -26,6 +28,12 @@ import re
 import subprocess
 import sys
 
+autodetect_pip = os.path.basename(os.environ.get("_", "")) == "pip" or 
os.path.basename(
+   os.path.dirname(__file__)
+).startswith("pip-")
+venv_prefix = "" if sys.prefix == sys.base_prefix else sys.prefix
+create_entry_points = bool(autodetect_pip or venv_prefix)
+eprefix = sysconfig.get_python_lib() if venv_prefix else ""
 
 # TODO:
 # - smarter rebuilds of docs w/ 'install_docbook' and 'install_apidoc'.
@@ -220,8 +228,9 @@ class x_build_scripts_custom(build_scripts):
self.scripts = x_scripts[self.dir_name]
else:
self.scripts = set(self.scripts)
-   for other_files in x_scripts.values():
-   
self.scripts.difference_update(other_files)
+   if not (create_entry_points and self.dir_name 
== "portage"):
+   for other_files in x_scripts.values():
+   
self.scripts.difference_update(other_files)
 
def run(self):
# group scripts by subdirectory
@@ -471,9 +480,10 @@ class x_install_lib(install_lib):
'VERSION': self.distribution.get_version(),
})
rewrite_file('portage/const.py', {
-   'PORTAGE_BASE_PATH': self.portage_base,
-   'PORTAGE_BIN_PATH': self.portage_bindir,
-   'PORTAGE_CONFIG_PATH': self.portage_confdir,
+   'EPREFIX': eprefix,
+   'GLOBAL_CONFIG_PATH': self.portage_confdir,
+   'PORTAGE_BASE_PATH': eprefix + self.portage_base,
+   'PORTAGE_BIN_PATH': eprefix + self.portage_bindir,
})
 
return ret
@@ -675,7 +685,12 @@ setup(
['$portage_base/bin', ['bin/deprecated-path']],
['$sysconfdir/portage/repo.postsync.d', 
['cnf/repo.postsync.d/example']],
],
-
+   entry_points={
+   "console_scripts": [
+   
"{}=portage.util.bin_entry_point:bin_entry_point".format(os.path.basename(path))
+   for path in 
itertools.chain.from_iterable(x_scripts.values())
+   ],
+   } if create_entry_points else {},
ext_modules = [Extension(name=n, sources=m,
extra_compile_args=['-D_FILE_OFFSET_BITS=64',
'-D_LARGEFILE_SOURCE', '-D_LARGEFILE64_SOURCE'])



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2021-02-25 Thread Zac Medico
commit: 061a895f7b0a310b374dff03af622b11146337d4
Author: Zac Medico  gentoo  org>
AuthorDate: Thu Feb 25 10:14:18 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Thu Feb 25 10:18:02 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=061a895f

iter_parents: prevent infinite loop after empty os.path.dirname result

Reported-by: dkjii  cock.li
Bug: https://bugs.gentoo.org/772806
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/path.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/portage/util/path.py b/lib/portage/util/path.py
index a0b96c7f3..f174bd71f 100644
--- a/lib/portage/util/path.py
+++ b/lib/portage/util/path.py
@@ -1,4 +1,4 @@
-# Copyright 2014 Gentoo Foundation
+# Copyright 2014-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import errno
@@ -45,4 +45,6 @@ def iter_parents(path):
yield path
while path != os.sep:
path = os.path.dirname(path)
+   if not path:
+   break
yield path



[gentoo-commits] proj/portage:master commit in: lib/portage/util/, lib/portage/tests/util/, bin/

2021-02-24 Thread Zac Medico
commit: d121ea57ed5310d84328be27f10a8556b0a7d7ba
Author: Zac Medico  gentoo  org>
AuthorDate: Fri May  8 23:32:49 2020 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Feb 24 15:27:47 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=d121ea57

Add emirrordist shelve dump/restore (bug 721680)

Bug: https://bugs.gentoo.org/721680
Signed-off-by: Zac Medico  gentoo.org>

 bin/shelve-utils  | 32 +++
 lib/portage/tests/util/test_shelve.py | 60 +++
 lib/portage/util/shelve.py| 58 +
 3 files changed, 150 insertions(+)

diff --git a/bin/shelve-utils b/bin/shelve-utils
new file mode 100755
index 0..5088ab5eb
--- /dev/null
+++ b/bin/shelve-utils
@@ -0,0 +1,32 @@
+#!/usr/bin/python -b
+# Copyright 2020-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import argparse
+import sys
+
+import portage
+from portage.util.shelve import dump, restore
+
+
+def main(argv=None):
+   parser = argparse.ArgumentParser(prog="shelve-utils")
+   subparsers = parser.add_subparsers(help="sub-command help")
+
+   dump_command = subparsers.add_parser("dump", help="dump shelve 
database")
+   dump_command.add_argument("src", help="input shelve file")
+   dump_command.add_argument("dest", help="output pickle file")
+   dump_command.set_defaults(func=dump)
+
+   restore_command = subparsers.add_parser("restore", help="restore shelve 
database")
+   restore_command.add_argument("src", help="input pickle file")
+   restore_command.add_argument("dest", help="output shelve file")
+   restore_command.set_defaults(func=restore)
+
+   args = parser.parse_args(args=portage._decode_argv(argv or 
sys.argv)[1:])
+   args.func(args)
+
+
+if __name__ == "__main__":
+   portage.util.initialize_logger()
+   main(argv=sys.argv)

diff --git a/lib/portage/tests/util/test_shelve.py 
b/lib/portage/tests/util/test_shelve.py
new file mode 100644
index 0..60592c6fb
--- /dev/null
+++ b/lib/portage/tests/util/test_shelve.py
@@ -0,0 +1,60 @@
+# Copyright 2020-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import argparse
+import os
+import shutil
+import tempfile
+import time
+
+from portage.tests import TestCase
+from portage.util.shelve import dump, open_shelve, restore
+
+
+class ShelveUtilsTestCase(TestCase):
+
+   TEST_DATA = (
+   # distfiles_db
+   {
+   "portage-2.3.89.tar.bz2": "sys-apps/portage-2.3.89",
+   "portage-2.3.99.tar.bz2": "sys-apps/portage-2.3.99",
+   },
+   # deletion_db
+   {
+   "portage-2.3.89.tar.bz2": time.time(),
+   "portage-2.3.99.tar.bz2": time.time(),
+   },
+   # recycle_db
+   {
+   "portage-2.3.89.tar.bz2": (0, time.time()),
+   "portage-2.3.99.tar.bz2": (0, time.time()),
+   },
+   )
+
+   def test_dump_restore(self):
+   for data in self.TEST_DATA:
+   tmpdir = tempfile.mkdtemp()
+   try:
+   dump_args = argparse.Namespace(
+   src=os.path.join(tmpdir, "shelve_file"),
+   dest=os.path.join(tmpdir, 
"pickle_file"),
+   )
+   db = open_shelve(dump_args.src, flag="c")
+   for k, v in data.items():
+   db[k] = v
+   db.close()
+   dump(dump_args)
+
+   os.unlink(dump_args.src)
+   restore_args = argparse.Namespace(
+   dest=dump_args.src,
+   src=dump_args.dest,
+   )
+   restore(restore_args)
+
+   db = open_shelve(restore_args.dest, flag="r")
+   for k, v in data.items():
+   self.assertEqual(db[k], v)
+   db.close()
+   finally:
+   shutil.rmtree(tmpdir)

diff --git a/lib/portage/util/shelve.py b/lib/portage/util/shelve.py
new file mode 100644
index 0..f070ee753
--- /dev/null
+++ b/lib/portage/util/shelve.py
@@ -0,0 +1,58 @@
+# Copyright 2020-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import logging
+import pickle
+import shelve
+
+
+def open_shelve(db_file, flag="r"):
+   """
+   The optional flag parameter has the same interpretation as the flag
+   

[gentoo-commits] proj/portage:master commit in: lib/portage/util/_async/

2021-02-14 Thread Zac Medico
commit: becd2d4f82ab212fd752848d673a72722af209ff
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Feb 15 04:28:40 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Feb 15 04:35:56 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=becd2d4f

PopenProcess: use call_soon for _async_waipid in _start

Use call_soon to delay the add_child_handler call that
_async_waipid will trigger, so that it will occur after
the event loop is running.

Bug: https://bugs.gentoo.org/770712
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_async/PopenProcess.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/portage/util/_async/PopenProcess.py 
b/lib/portage/util/_async/PopenProcess.py
index c1931327a..7f4e17ea2 100644
--- a/lib/portage/util/_async/PopenProcess.py
+++ b/lib/portage/util/_async/PopenProcess.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2018 Gentoo Foundation
+# Copyright 2012-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from _emerge.SubProcess import SubProcess
@@ -13,7 +13,7 @@ class PopenProcess(SubProcess):
self._registered = True
 
if self.pipe_reader is None:
-   self._async_waitpid()
+   self.scheduler.call_soon(self._async_waitpid)
else:
try:
self.pipe_reader.scheduler = self.scheduler



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2021-01-18 Thread Zac Medico
commit: 4f77b1ca80a7ae7987c0d3e0ef988b3c06d18744
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Jan 19 00:50:13 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Tue Jan 19 00:50:26 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=4f77b1ca

ProxyManager: remove unused loop parameter

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/socks5.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/portage/util/socks5.py b/lib/portage/util/socks5.py
index ddf6bb4d0..4aa08e1ab 100644
--- a/lib/portage/util/socks5.py
+++ b/lib/portage/util/socks5.py
@@ -73,7 +73,7 @@ class ProxyManager:
"""
return self.socket_path is not None
 
-   async def ready(self, loop=None):
+   async def ready(self):
"""
Wait for the proxy socket to become ready. This method is a 
coroutine.
"""



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/, lib/portage/repository/storage/

2021-01-18 Thread Zac Medico
commit: 5346ae96d8d4b141454fe802a74e855e3e246593
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Jan 18 14:37:17 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Jan 18 15:03:28 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=5346ae96

RepoStorageInterface: Use async and await syntax

Signed-off-by: Zac Medico  gentoo.org>

 .../repository/storage/hardlink_quarantine.py  | 45 +++--
 lib/portage/repository/storage/hardlink_rcu.py | 57 +-
 lib/portage/repository/storage/inplace.py  | 27 +++---
 lib/portage/repository/storage/interface.py| 17 +++
 lib/portage/util/futures/_sync_decorator.py|  6 +--
 5 files changed, 56 insertions(+), 96 deletions(-)

diff --git a/lib/portage/repository/storage/hardlink_quarantine.py 
b/lib/portage/repository/storage/hardlink_quarantine.py
index 165ab8324..bab34997b 100644
--- a/lib/portage/repository/storage/hardlink_quarantine.py
+++ b/lib/portage/repository/storage/hardlink_quarantine.py
@@ -1,4 +1,4 @@
-# Copyright 2018 Gentoo Foundation
+# Copyright 2018-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from portage import os
@@ -7,10 +7,6 @@ from portage.repository.storage.interface import (
RepoStorageInterface,
 )
 from portage.util.futures import asyncio
-from portage.util.futures.compat_coroutine import (
-   coroutine,
-   coroutine_return,
-)
 
 from _emerge.SpawnProcess import SpawnProcess
 
@@ -38,60 +34,55 @@ class HardlinkQuarantineRepoStorage(RepoStorageInterface):
self._spawn_kwargs = spawn_kwargs
self._current_update = None
 
-   @coroutine
-   def _check_call(self, cmd, loop=None):
+   async def _check_call(self, cmd):
"""
Run cmd and raise RepoStorageException on failure.
 
@param cmd: command to executre
@type cmd: list
"""
-   p = SpawnProcess(args=cmd, scheduler=asyncio._wrap_loop(loop), 
**self._spawn_kwargs)
+   p = SpawnProcess(args=cmd, scheduler=asyncio.get_event_loop(), 
**self._spawn_kwargs)
p.start()
-   if (yield p.async_wait()) != os.EX_OK:
+   if await p.async_wait() != os.EX_OK:
raise RepoStorageException('command exited with status 
{}: {}'.\
format(p.returncode, ' '.join(cmd)))
 
-   @coroutine
-   def init_update(self, loop=None):
+   async def init_update(self):
update_location = os.path.join(self._user_location, 
'.tmp-unverified-download-quarantine')
-   yield self._check_call(['rm', '-rf', update_location], 
loop=loop)
+   await self._check_call(['rm', '-rf', update_location])
 
# Use  rsync --link-dest to hardlink a files into 
self._update_location,
# since cp -l is not portable.
-   yield self._check_call(['rsync', '-a', '--link-dest', 
self._user_location,
+   await self._check_call(['rsync', '-a', '--link-dest', 
self._user_location,
'--exclude=/distfiles', '--exclude=/local', 
'--exclude=/lost+found', '--exclude=/packages',
'--exclude', 
'/{}'.format(os.path.basename(update_location)),
-   self._user_location + '/', update_location + '/'], 
loop=loop)
+   self._user_location + '/', update_location + '/'])
 
self._update_location = update_location
 
-   coroutine_return(self._update_location)
+   return self._update_location
 
@property
-   def current_update(self, loop=None):
+   def current_update(self):
if self._update_location is None:
raise RepoStorageException('current update does not 
exist')
return self._update_location
 
-   @coroutine
-   def commit_update(self, loop=None):
+   async def commit_update(self):
update_location = self.current_update
self._update_location = None
-   yield self._check_call(['rsync', '-a', '--delete',
+   await self._check_call(['rsync', '-a', '--delete',
'--exclude=/distfiles', '--exclude=/local', 
'--exclude=/lost+found', '--exclude=/packages',
'--exclude', 
'/{}'.format(os.path.basename(update_location)),
-   update_location + '/', self._user_location + '/'], 
loop=loop)
+   update_location + '/', self._user_location + '/'])
 
-   yield self._check_call(['rm', '-rf', update_location], 
loop=loop)
+   await self._check_call(['rm', '-rf', update_location])
 
-   @coroutine
-   def abort_update(self, loop=None):
+   async def abort_update(self):
if 

[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/

2021-01-18 Thread Zac Medico
commit: 8d962cb5cc97a5092ff45446c0f8da55b27d2434
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Jan 18 10:09:05 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Jan 18 11:18:43 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=8d962cb5

coroutine: do not require loop parameter

The loop parameter is not needed since global_event_loop now
returns the running event loop for the current thread.

Bug: https://bugs.gentoo.org/737698
Bug: https://bugs.gentoo.org/763339
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/compat_coroutine.py | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/lib/portage/util/futures/compat_coroutine.py 
b/lib/portage/util/futures/compat_coroutine.py
index 9a0c5c1c8..3e8dcec02 100644
--- a/lib/portage/util/futures/compat_coroutine.py
+++ b/lib/portage/util/futures/compat_coroutine.py
@@ -1,4 +1,4 @@
-# Copyright 2018 Gentoo Foundation
+# Copyright 2018-2021 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 import functools
@@ -68,10 +68,6 @@ def _generator_future(generator_func, *args, **kwargs):
the default event loop.
"""
loop = kwargs.get('loop')
-   if loop is None and portage._internal_caller:
-   # Require an explicit loop parameter, in order to support
-   # local event loops (bug 737698).
-   raise AssertionError("Missing required argument 'loop'")
loop = asyncio._wrap_loop(loop)
result = loop.create_future()
_GeneratorTask(generator_func(*args, **kwargs), result, loop=loop)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/_eventloop/, lib/portage/util/futures/_asyncio/

2021-01-11 Thread Zac Medico
commit: 386178481eb86ac603cd90ef1bb6ac6b68e51c50
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Jan  4 09:14:36 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Jan 11 09:36:48 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=38617848

global_event_loop: return running loop for current thread

Like asyncio.get_event_loop(), return the running loop for the
current thread if there is one, and otherwise construct a new
one if needed. This allows the _safe_loop function to become
synonymous with the global_event_loop function.

For the case of "loop running in non-main thread" of API
consumer, this change makes portage compatible with PEP
492 coroutines with async and await syntax. Portage
internals can safely begin using async / await syntax instead
of compat_coroutine.

Bug: https://bugs.gentoo.org/763339
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_eventloop/global_event_loop.py | 28 +++---
 lib/portage/util/futures/_asyncio/__init__.py| 30 +---
 2 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/lib/portage/util/_eventloop/global_event_loop.py 
b/lib/portage/util/_eventloop/global_event_loop.py
index 413011178..cb7a13078 100644
--- a/lib/portage/util/_eventloop/global_event_loop.py
+++ b/lib/portage/util/_eventloop/global_event_loop.py
@@ -1,28 +1,6 @@
-# Copyright 2012-2020 Gentoo Authors
+# Copyright 2012-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-import portage
-from portage.util._eventloop.asyncio_event_loop import AsyncioEventLoop
+__all__ = ('global_event_loop',)
 
-_instances = {}
-
-
-def global_event_loop():
-   """
-   Get a global EventLoop (or compatible object) instance which
-   belongs exclusively to the current process.
-   """
-
-   pid = portage.getpid()
-   instance = _instances.get(pid)
-   if instance is not None:
-   return instance
-
-   constructor = AsyncioEventLoop
-
-   # Use the _asyncio_wrapper attribute, so that unit tests can compare
-   # the reference to one retured from _wrap_loop(), since they should
-   # not close the loop if it refers to a global event loop.
-   instance = constructor()._asyncio_wrapper
-   _instances[pid] = instance
-   return instance
+from portage.util.futures._asyncio import _safe_loop as global_event_loop

diff --git a/lib/portage/util/futures/_asyncio/__init__.py 
b/lib/portage/util/futures/_asyncio/__init__.py
index d39f31786..5590963f1 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2018-2020 Gentoo Authors
+# Copyright 2018-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 __all__ = (
@@ -37,9 +37,6 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.util.futures:compat_coroutine@_compat_coroutine',
 )
 from portage.util._eventloop.asyncio_event_loop import AsyncioEventLoop as 
_AsyncioEventLoop
-from portage.util._eventloop.global_event_loop import (
-   global_event_loop as _global_event_loop,
-)
 # pylint: disable=redefined-builtin
 from portage.util.futures.futures import (
CancelledError,
@@ -238,7 +235,7 @@ def _wrap_loop(loop=None):
# The default loop returned by _wrap_loop should be consistent
# with global_event_loop, in order to avoid accidental registration
# of callbacks with a loop that is not intended to run.
-   loop = loop or _global_event_loop()
+   loop = loop or _safe_loop()
return (loop if hasattr(loop, '_asyncio_wrapper')
else _AsyncioEventLoop(loop=loop))
 
@@ -267,13 +264,15 @@ def _safe_loop():
@rtype: asyncio.AbstractEventLoop (or compatible)
@return: event loop instance
"""
-   if portage._internal_caller or threading.current_thread() is 
threading.main_thread():
-   return _global_event_loop()
+   loop = _get_running_loop()
+   if loop is not None:
+   return loop
 
thread_key = threading.get_ident()
with _thread_weakrefs.lock:
if _thread_weakrefs.pid != portage.getpid():
_thread_weakrefs.pid = portage.getpid()
+   _thread_weakrefs.mainloop = None
_thread_weakrefs.loops = weakref.WeakValueDictionary()
try:
loop = _thread_weakrefs.loops[thread_key]
@@ -283,9 +282,23 @@ def _safe_loop():
except RuntimeError:

_real_asyncio.set_event_loop(_real_asyncio.new_event_loop())
loop = _thread_weakrefs.loops[thread_key] = 
_AsyncioEventLoop()
+
+   if _thread_weakrefs.mainloop is None and threading.current_thread() is 
threading.main_thread():
+   _thread_weakrefs.mainloop = loop
+

[gentoo-commits] proj/portage:master commit in: lib/portage/util/_eventloop/

2021-01-10 Thread Zac Medico
commit: eeeb70bf50994c08ebcddac94474105f0635360c
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Jan 11 06:46:49 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Jan 11 07:28:28 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=eeeb70bf

AsyncioEventLoop: wrap child watcher for thread safety (bug 764905)

Use a child watcher wrapper to deliver the callbacks via the
call_soon_threadsafe method, since documentation for the asycio
AbstractChildWatcher class says that callbacks must be thread
safe.

Bug: https://bugs.gentoo.org/764905
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/_eventloop/asyncio_event_loop.py | 30 ++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/lib/portage/util/_eventloop/asyncio_event_loop.py 
b/lib/portage/util/_eventloop/asyncio_event_loop.py
index 4d7047ae8..b77728088 100644
--- a/lib/portage/util/_eventloop/asyncio_event_loop.py
+++ b/lib/portage/util/_eventloop/asyncio_event_loop.py
@@ -6,6 +6,7 @@ import signal
 
 import asyncio as _real_asyncio
 from asyncio.events import AbstractEventLoop as _AbstractEventLoop
+from asyncio.unix_events import AbstractChildWatcher as _AbstractChildWatcher
 
 import portage
 
@@ -47,6 +48,7 @@ class AsyncioEventLoop(_AbstractEventLoop):
self.set_debug = loop.set_debug
self.get_debug = loop.get_debug
self._wakeup_fd = -1
+   self._child_watcher = None
 
if portage._internal_caller:

loop.set_exception_handler(self._internal_caller_exception_handler)
@@ -87,7 +89,9 @@ class AsyncioEventLoop(_AbstractEventLoop):
@rtype: asyncio.AbstractChildWatcher
@return: the internal event loop's AbstractChildWatcher 
interface
"""
-   return _real_asyncio.get_child_watcher()
+   if self._child_watcher is None:
+   self._child_watcher = 
_ChildWatcherThreadSafetyWrapper(self, _real_asyncio.get_child_watcher())
+   return self._child_watcher
 
@property
def _asyncio_wrapper(self):
@@ -126,3 +130,27 @@ class AsyncioEventLoop(_AbstractEventLoop):
except ValueError:
# This is intended to fail when not called in 
the main thread.
pass
+
+
+class _ChildWatcherThreadSafetyWrapper(_AbstractChildWatcher):
+   def __init__(self, loop, real_watcher):
+   self._loop = loop
+   self._real_watcher = real_watcher
+
+   def close(self):
+   pass
+
+   def __enter__(self):
+   return self
+
+   def __exit__(self, a, b, c):
+   pass
+
+   def _child_exit(self, pid, status, callback, *args):
+   self._loop.call_soon_threadsafe(callback, pid, status, *args)
+
+   def add_child_handler(self, pid, callback, *args):
+   self._real_watcher.add_child_handler(pid, self._child_exit, 
callback, *args)
+
+   def remove_child_handler(self, pid):
+   return self._real_watcher.remove_child_handler(pid)



[gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/

2021-01-04 Thread Zac Medico
commit: 7efa7ecfe07737239be593b2c32e497cc1d2f154
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Jan  4 08:54:52 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Mon Jan  4 08:57:09 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=7efa7ecf

_Retry: Use ensure_future for self._current_task

Use ensure_future for compatibility with PEP 492 coroutines
with async and await syntax.

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/futures/retry.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/portage/util/futures/retry.py 
b/lib/portage/util/futures/retry.py
index 4092f60d6..31cc161da 100644
--- a/lib/portage/util/futures/retry.py
+++ b/lib/portage/util/futures/retry.py
@@ -1,4 +1,4 @@
-# Copyright 2018 Gentoo Foundation
+# Copyright 2018-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 __all__ = (
@@ -113,7 +113,7 @@ class _Retry:
 
def _begin_try(self):
self._tries += 1
-   self._current_task = self._func()
+   self._current_task = asyncio.ensure_future(self._func(), 
loop=self._loop)
self._current_task.add_done_callback(self._try_done)
if self._try_timeout is not None:
self._try_timeout_handle = self._loop.call_later(



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2021-01-01 Thread Zac Medico
commit: 84b555bb33f24b7628bebbaa16fe43325b7823a9
Author: Zac Medico  gentoo  org>
AuthorDate: Sat Jan  2 01:18:30 2021 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sat Jan  2 01:18:43 2021 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=84b555bb

lib/portage/util/__init__.py: Fix useless-return

Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/__init__.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/portage/util/__init__.py b/lib/portage/util/__init__.py
index bedcbcfe6..b0922bf09 100644
--- a/lib/portage/util/__init__.py
+++ b/lib/portage/util/__init__.py
@@ -1293,7 +1293,6 @@ class atomic_ofstream(AbstractContextManager, 
ObjectProxy):
self.abort()
else:
self.close()
-   return None
 
def _get_target(self):
return object.__getattribute__(self, '_file')



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2020-12-30 Thread Zac Medico
commit: 1574ae127b270739c4293271c959d1d981684906
Author: Florian Schmaus  geekplace  eu>
AuthorDate: Fri Dec 18 18:46:39 2020 +
Commit: Zac Medico  gentoo  org>
CommitDate: Thu Dec 31 01:43:22 2020 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=1574ae12

env_update: use "with statement" on atomic_ofstream

Signed-off-by: Florian Schmaus  geekplace.eu>
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/env_update.py | 30 --
 1 file changed, 12 insertions(+), 18 deletions(-)

diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index dec086cf8..5588931a8 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -342,18 +342,17 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env,
 
#create /etc/profile.env for bash support
profile_env_path = os.path.join(eroot, "etc", "profile.env")
-   outfile = atomic_ofstream(profile_env_path)
-   outfile.write(penvnotice)
-
-   env_keys = [x for x in env if x != "LDPATH"]
-   env_keys.sort()
-   for k in env_keys:
-   v = env[k]
-   if v.startswith('$') and not v.startswith('${'):
-   outfile.write("export %s=$'%s'\n" % (k, v[1:]))
-   else:
-   outfile.write("export %s='%s'\n" % (k, v))
-   outfile.close()
+   with atomic_ofstream(profile_env_path) as outfile:
+   outfile.write(penvnotice)
+
+   env_keys = [x for x in env if x != "LDPATH"]
+   env_keys.sort()
+   for k in env_keys:
+   v = env[k]
+   if v.startswith('$') and not v.startswith('${'):
+   outfile.write("export %s=$'%s'\n" % (k, v[1:]))
+   else:
+   outfile.write("export %s='%s'\n" % (k, v))
 
# Create the systemd user environment configuration file
# /etc/environment.d/10-gentoo-env.conf with the
@@ -363,8 +362,7 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env,
 
systemd_gentoo_env_path = os.path.join(systemd_environment_dir,
"10-gentoo-env.conf")
-   systemd_gentoo_env = atomic_ofstream(systemd_gentoo_env_path)
-   try:
+   with atomic_ofstream(systemd_gentoo_env_path) as systemd_gentoo_env:
senvnotice = notice + "\n\n"
systemd_gentoo_env.write(senvnotice)
 
@@ -384,10 +382,6 @@ def _env_update(makelinks, target_root, prev_mtimes, 
contents, env,
line = f"{env_key}={env_key_value}\n"
 
systemd_gentoo_env.write(line)
-   except:
-   systemd_gentoo_env.abort()
-   raise
-   systemd_gentoo_env.close()
 
#create /etc/csh.env for (t)csh support
outfile = atomic_ofstream(os.path.join(eroot, "etc", "csh.env"))



[gentoo-commits] proj/portage:master commit in: lib/portage/util/

2020-12-30 Thread Zac Medico
commit: e93e6d65fa1ca75f676a227f7918f8b6d747425c
Author: Florian Schmaus  geekplace  eu>
AuthorDate: Fri Dec 18 18:46:38 2020 +
Commit: Zac Medico  gentoo  org>
CommitDate: Thu Dec 31 01:40:42 2020 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=e93e6d65

Make atomic_ofstream a Context Manager

This allows using a "with statement" together with instances of
atomic_ofstream. Allowing for more readable, less error prone and
shorter code.

Signed-off-by: Florian Schmaus  geekplace.eu>
Signed-off-by: Zac Medico  gentoo.org>

 lib/portage/util/__init__.py | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/lib/portage/util/__init__.py b/lib/portage/util/__init__.py
index 0412b2b59..bedcbcfe6 100644
--- a/lib/portage/util/__init__.py
+++ b/lib/portage/util/__init__.py
@@ -11,6 +11,7 @@ __all__ = ['apply_permissions', 'apply_recursive_permissions',
'stack_dicts', 'stack_lists', 'unique_array', 'unique_everseen', 
'varexpand',
'write_atomic', 'writedict', 'writemsg', 'writemsg_level', 
'writemsg_stdout']
 
+from contextlib import AbstractContextManager
 from copy import deepcopy
 import errno
 import io
@@ -1246,7 +1247,7 @@ def apply_secpass_permissions(filename, uid=-1, gid=-1, 
mode=-1, mask=-1,
stat_cached=stat_cached, follow_links=follow_links)
return all_applied
 
-class atomic_ofstream(ObjectProxy):
+class atomic_ofstream(AbstractContextManager, ObjectProxy):
"""Write a file atomically via os.rename().  Atomic replacement prevents
interprocess interference and prevents corruption of the target
file when the write is interrupted (for example, when an 'out of space'
@@ -1287,6 +1288,13 @@ class atomic_ofstream(ObjectProxy):
encoding=_encodings['fs'], errors='strict'),
mode=mode, **kargs))
 
+   def __exit__(self, exc_type, exc_val, exc_tb):
+   if exc_type is not None:
+   self.abort()
+   else:
+   self.close()
+   return None
+
def _get_target(self):
return object.__getattribute__(self, '_file')
 



  1   2   >