From c26d77b52e3bfb82729787a5c30cca27a8cf9f99 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 14 Oct 2022 16:12:22 +1100 Subject: [PATCH] venv: Add a command-line package for creating virtual environments. Works like "python -m venv path" and creates a rudimentary virtual environment for the Unix port: - sets MICROPYPATH - copies the micropython binary to venv/bin/micropython which is in $PATH - installs mip & mip-cmdline in the venv Using the venv is the same as for CPython -- source the activate script to enter, and call the deactivate function to leave. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared --- python-stdlib/venv/manifest.py | 9 +++ python-stdlib/venv/venv/__main__.py | 99 +++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 python-stdlib/venv/manifest.py create mode 100644 python-stdlib/venv/venv/__main__.py diff --git a/python-stdlib/venv/manifest.py b/python-stdlib/venv/manifest.py new file mode 100644 index 0000000..9c36b31 --- /dev/null +++ b/python-stdlib/venv/manifest.py @@ -0,0 +1,9 @@ +metadata( + version="0.1.0", + description="Support for creating MicroPython virtual environments using `micropython -m venv`", +) + +require("argparse") +require("mip-cmdline") + +package("venv") diff --git a/python-stdlib/venv/venv/__main__.py b/python-stdlib/venv/venv/__main__.py new file mode 100644 index 0000000..36ed41d --- /dev/null +++ b/python-stdlib/venv/venv/__main__.py @@ -0,0 +1,99 @@ +# Support for creating MicroPython virtual environments using `micropython -m venv` +# MIT license; Copyright (c) 2022 Jim Mussared + +import argparse +import os +import sys + + +# If mip is not frozen into this binary, then also install it in the venv. +def install_mip(venv_lib_path): + need_mip = False + if "mip" in sys.modules: + del sys.modules["mip"] + saved_sys_path = sys.path[:] + try: + sys.path[:] = [".frozen"] + try: + import mip + + print("mip is frozen") + except ImportError: + need_mip = True + finally: + sys.path[:] = saved_sys_path + + if need_mip: + import mip + + mip.install("mip-cmdline", target=venv_lib_path) + + +def do_venv(): + parser = argparse.ArgumentParser(description="Create a micropython virtual environment") + parser.add_argument("path", nargs=1, help="Path to create the virtual environment in") + args = parser.parse_args(args=sys.argv[1:]) + venv_path = args.path[0] + print("Creating virtual environment in:", venv_path) + + # Equivalent to path = os.abspath(path). + if not venv_path.startswith("/"): + venv_path = os.getcwd() + os.sep + venv_path + + venv_bin_path = venv_path + os.sep + "bin" + venv_lib_path = venv_path + os.sep + "lib" + + for d in ( + venv_path, + venv_bin_path, + venv_lib_path, + ): + try: + os.mkdir(d) + except: + pass + + # Note the venv/lib dir goes before .frozen so that installed packages replace frozen ones. + with open(venv_bin_path + os.sep + "activate", "w") as f: + print( + """# Usage: source bin/activate + +deactivate() {{ + PATH="$_OLD_VIRTUAL_PATH" + export PATH + + MICROPYPATH="$_OLD_VIRTUAL_MICROPYPATH" + if [ -z "$MICROPYPATH" ]; then + export -n MICROPYPATH + else + export MICROPYPATH + fi + + unset VIRTUAL_ENV + + unset deactivate +}} + +VIRTUAL_ENV={} + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +_OLD_VIRTUAL_MICROPYPATH="$MICROPYPATH" +MICROPYPATH="$VIRTUAL_ENV/lib:.frozen" +export MICROPYPATH +""".format( + venv_path + ), + file=f, + ) + + # Add a `micropython` binary in $PATH pointing to this binary. + if hasattr(sys, "executable"): + os.system("cp {} {}".format(sys.executable, venv_bin_path + os.sep + "micropython")) + + install_mip(venv_lib_path) + + +do_venv()