qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v2 06/10] mkvenv: generate console entry shims from inside th


From: John Snow
Subject: [RFC PATCH v2 06/10] mkvenv: generate console entry shims from inside the venv
Date: Fri, 14 Apr 2023 01:54:45 -0400

This patch is meant to ensure that console entry point scripts will
always generate on Python 3.7 installations where we may not have access
to importlib.metadata. By running it from a separate process *inside*
the venv, we can be assured to have access to setuptools and by
extension pkg_resources as a fallback.

As a coincidence, it also gives us a pretty good place to do all kinds
of other "in-venv" setup that we might want to do later; for instance
meson and sphinx bootstrapping might be good candidates.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 python/scripts/mkvenv.py | 71 ++++++++++++++++++++++++++++++++--------
 1 file changed, 57 insertions(+), 14 deletions(-)

diff --git a/python/scripts/mkvenv.py b/python/scripts/mkvenv.py
index a3284e9ef1..317697a953 100644
--- a/python/scripts/mkvenv.py
+++ b/python/scripts/mkvenv.py
@@ -62,22 +62,33 @@ def __init__(self, *args, **kwargs) -> None:
         self.script_packages = kwargs.pop('script_packages', ())
         super().__init__(*args, **kwargs)
 
-        # The EnvBuilder class is cute and toggles this setting off
-        # before post_setup, but we need it to decide if we want to
-        # generate shims or not.
-        self._system_site_packages = self.system_site_packages
+        # Make the context available post-creation:
+        self._context: Optional[SimpleNamespace] = None
+
+    def ensure_directories(self, env_dir: DirType) -> SimpleNamespace:
+        logger.debug("ensure_directories(env_dir=%s)", env_dir)
+        self._context = super().ensure_directories(env_dir)
+        return self._context
+
+    def create(self, env_dir: DirType) -> None:
+        logger.debug("create(env_dir=%s)", env_dir)
+        super().create(env_dir)
+        self.post_post_setup(self._context)
 
     def post_setup(self, context: SimpleNamespace) -> None:
         logger.debug("post_setup(...)")
-
-        # Generate console_script entry points for system packages:
-        if self._system_site_packages:
-            generate_console_scripts(
-                context.env_exe, context.bin_path, self.script_packages)
-
         # print the python executable to stdout for configure.
         print(context.env_exe)
 
+    def post_post_setup(self, context: SimpleNamespace) -> None:
+        # The final, final hook; enter the venv and run any
+        # last steps we want to occur *inside* the venv.
+        args = [context.env_exe, __file__, 'post_init',
+                '--binpath', context.bin_path]
+        if self.system_site_packages:
+            args += ['--gen', ",".join(self.script_packages)]
+        subprocess.run(args, check=True)
+
 
 def need_ensurepip() -> bool:
     """
@@ -301,6 +312,10 @@ def generate_console_scripts(python_path: str, bin_path: 
str,
     """
     Generate script shims for console_script entry points in @packages.
     """
+    logger.debug(
+        "generate_console_scripts(python_path=%s, bin_path=%s, packages=%s)",
+        python_path, bin_path, packages)
+
     if not packages:
         return
 
@@ -334,6 +349,16 @@ def _get_entry_points() -> Iterator[Dict[str, str]]:
         logger.debug("wrote '%s'", script_path)
 
 
+def post_venv_setup(bin_path: str, packages: Sequence[str] = ()) -> None:
+    """
+    This is intended to be run *inside the venv* after it is created.
+    """
+    python_path = sys.executable
+    logger.debug("post_venv_setup(bin_path=%s, packages=%s)",
+                 bin_path, packages)
+    generate_console_scripts(python_path, bin_path, packages)
+
+
 def main() -> int:
     """CLI interface to make_qemu_venv. See module docstring."""
     if os.environ.get('DEBUG') or os.environ.get('GITLAB_CI'):
@@ -366,12 +391,28 @@ def main() -> int:
         help="Target directory to install virtual environment into.",
     )
 
+    subparser = subparsers.add_parser(
+        'post_init', help='post-venv initialization')
+    subparser.add_argument(
+        '--gen',
+        type=str,
+        action='append',
+        help="Regenerate console_scripts for given packages, if found.",
+    )
+    subparser.add_argument(
+        '--binpath',
+        type=str,
+        action='store',
+        help="Path where console script shims should be generated",
+    )
+
     args = parser.parse_args()
+    script_packages = []
+    for element in args.gen or ():
+        script_packages.extend(element.split(","))
+
     try:
         if args.command == 'create':
-            script_packages = []
-            for element in args.gen or ():
-                script_packages.extend(element.split(","))
             make_venv(
                 args.target,
                 system_site_packages=True,
@@ -380,7 +421,9 @@ def main() -> int:
                 with_pip=None,  # Autodetermine
                 script_packages=script_packages,
             )
-            logger.debug("mkvenv.py create - exiting")
+        if args.command == 'post_init':
+            post_venv_setup(args.binpath, script_packages)
+        logger.debug("mkvenv.py %s: exiting", args.command)
     except Ouch as exc:
         print("\n*** Ouch! ***\n", file=sys.stderr)
         print(str(exc), "\n\n", file=sys.stderr)
-- 
2.39.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]