"""Python virtual environment manager for xonsh.""" import sys import textwrap import xontrib.voxapi as voxapi import xonsh.lazyasd as lazyasd __all__ = () class VoxHandler: """Vox is a virtual environment manager for xonsh.""" def parser(): from argparse import ArgumentParser parser = ArgumentParser(prog="vox", description=__doc__) subparsers = parser.add_subparsers(dest="command") create = subparsers.add_parser( "new", aliases=["create"], help="Create a new virtual environment in $VIRTUALENV_HOME", ) create.add_argument("name", metavar="ENV", help="The environments to create") create.add_argument( "--system-site-packages", default=False, action="store_true", dest="system_site_packages", help="Give the virtual environment access to the " "system site-packages dir.", ) create.add_argument( "-p", "--interpreter", default=None, help=textwrap.dedent( """ The Python interpreter used to create the virtual environment. Can be configured via the $VOX_DEFAULT_INTERPRETER environment variable. """ ).strip(), ) from xonsh.platform import ON_WINDOWS group = create.add_mutually_exclusive_group() group.add_argument( "--symlinks", default=not ON_WINDOWS, action="store_true", dest="symlinks", help="Try to use symlinks rather than copies, " "when symlinks are not the default for " "the platform.", ) group.add_argument( "--copies", default=ON_WINDOWS, action="store_false", dest="symlinks", help="Try to use copies rather than symlinks, " "even when symlinks are the default for " "the platform.", ) create.add_argument( "--without-pip", dest="with_pip", default=True, action="store_false", help="Skips installing or upgrading pip in the " "virtual environment (pip is bootstrapped " "by default)", ) create.add_argument( "-a", "--activate", default=False, action="store_true", dest="activate", help="Activate the newly created virtual environment.", ) activate = subparsers.add_parser( "activate", aliases=["workon", "enter"], help="Activate virtual environment" ) activate.add_argument( "name", metavar="ENV", help=( "The environment to activate. ENV can be " "either a name from the venvs shown by vox" "list or the path to an arbitrary venv" ), ) deactivate = subparsers.add_parser( "deactivate", aliases=["exit"], help="Deactivate current virtual environment", ) deactivate.add_argument( "--remove", dest="remove", default=False, action="store_true", help="Remove the virtual environment after leaving it.", ) subparsers.add_parser( "list", aliases=["ls"], help=("List environments available in " "$VIRTUALENV_HOME"), ) remove = subparsers.add_parser( "remove", aliases=["rm", "delete", "del"], help="Remove virtual environment" ) remove.add_argument( "names", metavar="ENV", nargs="+", help=( "The environments to remove. ENV can be " "either a name from the venvs shown by vox" "list or the path to an arbitrary venv" ), ) subparsers.add_parser("help", help="Show this help message") return parser parser = lazyasd.LazyObject(parser, locals(), "parser") aliases = { "create": "new", "workon": "activate", "enter": "activate", "exit": "deactivate", "ls": "list", "rm": "remove", "delete": "remove", "del": "remove", } def __init__(self): self.vox = voxapi.Vox() def __call__(self, args, stdin=None): """Call the right handler method for a given command.""" args = self.parser.parse_args(args) cmd = self.aliases.get(args.command, args.command) if cmd is None: self.parser.print_usage() else: getattr(self, "cmd_" + cmd)(args, stdin) def cmd_new(self, args, stdin=None): """Create a virtual environment in $VIRTUALENV_HOME with python3's ``venv``.""" print("Creating environment...") self.vox.create( args.name, system_site_packages=args.system_site_packages, symlinks=args.symlinks, with_pip=args.with_pip, interpreter=args.interpreter, ) if args.activate: self.vox.activate(args.name) print(f"Environment {args.name!r} created and activated.\n") else: print( f'Environment {args.name!r} created. Activate it with "vox activate {args.name}".\n' ) def cmd_activate(self, args, stdin=None): """Activate a virtual environment.""" try: self.vox.activate(args.name) except KeyError: print( 'This environment doesn\'t exist. Create it with "vox new %s".\n' % args.name, file=sys.stderr, ) return None else: print('Activated "%s".\n' % args.name) def cmd_deactivate(self, args, stdin=None): """Deactivate the active virtual environment.""" if self.vox.active() is None: print( 'No environment currently active. Activate one with "vox activate".\n', file=sys.stderr, ) return None env_name = self.vox.deactivate() if args.remove: del self.vox[env_name] print(f'Environment "{env_name}" deactivated and removed.\n') else: print(f'Environment "{env_name}" deactivated.\n') def cmd_list(self, args, stdin=None): """List available virtual environments.""" try: envs = sorted(self.vox.keys()) except PermissionError: print("No permissions on VIRTUALENV_HOME") return None if not envs: print( 'No environments available. Create one with "vox new".\n', file=sys.stderr, ) return None print("Available environments:") print("\n".join(envs)) def cmd_remove(self, args, stdin=None): """Remove virtual environments.""" for name in args.names: try: del self.vox[name] except voxapi.EnvironmentInUse: print( 'The "%s" environment is currently active. In order to remove it, deactivate it first with "vox deactivate".\n' % name, file=sys.stderr, ) return except KeyError: print('"%s" environment doesn\'t exist.\n' % name, file=sys.stderr) return else: print('Environment "%s" removed.' % name) print() def cmd_help(self, args, stdin=None): self.parser.print_help() @classmethod def handle(cls, args, stdin=None): """Runs Vox environment manager.""" vox = cls() return vox(args, stdin=stdin) aliases["vox"] = VoxHandler.handle