def main(arguments, toxinidir=None): "ctox: tox with conda." try: # pragma: no cover # Exit on broken pipe. import signal signal.signal(signal.SIGPIPE, signal.SIG_DFL) except AttributeError: # pragma: no cover # SIGPIPE is not available on Windows. pass try: import sys sys.exit(ctox(arguments, toxinidir)) except CalledProcessError as c: print(c.output) return 1 except NotImplementedError as e: gh = "https://github.com/hayd/ctox/issues" from colorama import Style cprint(Style.BRIGHT + str(e), 'err') cprint( "If this is a valid tox.ini substitution, please open an issue on\n" "github and request support: %s." % gh, 'warn') return 1 except KeyboardInterrupt: # pragma: no cover return 1
def run_one_command(env, command): # TODO move large part of this function to subst.parse_command. abbr_cmd, cmd, command = print_pretty_command(env, command) # Skip comments. line = " ".join(command).strip() if not line or line.startswith("#"): return 0 # Ensure the command is already in envbindir or in the whitelist, correct # it if it's not in the whitelist (it'll OSError if it's not found). if cmd not in env.whitelist and not cmd.startswith(env.envbindir): command[0] = os.path.join(env.envbindir, cmd) # Run the command! try: p = Popen(command, cwd=env.changedir, stderr=STDOUT) p.communicate() return p.returncode except OSError as e: # Command not found locally (or not in whitelist). cprint(" OSError: %s" % e.args[1], 'err') cprint(" Is %s in dependancies or whitelist_externals?\n" % abbr_cmd, 'warn') return 1
def main(arguments, toxinidir=None): "ctox: tox with conda." try: # pragma: no cover # Exit on broken pipe. import signal signal.signal(signal.SIGPIPE, signal.SIG_DFL) except AttributeError: # pragma: no cover # SIGPIPE is not available on Windows. pass try: import sys sys.exit(ctox(arguments, toxinidir)) except CalledProcessError as c: print(c.output) return 1 except NotImplementedError as e: gh = "https://github.com/hayd/ctox/issues" from colorama import Style cprint(Style.BRIGHT + str(e), 'err') cprint("If this is a valid tox.ini substitution, please open an issue on\n" "github and request support: %s." % gh, 'warn') return 1 except KeyboardInterrupt: # pragma: no cover return 1
def uninstall_deps(env, deps): # TODO actually use this. if deps: print("removing previous deps...") success = all(uninstall(env=env, lib=d) for d in deps[1:]) if (not success) or deps[0] != "pip": cprint(" Environment dependancies mismatch, rebuilding.", "err") create_env(env, force_remove=True) with open(env.envctoxfile, "w") as f: f.write("")
def uninstall_deps(env, deps): # TODO actually use this. if deps: print("removing previous deps...") success = all(uninstall(env=env, lib=d) for d in deps[1:]) if (not success) or deps[0] != "pip": cprint(" Environment dependancies mismatch, rebuilding.", 'err') create_env(env, force_remove=True) with open(env.envctoxfile, 'w') as f: f.write("")
def install(env, lib): lib_ = lib.replace("==", "=") # obviously conda syntax is different success = safe_shell_out( ["conda", "install", lib_, "-p", env.name, "--yes", "--quiet"], cwd=env.toxdir ) or safe_shell_out([env.pip, "install", "--quiet", lib], cwd=env.toxdir) if success: with open(env.envctoxfile, "a") as f: f.write(" " + lib) else: cprint(" Unable to install %s." % lib, "err") return success
def install(env, lib): lib_ = lib.replace('==', '=') # obviously conda syntax is different success = (safe_shell_out(["conda", "install", lib_, "-p", env.name, "--yes", "--quiet"], cwd=env.toxdir) or safe_shell_out([env.pip, "install", "--quiet", lib], cwd=env.toxdir)) if success: with open(env.envctoxfile, 'a') as f: f.write(" " + lib) else: cprint(" Unable to install %s." % lib, 'err') return success
def run_one_command(env, command): # TODO move large part of this function to subst.parse_command. abbr_cmd, cmd, command = print_pretty_command(env, command) # Skip comments. line = " ".join(command).strip() if not line or line.startswith("#"): return 0 # Ensure the command is already in envbindir or in the whitelist, correct # it if it's not in the whitelist (it'll OSError if it's not found). if cmd not in env.whitelist and not cmd.startswith(env.envbindir): command[0] = os.path.join(env.envbindir, cmd) # Run the command! try: p = Popen(command, cwd=env.changedir, stderr=STDOUT) p.communicate() return p.returncode except OSError as e: # Command not found locally (or not in whitelist). cprint(" OSError: %s" % e.args[1], "err") cprint(" Is %s in dependancies or whitelist_externals?\n" % abbr_cmd, "warn") return 1
def ctox(self): """Main method for the environment. Parse the tox.ini config, install the dependancies and run the commands. The output of the commands is printed. Returns 0 if they ran successfully, 1 if there was an error (either in setup or whilst running the commands), 2 if the build was skipped. """ # TODO make this less of a hack e.g. using basepython from config # if it exists (and use an attribute directly). if self.name[:4] not in SUPPORTED_ENVS: from colorama import Style cprint( Style.BRIGHT + "Skipping unsupported python version %s\n" % self.name, 'warn') return 2 # TODO don't remove env if there's a dependancy mis-match # rather "clean" it to the empty state (the hope being to keep # the dist build around - so not all files need to be rebuilt) # TODO extract this as a method (for readability) if not self.env_exists() or self.reusableable(): cprint("%s create: %s" % (self.name, self.envdir)) self.create_env(force_remove=True) cprint("%s installdeps: %s" % (self.name, ', '.join(self.deps))) if not self.install_deps(): cprint(" deps installation failed, aborted.\n", 'err') return 1 else: cprint("%s cached (deps unchanged): %s" % (self.name, self.envdir)) # install the project from the zipped file # TODO think more carefully about where it should be installed # specifically we want to be able this to include the test files (which # are not always unpacked when installed so as to run the tests there) # if there are build files (e.g. cython) then tests must run where # the build was. Also, reinstalling should not overwrite the builds # e.g. setup.py will skip rebuilding cython files if they are unchanged cprint("%s inst: %s" % (self.name, self.envdistdir)) if not self.install_dist(): cprint(" install failed.\n", 'err') return 1 cprint("%s runtests" % self.name) # return False if all commands were successfully run # otherwise returns True if at least one command exited badly return self.run_commands()
def ctox(arguments, toxinidir): """Sets up conda environments, and sets up and runs each environment based on the project's tox.ini configuration file. Returns 1 if either the build or running the commands failed or 0 if all commmands ran successfully. """ if arguments is None: arguments = [] if toxinidir is None: toxinidir = os.getcwd() args, options = parse_args(arguments) if args.version: print(version) return 0 # if no conda trigger OSError try: with open(os.devnull, "w") as fnull: check_output(['conda', '--version'], stderr=fnull) except OSError: cprint( "conda not found, you need to install it to use ctox.\n" "The recommended way is to download miniconda,\n" "Do not install conda via pip.", 'err') return 1 toxinifile = os.path.join(toxinidir, "tox.ini") from ctox.config import read_config, get_envlist config = read_config(toxinifile) if args.e == 'ALL': envlist = get_envlist(config) else: envlist = args.e.split(',') # TODO configure with option toxdir = os.path.join(toxinidir, ".tox") # create a zip file for the project from ctox.pkg import make_dist, package_name cprint("GLOB sdist-make: %s" % os.path.join(toxinidir, "setup.py")) package = package_name(toxinidir) if not make_dist(toxinidir, toxdir, package): cprint(" setup.py sdist failed", 'err') return 1 # setup each environment and run ctox failing = {} for env_name in envlist: env = Env(name=env_name, config=config, options=options, toxdir=toxdir, toxinidir=toxinidir, package=package) failing[env_name] = env.ctox() # print summary of the outcomes of ctox for each environment cprint('Summary') print("-" * 23) for env_name in envlist: n = failing[env_name] outcome = ('succeeded', 'failed', 'skipped')[n] status = ('ok', 'err', 'warn')[n] cprint("%s commands %s" % (env_name, outcome), status) return any(1 == v for v in failing.values())
def ctox(self): """Main method for the environment. Parse the tox.ini config, install the dependancies and run the commands. The output of the commands is printed. Returns 0 if they ran successfully, 1 if there was an error (either in setup or whilst running the commands), 2 if the build was skipped. """ # TODO make this less of a hack e.g. using basepython from config # if it exists (and use an attribute directly). if self.name[:4] not in SUPPORTED_ENVS: from colorama import Style cprint(Style.BRIGHT + "Skipping unsupported python version %s\n" % self.name, 'warn') return 2 # TODO don't remove env if there's a dependancy mis-match # rather "clean" it to the empty state (the hope being to keep # the dist build around - so not all files need to be rebuilt) # TODO extract this as a method (for readability) if not self.env_exists() or self.reusableable(): cprint("%s create: %s" % (self.name, self.envdir)) self.create_env(force_remove=True) cprint("%s installdeps: %s" % (self.name, ', '.join(self.deps))) if not self.install_deps(): cprint(" deps installation failed, aborted.\n", 'err') return 1 else: cprint("%s cached (deps unchanged): %s" % (self.name, self.envdir)) # install the project from the zipped file # TODO think more carefully about where it should be installed # specifically we want to be able this to include the test files (which # are not always unpacked when installed so as to run the tests there) # if there are build files (e.g. cython) then tests must run where # the build was. Also, reinstalling should not overwrite the builds # e.g. setup.py will skip rebuilding cython files if they are unchanged cprint("%s inst: %s" % (self.name, self.envdistdir)) if not self.install_dist(): cprint(" install failed.\n", 'err') return 1 cprint("%s runtests" % self.name) # return False if all commands were successfully run # otherwise returns True if at least one command exited badly return self.run_commands()
def ctox(arguments, toxinidir): """Sets up conda environments, and sets up and runs each environment based on the project's tox.ini configuration file. Returns 1 if either the build or running the commands failed or 0 if all commmands ran successfully. """ if arguments is None: arguments = [] if toxinidir is None: toxinidir = os.getcwd() args, options = parse_args(arguments) if args.version: print(version) return 0 # if no conda trigger OSError try: with open(os.devnull, "w") as fnull: check_output(['conda', '--version'], stderr=fnull) except OSError: cprint("conda not found, you need to install it to use ctox.\n" "The recommended way is to download miniconda,\n" "Do not install conda via pip.", 'err') return 1 toxinifile = os.path.join(toxinidir, "tox.ini") from ctox.config import read_config, get_envlist config = read_config(toxinifile) if args.e == 'ALL': envlist = get_envlist(config) else: envlist = args.e.split(',') # TODO configure with option toxdir = os.path.join(toxinidir, ".tox") # create a zip file for the project from ctox.pkg import make_dist, package_name cprint("GLOB sdist-make: %s" % os.path.join(toxinidir, "setup.py")) package = package_name(toxinidir) if not make_dist(toxinidir, toxdir, package): cprint(" setup.py sdist failed", 'err') return 1 # setup each environment and run ctox failing = {} for env_name in envlist: env = Env(name=env_name, config=config, options=options, toxdir=toxdir, toxinidir=toxinidir, package=package) failing[env_name] = env.ctox() # print summary of the outcomes of ctox for each environment cprint('Summary') print("-" * 23) for env_name in envlist: n = failing[env_name] outcome = ('succeeded', 'failed', 'skipped')[n] status = ('ok', 'err', 'warn')[n] cprint("%s commands %s" % (env_name, outcome), status) return any(1 == v for v in failing.values())