def _main(environ, argv): """Logic for main(), with less direct system interaction. Routines called here raise InvalidArgument with messages that should be delivered on stderr, to be caught by main. """ options = get_options(argv) if options.version: return handle_version() vexrc = get_vexrc(options, environ) # Handle --shell-config as soon as its arguments are available. if options.shell_to_configure: return handle_shell_config(options.shell_to_configure, vexrc, environ) if options.list is not None: return handle_list(vexrc.get_ve_base(environ), options.list) # Do as much as possible before a possible make, so errors can raise # without leaving behind an unused virtualenv. # get_virtualenv_name is destructive and must happen before get_command cwd = get_cwd(options) ve_base = vexrc.get_ve_base(environ) ve_name = get_virtualenv_name(options) command = get_command(options, vexrc, environ) # Either we create ve_path, get it from options.path or find it # in ve_base. if options.make: if options.path: make_path = os.path.abspath(options.path) else: make_path = os.path.abspath(os.path.join(ve_base, ve_name)) handle_make(environ, options, make_path) ve_path = make_path elif options.path: ve_path = os.path.abspath(options.path) if not os.path.exists(ve_path) or not os.path.isdir(ve_path): raise exceptions.InvalidVirtualenv( "argument for --path is not a directory") else: try: ve_path = get_virtualenv_path(ve_base, ve_name) except exceptions.NoVirtualenvName: options.print_help() raise # get_environ has to wait until ve_path is defined, which might # be after a make; of course we can't run until we have env. env = get_environ(environ, vexrc['env'], ve_path) returncode = run(command, env=env, cwd=cwd) if options.remove: handle_remove(ve_path) if returncode is None: raise exceptions.InvalidCommand( "command not found: {0!r}".format(command[0])) return returncode
def _main(environ, argv): """Logic for main(), with less direct system interaction. Routines called here raise InvalidArgument with messages that should be delivered on stderr, to be caught by main. """ options = get_options(argv) if options.version: return handle_version() vexrc = get_vexrc(options, environ) # Handle --shell-config as soon as its arguments are available. if options.shell_to_configure: return handle_shell_config(options.shell_to_configure, vexrc, environ) if options.list is not None: return handle_list(vexrc.get_ve_base(environ), options.list) # Do as much as possible before a possible make, so errors can raise # without leaving behind an unused virtualenv. # get_virtualenv_name is destructive and must happen before get_command cwd = get_cwd(options) ve_base = vexrc.get_ve_base(environ) ve_name = get_virtualenv_name(options) command = get_command(options, vexrc, environ) # Either we create ve_path, get it from options.path or find it # in ve_base. if options.make: if options.path: make_path = os.path.abspath(options.path) else: make_path = os.path.abspath(os.path.join(ve_base, ve_name)) handle_make(environ, options, make_path) ve_path = make_path elif options.path: ve_path = os.path.abspath(options.path) if not os.path.exists(ve_path) or not os.path.isdir(ve_path): raise exceptions.InvalidVirtualenv( "argument for --path is not a directory") else: try: ve_path = get_virtualenv_path(ve_base, ve_name) except exceptions.NoVirtualenvName: options.print_help() raise # get_environ has to wait until ve_path is defined, which might # be after a make; of course we can't run until we have env. env = get_environ(environ, vexrc['env'], ve_path) returncode = run(command, env=env, cwd=cwd) if options.remove: handle_remove(ve_path) if returncode is None: raise exceptions.InvalidCommand("command not found: {0!r}".format( command[0])) return returncode
def handle_make(environ, options, make_path): if os.path.exists(make_path): # Can't ignore existing virtualenv happily because existing one # might have different parameters and --make implies nonexistent raise exceptions.VirtualenvAlreadyMade( "virtualenv already exists: {0!r}".format(make_path) ) ve_base = os.path.dirname(make_path) if not os.path.exists(ve_base): os.mkdir(ve_base) elif not os.path.isdir(ve_base): raise exceptions.VirtualenvNotMade( "could not make virtualenv: " "{0!r} already exists but is not a directory. " "Choose a different virtualenvs path using ~/.vexrc " "or $WORKON_HOME, or remove the existing file; " "then rerun your vex --make command.".format(ve_base) ) # TODO: virtualenv is usually not on PATH for Windows, # but finding it is a terrible issue. if os.name == "nt" and not os.environ.get("VIRTUAL_ENV", ""): ve = os.path.join( os.path.dirname(sys.executable), "Scripts", "virtualenv" ) else: ve = "virtualenv" args = [ve, make_path] if options.python: if os.name == "nt": python = distutils.spawn.find_executable(options.python) if python: options.python = python args += ["--python", options.python] if options.site_packages: args += ["--system-site-packages"] if options.always_copy: args+= ["--always-copy"] returncode = run(args, env=environ, cwd=ve_base) if returncode != 0: raise exceptions.VirtualenvNotMade("error creating virtualenv") if os.name != "nt": pydoc_path = os.path.join(make_path, "bin", "pydoc") if os.path.exists(os.path.dirname(pydoc_path)): with open(pydoc_path, "wb") as out: out.write(PYDOC_SCRIPT) perms = os.stat(pydoc_path).st_mode os.chmod(pydoc_path, perms | 0o0111) else: pydoc_path = os.path.join(make_path, "Scripts", "pydoc.bat") with open(pydoc_path, "wb") as out: out.write(PYDOC_BATCH)
def test_run(): # mock subprocess.Popen because we are cowards with PatchedModule(os.path, exists=lambda path: True), \ PatchedModule(subprocess, Popen=FakePopen(returncode=888)) as mod: assert not mod.Popen.waited command = "foo" env = {"this": "irrelevant"} cwd = "also_irrelevant" returncode = run.run(command, env=env, cwd=cwd) assert mod.Popen.waited assert mod.Popen.command == command assert mod.Popen.env == env assert mod.Popen.cwd == cwd assert returncode == 888
def test_run(): # mock subprocess.Popen because we are cowards with PatchedModule(os.path, exists=lambda path: True), \ PatchedModule(subprocess, Popen=FakePopen(returncode=888)) as mod: assert not mod.Popen.waited command = 'foo' env = {'this': 'irrelevant'} cwd = 'also_irrelevant' returncode = run.run(command, env=env, cwd=cwd) assert mod.Popen.waited assert mod.Popen.command == command assert mod.Popen.env == env assert mod.Popen.cwd == cwd assert returncode == 888
def handle_make(environ, options, make_path): if os.path.exists(make_path): # Can't ignore existing virtualenv happily because existing one # might have different parameters and --make implies nonexistent raise exceptions.VirtualenvAlreadyMade(make_path) ve_base = os.path.dirname(make_path) if not os.path.exists(ve_base): os.mkdir(ve_base) elif not os.path.isdir(ve_base): raise exceptions.VirtualenvNotMade( "could not make virtualenv: " "{0!r} already exists but is not a directory. " "Choose a different virtualenvs path using ~/.vexrc " "or $WORKON_HOME, or remove the existing file; " "then rerun your vex --make command.".format(ve_base) ) # TODO: virtualenv is usually not on PATH for Windows, # but finding it is a terrible issue. if os.name == 'nt' and not os.environ.get('VIRTUAL_ENV', ''): ve = os.path.join( os.path.dirname(sys.executable), 'Scripts', 'virtualenv' ) else: ve = 'virtualenv' args = [ve, make_path] if options.python: args += ['--python', options.python] if options.site_packages: args += ['--site-packages'] if options.always_copy: args+= ['--always-copy'] returncode = run(args, env=environ, cwd=ve_base) if returncode != 0: raise exceptions.VirtualenvNotMade("error creating virtualenv") if os.name != 'nt': pydoc_path = os.path.join(make_path, 'bin', 'pydoc') with open(pydoc_path, 'wb') as out: out.write(PYDOC_SCRIPT) perms = os.stat(pydoc_path).st_mode os.chmod(pydoc_path, perms | 0o0111) else: pydoc_path = os.path.join(make_path, 'Scripts', 'pydoc.bat') with open(pydoc_path, 'wb') as out: out.write(PYDOC_BATCH)
def test_run_bad_command(): env = os.environ.copy() returncode = run.run("blah_unlikely", env=env, cwd=".") assert returncode is None