| 
 | 1 | +# Support for creating MicroPython virtual environments using `micropython -m venv`  | 
 | 2 | +# MIT license; Copyright (c) 2022 Jim Mussared  | 
 | 3 | + | 
 | 4 | +import argparse  | 
 | 5 | +import os  | 
 | 6 | +import sys  | 
 | 7 | + | 
 | 8 | + | 
 | 9 | +# If mip is not frozen into this binary, then also install it in the venv.  | 
 | 10 | +def install_mip(venv_lib_path):  | 
 | 11 | + need_mip = False  | 
 | 12 | + if "mip" in sys.modules:  | 
 | 13 | + del sys.modules["mip"]  | 
 | 14 | + saved_sys_path = sys.path[:]  | 
 | 15 | + try:  | 
 | 16 | + sys.path[:] = [".frozen"]  | 
 | 17 | + try:  | 
 | 18 | + import mip  | 
 | 19 | + | 
 | 20 | + print("mip is frozen")  | 
 | 21 | + except ImportError:  | 
 | 22 | + need_mip = True  | 
 | 23 | + finally:  | 
 | 24 | + sys.path[:] = saved_sys_path  | 
 | 25 | + | 
 | 26 | + if need_mip:  | 
 | 27 | + import mip  | 
 | 28 | + | 
 | 29 | + mip.install("mip-cmdline", target=venv_lib_path)  | 
 | 30 | + | 
 | 31 | + | 
 | 32 | +def do_venv():  | 
 | 33 | + parser = argparse.ArgumentParser(description="Create a micropython virtual environment")  | 
 | 34 | + parser.add_argument("path", nargs=1, help="Path to create the virtual environment in")  | 
 | 35 | + args = parser.parse_args(args=sys.argv[1:])  | 
 | 36 | + venv_path = args.path[0]  | 
 | 37 | + print("Creating virtual environment in:", venv_path)  | 
 | 38 | + | 
 | 39 | + # Equivalent to path = os.abspath(path).  | 
 | 40 | + if not venv_path.startswith("/"):  | 
 | 41 | + venv_path = os.getcwd() + os.sep + venv_path  | 
 | 42 | + | 
 | 43 | + venv_bin_path = venv_path + os.sep + "bin"  | 
 | 44 | + venv_lib_path = venv_path + os.sep + "lib"  | 
 | 45 | + | 
 | 46 | + for d in (  | 
 | 47 | + venv_path,  | 
 | 48 | + venv_bin_path,  | 
 | 49 | + venv_lib_path,  | 
 | 50 | + ):  | 
 | 51 | + try:  | 
 | 52 | + os.mkdir(d)  | 
 | 53 | + except:  | 
 | 54 | + pass  | 
 | 55 | + | 
 | 56 | + # Note the venv/lib dir goes before .frozen so that installed packages replace frozen ones.  | 
 | 57 | + with open(venv_bin_path + os.sep + "activate", "w") as f:  | 
 | 58 | + print(  | 
 | 59 | + """# Usage: source bin/activate  | 
 | 60 | +
  | 
 | 61 | +deactivate() {{  | 
 | 62 | + PATH="$_OLD_VIRTUAL_PATH"  | 
 | 63 | + export PATH  | 
 | 64 | +
  | 
 | 65 | + MICROPYPATH="$_OLD_VIRTUAL_MICROPYPATH"  | 
 | 66 | + if [ -z "$MICROPYPATH" ]; then  | 
 | 67 | + export -n MICROPYPATH  | 
 | 68 | + else  | 
 | 69 | + export MICROPYPATH  | 
 | 70 | + fi  | 
 | 71 | +
  | 
 | 72 | + unset VIRTUAL_ENV  | 
 | 73 | +
  | 
 | 74 | + unset deactivate  | 
 | 75 | +}}  | 
 | 76 | +
  | 
 | 77 | +VIRTUAL_ENV={}  | 
 | 78 | +
  | 
 | 79 | +_OLD_VIRTUAL_PATH="$PATH"  | 
 | 80 | +PATH="$VIRTUAL_ENV/bin:$PATH"  | 
 | 81 | +export PATH  | 
 | 82 | +
  | 
 | 83 | +_OLD_VIRTUAL_MICROPYPATH="$MICROPYPATH"  | 
 | 84 | +MICROPYPATH="$VIRTUAL_ENV/lib:.frozen"  | 
 | 85 | +export MICROPYPATH  | 
 | 86 | +""".format(  | 
 | 87 | + venv_path  | 
 | 88 | + ),  | 
 | 89 | + file=f,  | 
 | 90 | + )  | 
 | 91 | + | 
 | 92 | + # Add a `micropython` binary in $PATH pointing to this binary.  | 
 | 93 | + if hasattr(sys, "executable"):  | 
 | 94 | + os.system("cp {} {}".format(sys.executable, venv_bin_path + os.sep + "micropython"))  | 
 | 95 | + | 
 | 96 | + install_mip(venv_lib_path)  | 
 | 97 | + | 
 | 98 | + | 
 | 99 | +do_venv()  | 
0 commit comments