def test_call(tmpdir): def assert_pip_call(response, code=0, output=True, err=False): rcode, rout, rerr = response assert rcode == code def _assert_outerr(routerr, outerr): if isinstance(output, bool): if output: assert rout else: assert not rout else: assert rout == output _assert_outerr(rout, output) _assert_outerr(rerr, err) directory = tmpdir.mkdir("tmp") tempfile = directory.join("tmp.log") path = str(tempfile) _pip.call("install", "requests") assert_pip_call(_pip.call("install", "requests", quiet=True)) _pip.call("install", "requests", log=path) assert tempfile.read()
def _get_pip_info(*args, **kwargs): packages = args pip_exec = kwargs.get("pip_exec", None) _, out, _ = _pip.call("show", *packages, pip_exec=pip_exec, output=True) results = [strip(o) for o in out.split("---")] info = dict() for i, package in enumerate(packages): result = results[i] detail = dict((kebab_case(k), v) \ for k, v in \ iteritems( dict([(s + [""]) if len(s) == 1 else s \ for s in [re.split(r":\s?", o, maxsplit = 1) \ for o in result.split("\n")]] ) ) ) info[package] = detail return info
def get_registry_from_pip(pip_path, user=False, sync=False, outdated=True, build_dependency_tree=False, jobs=1, only_packages=[], ignore_packages=[]): logger.info("Fetching installed packages for %s..." % pip_path) _, output, _ = _pip.call("list", user = user, outdated = outdated, \ format = "json", pip_exec = pip_path, output = True) packages = json.loads(output) logger.info("%s packages found for %s." % (len(packages), pip_path)) if only_packages: packages = [p for p in packages if p["name"] in only_packages] if ignore_packages: packages = [p for p in packages if p["name"] not in ignore_packages] registry = Registry(source=pip_path, packages=packages, installed=True, sync=sync, build_dependency_tree=build_dependency_tree, jobs=jobs) logger.info("Packages within `pip` %s found: %s..." % (pip_path, registry.packages)) # _pip.get_installed_distributions() # https://github.com/achillesrasquinha/pipupgrade/issues/13 return registry
def pip_upgrade(package, pip_exec=None, user=None, quiet=None): return _pip.call("install", package, pip_exec=pip_exec, user=user, quiet=quiet, no_cache_dir=True, upgrade=True)
def test_call(tmpdir): directory = tmpdir.mkdir("tmp") tempfile = directory.join("tmp.log") path = str(tempfile) _pip.call("install", "requests") _pip.call("install", "requests", quiet=True) _pip.call("install", "requests", log=path) _pip.call("list")
def update_pipfile(pipfile, verbose=False): if not verbose: logger.setLevel(log.NOTSET) realpath = osp.realpath(pipfile) basepath = osp.dirname(realpath) logger.info("Searching for `pipenv`...") pipenv = which("pipenv") if not pipenv: logger.info("Attempting to install pipenv...") _pip.call("install", "pipenv") pipenv = which("pipenv", raise_err=True) logger.info("`pipenv` found.") code = popen("%s update" % pipenv, quiet=not verbose, cwd=basepath) return code == 0
def get_registry_from_pip(pip_path, sync=False): _, output, _ = _pip.call("list", outdated = True, \ format = "json", pip_exec = pip_path, output = True) packages = json.loads(output) registry = Registry(source=pip_path, packages=packages, installed=True, sync=sync) logger.info("Packages within `pip` %s found: %s..." % (pip_path, registry.packages)) # _pip.get_installed_distributions() # https://github.com/achillesrasquinha/pipupgrade/issues/13 return registry
def update_pip(pip_exec, user = None, quiet = None): cli.echo(cli_format("Updating %s..." % pip_exec, cli.YELLOW)) output = _pip.call("install", "pip", pip_exec = pip_exec, user = user, quiet = quiet, no_cache_dir = True, upgrade = True) if isinstance(output, int): code = output else: code = output[0] if not code: cli.echo("%s upto date." % cli_format(pip_exec, cli.CYAN)) return output
def environment(): environ = dict() environ["version"] = __version__ environ["python_version"] = platform.python_version() environ["os"] = platform.platform() environ["config"] = dict(path=dict(PATH)) environ["pip_executables"] = [ dict(executable=executable, version=_pip.call("--version", pip_exec=executable, output=True)[1]) for executable in _pip._PIP_EXECUTABLES ] from pipupgrade import settings environ["settings"] = settings.to_dict() return environ
def update_registry(registry, yes=False, user=False, check=False, latest=False, interactive=False, format_="table", all=False, filter_=[], file=None, raise_err=True, verbose=False, upgrade_type=("minor", "patch")): source = registry.source packages = registry.packages if filter_: packages = [p for p in packages if p.name in filter_] table = Table( header=["Name", "Current Version", "Latest Version", "Home Page"]) nodes = [] render = False dinfo = [] # Information DataFrame for package in packages: package.source = source package.installed = registry.installed current_version = package.current_version if all or current_version: current_version = current_version.replace("==", "") if all or (package.latest_version and current_version != package.latest_version): render = True if format_ in _DEPENDENCY_FORMATS: nodes.append(package) else: table.insert([ cli_format( package.name, _SEMVER_COLOR_MAP.get(package.difference, cli.CLEAR)), package.current_version or "na", _cli_format_semver(package.latest_version, package.difference), cli_format(package.home_page, cli.CYAN) ]) dinfo.append(package) stitle = "Installed Distributions (%s)" % source if registry.installed else source if render: if format_ in _DEPENDENCY_FORMATS: nodes = _resolve_dependencies(nodes) dinfo = nodes if format_ == "tree": string = _render_dependency_tree(nodes) elif format_ == "json": string = _render_json(nodes) elif format_ == "yaml": string = _render_yaml(nodes) elif format_ == "table": string = table.render() cli.echo("\nSource: %s\n" % stitle, file=file) if not interactive or check: cli.echo(string, file=file) cli.echo(file=file) if not check: packages = [ p for p in dinfo if p.difference in upgrade_type or p.difference == "major" ] packages = [ p for p in dinfo if p.difference != "major" or getattr(p, "has_dependency_conflict", False) or latest ] npackages = len(packages) spackages = pluralize("package", npackages) # Packages "string" query = "Do you wish to update %s %s?" % (npackages, spackages) if npackages and (yes or interactive or cli.confirm(query, quit_=True)): for i, package in enumerate(packages): update = True query = "%s (%s) -> (%s)" % (cli_format( package.name, _SEMVER_COLOR_MAP.get(package.difference, cli.CLEAR)), package.current_version, _cli_format_semver( package.latest_version, package.difference)) if interactive: update = yes or cli.confirm(query) if update: cli.echo(cli_format( "Updating %s of %s %s: %s" % (i + 1, npackages, spackages, cli_format(package.name, cli.GREEN)), cli.BOLD), file=file) if not package.installed: _update_requirements(package.source, package) else: try: _pip.call("install", package.name, pip_exec=package.source, user=user, quiet=not verbose, no_cache_dir=True, upgrade=True) except PopenError as e: if raise_err: raise else: cli.echo("%s upto date." % cli_format(stitle, cli.CYAN), file=file)
def command(pip_path=[], requirements=[], pipfile=[], project=None, pull_request=False, git_username=None, git_email=None, github_access_token=None, github_reponame=None, github_username=None, target_branch="master", latest=False, format="table", all=False, pip=False, self=False, jobs=1, user=False, check=False, interactive=False, yes=False, no_included_requirements=False, no_cache=False, no_color=True, output=None, force=False, verbose=False): if not verbose: logger.setLevel(log.NOTSET) logger.info("Environment: %s" % environment()) cli.echo(cli_format("Checking...", cli.YELLOW)) logger.info("Arguments Passed: %s" % locals()) pip_path = pip_path or [] pip_path = [which(p) for p in pip_path] or _pip._PIP_EXECUTABLES logger.info("`pip` executables found: %s" % pip_path) logger.info("Using %s jobs..." % jobs) registries = [] if pip: logger.info("Updating pip executables: %s" % " ".join(pip_path)) with parallel.no_daemon_pool(processes=jobs) as pool: pool.map( partial(update_pip, **{ "user": user, "quiet": not verbose }), pip_path) if self: package = __name__ logger.info("Updating %s..." % package) cli.echo(cli_format("Updating %s..." % package, cli.YELLOW)) _pip.call("install", package, user=user, quiet=not verbose, no_cache=True, upgrade=True) cli.echo("%s upto date." % cli_format(package, cli.CYAN)) else: if project: project = sequencify(project) requirements = requirements or [] pipfile = pipfile or [] logger.info("Detecting projects and its dependencies...") with parallel.no_daemon_pool(processes=jobs) as pool: project = pool.map( partial(Project.from_path, **{"recursive_search": force}), project) requirements += flatten(map(lambda p: p.requirements, project)) pipfile += flatten( map(lambda p: [p.pipfile] if p.pipfile else [], project)) logger.info("Updating projects %s..." % project) if requirements: logger.info("Detecting requirements...") if not no_included_requirements: with parallel.no_daemon_pool(processes=jobs) as pool: results = pool.map(get_included_requirements, requirements) requirements += flatten(results) logger.info("Requirements found: %s" % requirements) with parallel.no_daemon_pool(processes=jobs) as pool: results = pool.map( partial(get_registry_from_requirements, **{ "sync": no_cache, "jobs": jobs }), requirements) registries += results else: with parallel.no_daemon_pool(processes=jobs) as pool: results = pool.map( partial( get_registry_from_pip, **{ "user": user, "sync": no_cache, "outdated": not all, "build_dependency_tree": format in _DEPENDENCY_FORMATS, "jobs": jobs }), pip_path) registries += results logger.info("Updating registries: %s..." % registries) # TODO: Tweaks within parallel.no_daemon_pool to run serially. if yes: with parallel.no_daemon_pool(processes=jobs) as pool: results = pool.map( partial( update_registry, **{ "yes": yes, "user": user, "check": check, "latest": latest, "interactive": interactive, "verbose": verbose, "format_": format, "all": all }), registries) else: for registry in registries: update_registry(registry, yes=yes, user=user, check=check, latest=latest, interactive=interactive, verbose=verbose, format_=format, all=all) if pipfile: logger.info("Updating Pipfiles: %s..." % pipfile) cli.echo( cli_format("Updating Pipfiles: %s..." % ", ".join(pipfile), cli.YELLOW)) with parallel.no_daemon_pool(processes=jobs) as pool: results = pool.map( partial(update_pipfile, **{"verbose": verbose}), pipfile) if builtins.all(results): cli.echo(cli_format("Pipfiles upto date.", cli.GREEN)) if project and pull_request: errstr = '%s not found. Use %s or the environment variable "%s" to set value.' if not git_username: raise ValueError(errstr % ("Git Username", "--git-username", getenvvar("GIT_USERNAME"))) if not git_email: raise ValueError( errstr % ("Git Email", "--git-email", getenvvar("GIT_EMAIL"))) for p in project: popen("git config user.name %s" % git_username, cwd=p.path) popen("git config user.email %s" % git_email, cwd=p.path) _, output, _ = popen("git status -s", output=True) if output: branch = get_timestamp_str(format_="%Y%m%d%H%M%S") popen("git checkout -B %s" % branch, quiet=not verbose) title = "fix(dependencies): Update dependencies to latest" body = "" # TODO: cross-check with "git add" ? files = p.requirements + [p.pipfile] popen("git add %s" % " ".join(files), quiet=not verbose, cwd=p.path) popen("git commit -m '%s'" % title, quiet=not verbose, cwd=p.path) popen("git push origin %s" % branch, quiet=not verbose, cwd=p.path) if not github_reponame: raise ValueError( errstr % ("GitHub Reponame", "--github-reponame", getenvvar("GITHUB_REPONAME"))) if not github_username: raise ValueError( errstr % ("GitHub Username", "--github-username", getenvvar("GITHUB_USERNAME"))) url = "/".join([ "https://api.github.com", "repos", github_username, github_reponame, "pulls" ]) headers = dict({ "Content-Type": "application/json", "Authorization": "token %s" % github_access_token }) data = dict(head="%s:%s" % (git_username, branch), base=target_branch, title=title, body=body) # Although there's monkey patch support for the "requests" # library, avoid using the "json" parameter which was # added in requests 2.4.2+ response = req.post(url, data=json.dumps(data), headers=headers) if response.ok: response = response.json() number = response["number"] url = "/".join( map(str, [ "https://github.com", github_username, github_reponame, "pull", number ])) message = "Created a Pull Request at %s" % url cli.echo(cli_format(message, cli.GREEN)) else: response.raise_for_status()
def update_registry(registry, yes=False, user=False, check=False, latest=False, interactive=False, verbose=False): source = registry.source packages = registry.packages table = Table( header=["Name", "Current Version", "Latest Version", "Home Page"]) dinfo = [] # Information DataFrame for package in packages: package.source = source package.installed = registry.installed if package.latest_version and package.current_version != package.latest_version: diff_type = None try: diff_type = semver.difference(package.current_version, package.latest_version) except (TypeError, ValueError): pass table.insert([ cli_format(package.name, _SEMVER_COLOR_MAP.get(diff_type, cli.CLEAR)), package.current_version or "na", _cli_format_semver(package.latest_version, diff_type), cli_format(package.home_page, cli.CYAN) ]) package.diff_type = diff_type dinfo.append(package) if not registry.installed: _update_requirements(package.source, package) stitle = "Installed Distributions (%s)" % source if registry.installed else source if not table.empty: string = table.render() cli.echo("\nSource: %s\n" % stitle) if not interactive: cli.echo(string) cli.echo() if not check: packages = [p for p in dinfo if p.diff_type != "major" or latest] npackages = len(packages) spackages = pluralize("package", npackages) # Packages "string" query = "Do you wish to update %s %s?" % (npackages, spackages) if npackages and (yes or interactive or cli.confirm(query, quit_=True)): for i, package in enumerate(packages): update = True query = "%s (%s > %s)" % (cli_format( package.name, _SEMVER_COLOR_MAP.get(package.diff_type, cli.CLEAR)), package.current_version, _cli_format_semver( package.latest_version, package.diff_type)) if interactive: update = yes or cli.confirm(query) if update: cli.echo( cli_format( "Updating %s of %s %s: %s" % (i + 1, npackages, spackages, cli_format(package.name, cli.GREEN)), cli.BOLD)) _pip.call("install", package.name, pip_exec=package.source, user=user, quiet=not verbose, no_cache_dir=True, upgrade=True) if not package.installed: _update_requirements(package.source, package) else: cli.echo("%s upto date." % cli_format(stitle, cli.CYAN))
def _command(*args, **kwargs): check_update_available() a = to_params(kwargs) if not a.verbose: logger.setLevel(log.NOTSET) logger.info("Environment: %s" % environment()) logger.info("Arguments Passed: %s" % locals()) if a.doctor: logger.info("Performing Diagnostics and attempting to fix.") if a.clean: path_config = get_config_path(name=NAME) paths = [osp.join(path_config, "db.db")] for path in paths: remove(path) # check database and repair. else: if a.resolve: import_or_raise("mixology") import_or_raise("semver", name="poetry-semver") populate_db = import_handler("pipupgrade.pubgrub.populate_db") populate_db() file_ = a.output if file_: logger.info("Writing to output file %s..." % file_) touch(file_) cli.echo(cli_format("Checking...", cli.YELLOW), file=file_) pip_path = a.pip_path or [] pip_path = [which(p) for p in pip_path] or _pip._PIP_EXECUTABLES logger.info("`pip` executables found: %s" % pip_path) logger.info("Using %s jobs..." % a.jobs) registries = [] if a.pip: logger.info("Updating pip executables: %s" % " ".join(pip_path)) with parallel.no_daemon_pool(processes=a.jobs) as pool: pool.imap_unordered( partial( update_pip, **{ "user": a.user, "quiet": not a.verbose, "file": file_ }), pip_path) if a.self: package = NAME logger.info("Updating %s..." % package) cli.echo(cli_format("Updating %s..." % package, cli.YELLOW), file=file_) _pip.call("install", package, user=a.user, quiet=not a.verbose, no_cache=True, upgrade=True, output=file_) cli.echo("%s upto date." % cli_format(package, cli.CYAN), file=file_) else: requirements = sequencify(a.requirements or []) pipfile = sequencify(a.pipfile or []) if a.project: project = sequencify(a.project) logger.info("Detecting projects and its dependencies...") with parallel.no_daemon_pool(processes=a.jobs) as pool: project = pool.imap_unordered( partial(Project.from_path, **{"depth_search": a.force}), project) requirements += flatten( map(lambda p: p.requirements, project)) pipfile += flatten( map(lambda p: [p.pipfile] if p.pipfile else [], project)) logger.info("Updating projects %s..." % project) if requirements: logger.info("Detecting requirements...") if not a.no_included_requirements: with parallel.no_daemon_pool(processes=a.jobs) as pool: results = pool.imap_unordered( get_included_requirements, requirements) requirements += flatten(results) requirements = list(set(requirements)) logger.info("Requirements found: %s" % requirements) with parallel.no_daemon_pool(processes=a.jobs) as pool: results = pool.imap_unordered( partial( get_registry_from_requirements, **{ "sync": a.no_cache, "jobs": a.jobs, "only_packages": a.packages, "file": file_, "ignore_packages": a.ignore, "resolve": a.resolve, "latest": a.latest }), requirements) registries += results else: with parallel.no_daemon_pool(processes=a.jobs) as pool: for registry in pool.imap_unordered( partial( get_registry_from_pip, **{ "user": a.user, "sync": a.no_cache, "outdated": not a.all, "build_dependency_tree": a.format in _DEPENDENCY_FORMATS, "jobs": a.jobs, "only_packages": a.packages, "ignore_packages": a.ignore, "resolve": a.resolve, "latest": a.latest }), pip_path): registries.append(registry) logger.info("Updating registries: %s..." % registries) for registry in registries: update_registry(registry, yes=a.yes, user=a.user, check=a.check, latest=a.latest, interactive=a.interactive, verbose=a.verbose, format_=a.format, all=a.all, filter_=a.packages, file=file_, raise_err=not a.ignore_error, upgrade_type=a.upgrade_type) if pipfile: logger.info("Updating Pipfiles: %s..." % pipfile) cli.echo(cli_format( "Updating Pipfiles: %s..." % ", ".join(pipfile), cli.YELLOW), file=file_) with parallel.no_daemon_pool(processes=a.jobs) as pool: results = pool.imap_unordered( partial(update_pipfile, **{"verbose": a.verbose}), pipfile) if builtins.all(results): cli.echo(cli_format("Pipfiles upto date.", cli.GREEN), file=file_) if a.project and a.pull_request: errstr = '%s not found. Use %s or the environment variable "%s" to set value.' if not a.git_username: raise ValueError(errstr % ("Git Username", "--git-username", getenvvar("GIT_USERNAME"))) if not a.git_email: raise ValueError( errstr % ("Git Email", "--git-email", getenvvar("GIT_EMAIL"))) for p in project: popen("git config user.name %s" % a.git_username, cwd=p.path) popen("git config user.email %s" % a.git_email, cwd=p.path) _, output, _ = popen("git status -s", output=True, cwd=p.path) if output: branch = get_timestamp_str(format_="%Y%m%d%H%M%S") popen("git checkout -B %s" % branch, quiet=not a.verbose, cwd=p.path) title = "fix(dependencies): Update dependencies to latest" body = "" # TODO: cross-check with "git add" ? files = p.requirements + [p.pipfile] popen("git add %s" % " ".join(files), quiet=not a.verbose, cwd=p.path) popen("git commit -m '%s'" % title, quiet=not a.verbose, cwd=p.path) popen("git push origin %s" % branch, quiet=not a.verbose, cwd=p.path) if not a.github_reponame: raise ValueError( errstr % ("GitHub Reponame", "--github-reponame", getenvvar("GITHUB_REPONAME"))) if not a.github_username: raise ValueError( errstr % ("GitHub Username", "--github-username", getenvvar("GITHUB_USERNAME"))) url = "/".join([ "https://api.github.com", "repos", a.github_username, a.github_reponame, "pulls" ]) headers = dict({ "Content-Type": "application/json", "Authorization": "token %s" % a.github_access_token }) data = dict(head="%s:%s" % (a.git_username, branch), base=a.target_branch, title=title, body=body) # Although there's monkey patch support for the "requests" # library, avoid using the "json" parameter which was # added in requests 2.4.2+ response = req.post(url, data=json.dumps(data), headers=headers) if response.ok: response = response.json() number = response["number"] url = "/".join( map(str, [ "https://github.com", a.github_username, a.github_reponame, "pull", number ])) message = "Created a Pull Request at %s" % url cli.echo(cli_format(message, cli.GREEN), file=file_) else: response.raise_for_status()
def command(pip_path=[], requirements=[], pipfile=[], project=None, pull_request=False, git_username=None, git_email=None, github_access_token=None, github_reponame=None, github_username=None, target_branch="master", latest=False, self=False, user=False, check=False, interactive=False, yes=False, no_color=True, verbose=False): cli.echo(cli_format("Checking...", cli.YELLOW)) pip_path = pip_path or [] pip_path = [which(p) for p in pip_path] or _pip._PIP_EXECUTABLES registries = [] if self: package = __name__ _pip.call("install", package, user=user, quiet=not verbose, no_cache=True, upgrade=True) cli.echo("%s upto date." % cli_format(package, cli.CYAN)) else: if project: requirements = requirements or [] pipfile = pipfile or [] for i, p in enumerate(project): project[i] = Project(osp.abspath(p)) requirements += project[i].requirements pipfile += [project[i].pipfile] if requirements: for requirement in requirements: path = osp.realpath(requirement) if not osp.exists(path): cli.echo(cli_format("{} not found.".format(path), cli.RED)) sys.exit(os.EX_NOINPUT) else: requirements += _get_included_requirements(requirement) for requirement in requirements: path = osp.realpath(requirement) if not osp.exists(path): cli.echo(cli_format("{} not found.".format(path), cli.RED)) sys.exit(os.EX_NOINPUT) else: packages = _pip.parse_requirements(requirement, session="hack") registry = Registry(source=path, packages=packages) registries.append(registry) else: for pip_ in pip_path: _, output, _ = _pip.call("list", outdated = True, \ format = "json", pip_exec = pip_) packages = json.loads(output) registry = Registry(source=pip_, packages=packages, installed=True) registries.append(registry) # _pip.get_installed_distributions() # https://github.com/achillesrasquinha/pipupgrade/issues/13 for registry in registries: source = registry.source packages = registry.packages table = Table(header=[ "Name", "Current Version", "Latest Version", "Home Page" ]) dinfo = [] # Information DataFrame for package in packages: package = Package(package) package.source = source package.installed = registry.installed if package.latest_version and package.current_version != package.latest_version: diff_type = None try: diff_type = semver.difference(package.current_version, package.latest_version) except (TypeError, ValueError): pass table.insert([ cli_format(package.name, _SEMVER_COLOR_MAP.get(diff_type, cli.CLEAR)), package.current_version or "na", _cli_format_semver(package.latest_version, diff_type), cli_format(package.home_page, cli.CYAN) ]) package.diff_type = diff_type dinfo.append(package) if not registry.installed: _update_requirements(package.source, package) stitle = "Installed Distributions (%s)" % source if registry.installed else source if not table.empty: string = table.render() cli.echo("\nSource: %s\n" % stitle) if not interactive: cli.echo(string) cli.echo() if not check: packages = [ p for p in dinfo if p.diff_type != "major" or latest ] npackages = len(packages) spackages = pluralize("package", npackages) # Packages "string" query = "Do you wish to update %s %s?" % (npackages, spackages) if npackages and (yes or interactive or cli.confirm(query, quit_=True)): for i, package in enumerate(packages): update = True query = "%s (%s > %s)" % ( cli_format( package.name, _SEMVER_COLOR_MAP.get( package.diff_type, cli.CLEAR)), package.current_version, _cli_format_semver(package.latest_version, package.diff_type)) if interactive: update = yes or cli.confirm(query) if update: cli.echo( cli_format( "Updating %s of %s %s: %s" % (i + 1, npackages, spackages, cli_format(package.name, cli.GREEN)), cli.BOLD)) _pip.call("install", package.name, pip_exec=package.source, user=user, quiet=not verbose, no_cache_dir=True, upgrade=True) if not package.installed: _update_requirements( package.source, package) else: cli.echo("%s upto date." % cli_format(stitle, cli.CYAN)) if pipfile: for pipf in pipfile: realpath = osp.realpath(pipf) basepath = osp.dirname(realpath) pipenv = which("pipenv", raise_err=True) popen("%s update" % pipenv, quiet=not verbose, cwd=basepath) cli.echo("%s upto date." % cli_format(realpath, cli.CYAN)) if project and pull_request: errstr = '%s not found. Use %s or the environment variable "%s" to set value.' if not git_username: raise ValueError(errstr % ("Git Username", "--git-username", getenvvar("GIT_USERNAME"))) if not git_email: raise ValueError( errstr % ("Git Email", "--git-email", getenvvar("GIT_EMAIL"))) for p in project: popen("git config user.name %s" % git_username, cwd=p.path) popen("git config user.email %s" % git_email, cwd=p.path) _, output, _ = popen("git status -s", output=True) if output: branch = get_timestamp_str(format_="%Y%m%d%H%M%S") popen("git checkout -B %s" % branch, quiet=not verbose) title = "fix(dependencies): Update dependencies to latest" body = "" # TODO: cross-check with "git add" ? files = p.requirements + [p.pipfile] popen("git add %s" % " ".join(files), quiet=not verbose, cwd=p.path) popen("git commit -m '%s'" % title, quiet=not verbose, cwd=p.path) popen("git push origin %s" % branch, quiet=not verbose, cwd=p.path) if not github_reponame: raise ValueError( errstr % ("GitHub Reponame", "--github-reponame", getenvvar("GITHUB_REPONAME"))) if not github_username: raise ValueError( errstr % ("GitHub Username", "--github-username", getenvvar("GITHUB_USERNAME"))) url = "/".join([ "https://api.github.com", "repos", github_username, github_reponame, "pulls" ]) headers = dict({ "Content-Type": "application/json", "Authorization": "token %s" % github_access_token }) data = dict(head="%s:%s" % (git_username, branch), base=target_branch, title=title, body=body) # Although there's monkey patch support for the "requests" # library, avoid using the "json" parameter which was # added in requests 2.4.2+ response = req.post(url, data=json.dumps(data), headers=headers) if response.ok: response = response.json() number = response["number"] url = "/".join( map(str, [ "https://github.com", github_username, github_reponame, "pull", number ])) message = "Created a Pull Request at %s" % url cli.echo(cli_format(message, cli.GREEN)) else: response.raise_for_status()