aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/portage/__init__.py')
-rw-r--r--lib/portage/__init__.py156
1 files changed, 76 insertions, 80 deletions
diff --git a/lib/portage/__init__.py b/lib/portage/__init__.py
index 13af8da09..aa81bdb4c 100644
--- a/lib/portage/__init__.py
+++ b/lib/portage/__init__.py
@@ -1,13 +1,13 @@
-# Copyright 1998-2021 Gentoo Authors
+# Copyright 1998-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# pylint: disable=ungrouped-imports
-VERSION = "HEAD"
-
# ===========================================================================
# START OF IMPORTS -- START OF IMPORTS -- START OF IMPORTS -- START OF IMPORT
# ===========================================================================
+from portage import installation
+
try:
import asyncio
import sys
@@ -16,7 +16,7 @@ try:
if not hasattr(errno, "ESTALE"):
# ESTALE may not be defined on some systems, such as interix.
errno.ESTALE = -1
- import multiprocessing.util
+ import functools
import re
import types
import platform
@@ -48,11 +48,10 @@ except ImportError as e:
sys.stderr.write(
"!!! gone wrong. Here is the information we got for this exception:\n"
)
- sys.stderr.write(" " + str(e) + "\n\n")
+ sys.stderr.write(f" {e}\n\n")
raise
try:
-
import portage.proxy.lazyimport
import portage.proxy as proxy
@@ -93,7 +92,7 @@ try:
+ "doebuild_environment,spawn,spawnebuild",
"portage.package.ebuild.config:autouse,best_from_dict,"
+ "check_config_instance,config",
- "portage.package.ebuild.deprecated_profile_check:" + "deprecated_profile_check",
+ "portage.package.ebuild.deprecated_profile_check:deprecated_profile_check",
"portage.package.ebuild.digestcheck:digestcheck",
"portage.package.ebuild.digestgen:digestgen",
"portage.package.ebuild.fetch:fetch",
@@ -124,6 +123,7 @@ try:
+ "cpv_getkey@getCPFromCPV,endversion_keys,"
+ "suffix_value@endversion,pkgcmp,pkgsplit,vercmp,ververify",
"portage.xpak",
+ "portage.gpkg",
"subprocess",
"time",
)
@@ -183,9 +183,10 @@ except ImportError as e:
"!!! There is a README.RESCUE file that details the steps required to perform\n"
)
sys.stderr.write("!!! a recovery of portage.\n")
- sys.stderr.write(" " + str(e) + "\n\n")
+ sys.stderr.write(f" {e}\n\n")
raise
+utf8_mode = sys.getfilesystemencoding() == "utf-8"
# We use utf_8 encoding everywhere. Previously, we used
# sys.getfilesystemencoding() for the 'merge' encoding, but that had
@@ -259,23 +260,21 @@ class _unicode_func_wrapper:
self._encoding = encoding
def _process_args(self, args, kwargs):
-
encoding = self._encoding
wrapped_args = [
_unicode_encode(x, encoding=encoding, errors="strict") for x in args
]
if kwargs:
- wrapped_kwargs = dict(
- (k, _unicode_encode(v, encoding=encoding, errors="strict"))
+ wrapped_kwargs = {
+ k: _unicode_encode(v, encoding=encoding, errors="strict")
for k, v in kwargs.items()
- )
+ }
else:
wrapped_kwargs = {}
return (wrapped_args, wrapped_kwargs)
def __call__(self, *args, **kwargs):
-
encoding = self._encoding
wrapped_args, wrapped_kwargs = self._process_args(args, kwargs)
@@ -321,6 +320,9 @@ class _unicode_module_wrapper:
object.__setattr__(self, "_cache", cache)
def __getattribute__(self, attr):
+ if utf8_mode:
+ return getattr(object.__getattribute__(self, "_mod"), attr)
+
cache = object.__getattribute__(self, "_cache")
if cache is not None:
result = cache.get(attr)
@@ -347,30 +349,6 @@ class _unicode_module_wrapper:
return result
-class _eintr_func_wrapper:
- """
- Wraps a function and handles EINTR by calling the function as
- many times as necessary (until it returns without raising EINTR).
- """
-
- __slots__ = ("_func",)
-
- def __init__(self, func):
- self._func = func
-
- def __call__(self, *args, **kwargs):
-
- while True:
- try:
- rval = self._func(*args, **kwargs)
- break
- except EnvironmentError as e:
- if e.errno != errno.EINTR:
- raise
-
- return rval
-
-
import os as _os
_os_overrides = {
@@ -378,14 +356,11 @@ _os_overrides = {
id(_os.popen): _os.popen,
id(_os.read): _os.read,
id(_os.system): _os.system,
- id(_os.waitpid): _eintr_func_wrapper(_os.waitpid),
+ id(_os.waitpid): _os.waitpid,
}
-try:
- _os_overrides[id(_os.mkfifo)] = _os.mkfifo
-except AttributeError:
- pass # Jython
+_os_overrides[id(_os.mkfifo)] = _os.mkfifo
if hasattr(_os, "statvfs"):
_os_overrides[id(_os.statvfs)] = _os.statvfs
@@ -408,7 +383,7 @@ try:
_selinux_merge = _unicode_module_wrapper(_selinux, encoding=_encodings["merge"])
except (ImportError, OSError) as e:
if isinstance(e, OSError):
- sys.stderr.write("!!! SELinux not loaded: %s\n" % str(e))
+ sys.stderr.write(f"!!! SELinux not loaded: {e}\n")
del e
_selinux = None
selinux = None
@@ -446,7 +421,7 @@ class _ForkWatcher:
_ForkWatcher.hook(_ForkWatcher)
-multiprocessing.util.register_after_fork(_ForkWatcher, _ForkWatcher.hook)
+os.register_at_fork(after_in_child=functools.partial(_ForkWatcher.hook, _ForkWatcher))
def getpid():
@@ -481,10 +456,10 @@ def _shell_quote(s):
"""
if _shell_quote_re.search(s) is None:
return s
- for letter in '\\"$`':
+ for letter in r"\"$`":
if letter in s:
- s = s.replace(letter, "\\" + letter)
- return '"%s"' % s
+ s = s.replace(letter, rf"\{letter}")
+ return f'"{s}"'
bsd_chflags = None
@@ -497,9 +472,9 @@ if platform.system() in ("FreeBSD",):
def load_mod(name):
- modname = ".".join(name.split(".")[:-1])
- mod = __import__(modname)
components = name.split(".")
+ modname = ".".join(components[:-1])
+ mod = __import__(modname)
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
@@ -533,7 +508,7 @@ def abssymlink(symlink, target=None):
mylink = os.readlink(symlink)
if mylink[0] != "/":
mydir = os.path.dirname(symlink)
- mylink = mydir + "/" + mylink
+ mylink = f"{mydir}/{mylink}"
return os.path.normpath(mylink)
@@ -545,19 +520,22 @@ _deprecated_eapis = frozenset(
"3_pre1",
"3_pre2",
"4_pre1",
- "4-python",
"4-slot-abi",
"5_pre1",
"5_pre2",
- "5-progress",
"6_pre1",
"7_pre1",
]
)
+
+from itertools import chain
+
_supported_eapis = frozenset(
- [str(x) for x in range(portage.const.EAPI + 1)]
- + list(_testing_eapis)
- + list(_deprecated_eapis)
+ chain(
+ (str(x) for x in range(portage.const.EAPI + 1)),
+ _testing_eapis,
+ _deprecated_eapis,
+ )
)
@@ -567,7 +545,6 @@ def _eapi_is_deprecated(eapi):
def eapi_is_supported(eapi):
eapi = str(eapi).strip()
-
return eapi in _supported_eapis
@@ -596,7 +573,7 @@ def _parse_eapi_ebuild_head(f):
def _movefile(src, dest, **kwargs):
"""Calls movefile and raises a PortageException if an error occurs."""
if movefile(src, dest, **kwargs) is None:
- raise portage.exception.PortageException("mv '%s' '%s'" % (src, dest))
+ raise portage.exception.PortageException(f"mv '{src}' '{dest}'")
auxdbkeys = (
@@ -641,6 +618,15 @@ class _trees_dict(dict):
def create_trees(
config_root=None, target_root=None, trees=None, env=None, sysroot=None, eprefix=None
):
+ if utf8_mode:
+ config_root = (
+ os.fsdecode(config_root) if isinstance(config_root, bytes) else config_root
+ )
+ target_root = (
+ os.fsdecode(target_root) if isinstance(target_root, bytes) else target_root
+ )
+ sysroot = os.fsdecode(sysroot) if isinstance(sysroot, bytes) else sysroot
+ eprefix = os.fsdecode(eprefix) if isinstance(eprefix, bytes) else eprefix
if trees is None:
trees = _trees_dict()
@@ -667,12 +653,10 @@ def create_trees(
if settings["ROOT"] == "/" and settings["EPREFIX"] == const.EPREFIX:
trees._running_eroot = trees._target_eroot
else:
-
# When ROOT != "/" we only want overrides from the calling
# environment to apply to the config that's associated
# with ROOT != "/", so pass a nearly empty dict for the env parameter.
- clean_env = {}
- for k in (
+ env_sequence = (
"PATH",
"PORTAGE_GRPNAME",
"PORTAGE_REPOSITORIES",
@@ -686,18 +670,29 @@ def create_trees(
"https_proxy",
"no_proxy",
"__PORTAGE_TEST_HARDLINK_LOCKS",
- ):
- v = settings.get(k)
- if v is not None:
- clean_env[k] = v
+ )
+ env = ((k, settings.get(k)) for k in env_sequence)
+ clean_env = {k: v for k, v in env if v is not None}
+
if depcachedir is not None:
clean_env["PORTAGE_DEPCACHEDIR"] = depcachedir
- settings = config(
+ mysettings = config(
config_root=None, target_root="/", env=clean_env, sysroot="/", eprefix=None
)
- settings.lock()
- trees._running_eroot = settings["EROOT"]
- myroots.append((settings["EROOT"], settings))
+ mysettings.lock()
+ trees._running_eroot = mysettings["EROOT"]
+ myroots.append((mysettings["EROOT"], mysettings))
+
+ if settings["SYSROOT"] != "/" and settings["SYSROOT"] != settings["ROOT"]:
+ mysettings = config(
+ config_root=settings["SYSROOT"],
+ target_root=settings["SYSROOT"],
+ env=clean_env,
+ sysroot=settings["SYSROOT"],
+ eprefix="",
+ )
+ mysettings.lock()
+ myroots.append((mysettings["EROOT"], mysettings))
for myroot, mysettings in myroots:
trees[myroot] = portage.util.LazyItemsDict(trees.get(myroot, {}))
@@ -712,7 +707,7 @@ def create_trees(
return trees
-if VERSION == "HEAD":
+if installation.TYPE == installation.TYPES.SOURCE:
class _LazyVersion(proxy.objectproxy.ObjectProxy):
def _get_target(self):
@@ -725,12 +720,11 @@ if VERSION == "HEAD":
BASH_BINARY,
"-c",
(
- "cd %s ; git describe --match 'portage-*' || exit $? ; "
- + 'if [ -n "`git diff-index --name-only --diff-filter=M HEAD`" ] ; '
- + "then echo modified ; git rev-list --format=%%ct -n 1 HEAD ; fi ; "
- + "exit 0"
- )
- % _shell_quote(PORTAGE_BASE_PATH),
+ f"cd {_shell_quote(PORTAGE_BASE_PATH)} ; git describe --match 'portage-*' || exit $? ; "
+ 'if [ -n "`git diff-index --name-only --diff-filter=M HEAD`" ] ; '
+ "then echo modified ; git rev-list --format=%%ct -n 1 HEAD ; fi ; "
+ "exit 0"
+ ),
]
cmd = [
_unicode_encode(x, encoding=encoding, errors="strict") for x in cmd
@@ -749,7 +743,7 @@ if VERSION == "HEAD":
patchlevel = False
if len(version_split) > 2:
patchlevel = True
- VERSION = "%s_p%s" % (VERSION, version_split[2])
+ VERSION = f"{VERSION}_p{version_split[2]}"
if len(output_lines) > 1 and output_lines[1] == "modified":
head_timestamp = None
if len(output_lines) > 3:
@@ -764,14 +758,17 @@ if VERSION == "HEAD":
):
timestamp = timestamp - head_timestamp
if not patchlevel:
- VERSION = "%s_p0" % (VERSION,)
- VERSION = "%s_p%d" % (VERSION, timestamp)
+ VERSION = f"{VERSION}_p0"
+ VERSION = f"{VERSION}_p{timestamp}"
return VERSION
VERSION = "HEAD"
return VERSION
VERSION = _LazyVersion()
+else:
+ VERSION = "@VERSION@"
+
_legacy_global_var_names = (
"archlist",
"db",
@@ -790,7 +787,6 @@ _legacy_global_var_names = (
def _reset_legacy_globals():
-
global _legacy_globals_constructed
_legacy_globals_constructed = set()
for k in _legacy_global_var_names:
@@ -798,7 +794,6 @@ def _reset_legacy_globals():
class _LegacyGlobalProxy(proxy.objectproxy.ObjectProxy):
-
__slots__ = ("_name",)
def __init__(self, name):
@@ -825,3 +820,4 @@ def _disable_legacy_globals():
global _legacy_global_var_names
for k in _legacy_global_var_names:
globals().pop(k, None)
+ portage.data._initialized_globals.clear()