Exemplo n.º 1
0
def _format_package(package):
    difference = None

    try:
        difference = semver.difference(package.current_version,
                                       package.latest_version)
    except (TypeError, ValueError):
        pass

    string = "* %s" % cli_format(package.name,
                                 _SEMVER_COLOR_MAP.get(difference, cli.CLEAR))

    if getattr(package, "has_dependency_conflict", False):
        string += cli_format(" [dependency conflict]", cli.RED)

    if package.current_version:
        string += " (%s)" % package.current_version

    if package.latest_version and package.current_version != package.latest_version:
        string += " -> (%s)" % _cli_format_semver(package.latest_version,
                                                  difference)

    string += " " + cli_format("[%s]" % package.home_page, cli.CYAN)

    return string
Exemplo n.º 2
0
def update_pip(pip_exec, user=None, quiet=None, file=None):
    cli.echo(cli_format("Updating %s..." % pip_exec, cli.YELLOW), file=file)

    output = pip_upgrade("pip", pip_exec=pip_exec, user=user, quiet=quiet)

    if isinstance(output, int):
        code = output
    else:
        code = output[0]

    if not code:
        cli.echo("%s upto date." % cli_format(pip_exec, cli.CYAN), file=file)

    return output
Exemplo n.º 3
0
def get_registry_from_requirements(requirements,
                                   sync=False,
                                   jobs=1,
                                   only_packages=[],
                                   file=None):
    path = osp.realpath(requirements)

    if not osp.exists(path):
        cli.echo(cli_format("{} not found.".format(path), cli.RED), file=file)
        sys.exit(os.EX_NOINPUT)
    else:
        packages = _pip.parse_requirements(requirements, session="hack")

        if only_packages:
            packages = [p for p in packages if p.name in only_packages]

        registry = Registry(source=path,
                            packages=packages,
                            sync=sync,
                            jobs=jobs)

    logger.info("Packages within requirements %s found: %s..." %
                (requirements, registry.packages))

    return registry
Exemplo n.º 4
0
 def _format(x):
     return cli_format(x, cli.YELLOW)
Exemplo n.º 5
0
def update_registry(registry,
                    yes=False,
                    user=False,
                    check=False,
                    latest=False,
                    interactive=False,
                    format_="table",
                    all=False,
                    file=None,
                    raise_err=True,
                    verbose=False):
    source = registry.source
    packages = registry.packages

    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 != "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)
Exemplo n.º 6
0
def command(packages=[],
            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,
            ignore_error=False,
            force=False,
            verbose=False):
    if not verbose:
        logger.setLevel(log.NOTSET)

    logger.info("Environment: %s" % environment())
    logger.info("Arguments Passed: %s" % locals())

    file_ = output

    if file_:
        logger.info("Writing to output file %s..." % file_)
        touch(file_)

    cli.echo(cli_format("Checking...", cli.YELLOW), file=file_)

    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.imap_unordered(
                partial(update_pip, **{
                    "user": user,
                    "quiet": not verbose,
                    "file": file
                }), pip_path)

    if self:
        package = __name__
        logger.info("Updating %s..." % package)

        cli.echo(cli_format("Updating %s..." % package, cli.YELLOW),
                 file=file_)

        _pip.call("install",
                  package,
                  user=user,
                  quiet=not verbose,
                  no_cache=True,
                  upgrade=True)

        cli.echo("%s upto date." % cli_format(package, cli.CYAN), file=file_)
    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.imap_unordered(
                    partial(Project.from_path, **{"depth_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.imap_unordered(get_included_requirements,
                                                  requirements)
                    requirements += flatten(results)

            logger.info("Requirements found: %s" % requirements)

            with parallel.no_daemon_pool(processes=jobs) as pool:
                results = pool.imap_unordered(
                    partial(
                        get_registry_from_requirements, **{
                            "sync": no_cache,
                            "jobs": jobs,
                            "only_packages": packages,
                            "file": file_
                        }), requirements)
                registries += results
        else:
            with parallel.no_daemon_pool(processes=jobs) as pool:
                for registry in pool.imap_unordered(
                        partial(
                            get_registry_from_pip, **{
                                "user": user,
                                "sync": no_cache,
                                "outdated": not all,
                                "build_dependency_tree": format
                                in _DEPENDENCY_FORMATS,
                                "jobs": jobs,
                                "only_packages": packages
                            }), pip_path):
                    registries.append(registry)

        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:
                pool.imap_unordered(
                    partial(
                        update_registry, **{
                            "yes": yes,
                            "user": user,
                            "check": check,
                            "latest": latest,
                            "interactive": interactive,
                            "verbose": verbose,
                            "format_": format,
                            "all": all,
                            "filter": packages,
                            "file": file_,
                            "raise_err": not ignore_error
                        }), 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,
                                file=file_,
                                raise_err=not ignore_error)

        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=jobs) as pool:
                results = pool.imap_unordered(
                    partial(update_pipfile, **{"verbose": verbose}), pipfile)

                if builtins.all(results):
                    cli.echo(cli_format("Pipfiles upto date.", cli.GREEN),
                             file=file_)

        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, cwd=p.path)

                if output:
                    branch = get_timestamp_str(format_="%Y%m%d%H%M%S")
                    popen("git checkout -B %s" % branch,
                          quiet=not 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 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), file=file_)
                    else:
                        response.raise_for_status()