def test_difference(): assert difference("1.2.3", "2.3.4") == "major" assert difference("1.2.3", "1.3.4") == "minor" assert difference("1.2.3", "1.2.1") == "patch" assert difference("1.2.3", "1.2.3") == None with pytest.raises(ValueError): difference("1.2.3", "1.0") with pytest.raises(ValueError): difference("1.2.3.4", "1.2.3.4") with pytest.raises(NotImplementedError): difference("1.2.3-develop", "1.2.3")
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
def difference(self): difference = None try: difference = semver.difference(self.current_version, self.latest_version) except (TypeError, ValueError): pass return difference
def __init__(self, package, sync=False, pip_exec=None): logger.info("Initializing Package %s of type %s..." % (package, type(package))) self.current_version = None if isinstance(package, (_pip.Distribution, _pip.DistInfoDistribution, _pip.EggInfoDistribution)): self.name = package.project_name self.current_version = package.version elif isinstance(package, _pip.InstallRequirement): self.name = package.name if hasattr(package, "req"): if hasattr(package.req, "specifier"): self.current_version = str(package.req.specifier) else: self.current_version = package.installed_version elif isinstance(package, dict): self.name = package["name"] self.current_version = package["version"] self.latest_version = package.get("latest_version") elif isinstance(package, str): self.name = package if pip_exec: self.current_version = _get_package_version(package, pip_exec=pip_exec) res = None try: logger.info("Fetching package %s information from DB..." % self.name) res = _db.query(""" SELECT * FROM `tabPackage` WHERE name = '%s' """ % self.name) except db.OperationalError as e: logger.warn("Unable to fetch package name. %s" % e) if not res or sync: logger.info("Fetching PyPI info for package %s..." % self) _pypi_info = _get_pypi_info(self.name, raise_err=False) or {} if not hasattr(self, "latest_version"): self.latest_version = _pypi_info.get("version") self.home_page = _pypi_info.get("home_page") if not res: try: logger.info("Attempting to INSERT package %s into database." % self) _db.query(""" INSERT INTO `tabPackage` (name, latest_version, home_page, _created_at) VALUES ('%s', '%s', '%s', '%s') """ % (self.name, self.latest_version, self.home_page, datetime.now())) except (db.IntegrityError, db.OperationalError) as e: logger.warn("Unable to save package name. %s" % e) else: if sync: logger.info( "Attempting to UPDATE package %s within database." % self) try: _db.query(""" UPDATE `tabPackage` SET latest_version = '%s', home_page = '%s', _updated_at = '%s' WHERE name = '%s' """ % (self.latest_version, self.home_page, datetime.now(), self.name)) except db.OperationalError as e: logger.warn("Unable to update package name. %s" % e) else: logger.info("Using cached info for package %s." % self) self.latest_version = res["latest_version"] self.home_page = res["home_page"] self.dependency_tree = TreeNode(self) try: self.difference = semver.difference(self.current_version, self.latest_version) except (TypeError, ValueError): self.difference = None
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(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()