Example #1
0
    def __enter__(self):
        """Acquire lock"""
        if CFG.base:
            runez.Anchored.add(CFG.base.path)

        cutoff = time.time() + self.give_up
        holder_args = self._locked_by()
        while holder_args:
            if time.time() >= cutoff:
                lock = runez.bold(runez.short(self.lock_path))
                holder_args = runez.bold(holder_args)
                raise SoftLockException(
                    "Can't grab lock %s, giving up\nIt is being held by: pickley %s"
                    % (lock, holder_args))

            time.sleep(1)
            holder_args = self._locked_by()

        # We got the soft lock
        if runez.DRYRUN:
            print("Would acquire %s" % runez.short(self.lock_path))

        else:
            runez.log.trace("Acquired %s" % runez.short(self.lock_path))

        runez.write(self.lock_path,
                    "%s\n%s\n" % (os.getpid(), runez.quoted(sys.argv[1:])),
                    logger=False)
        self.pspec.resolve()
        return self
Example #2
0
def perform_install(pspec, is_upgrade=False, force=False, quiet=False):
    """
    Args:
        pspec (PackageSpec): Package spec to install
        is_upgrade (bool): If True, intent is an upgrade (not a new install)
        force (bool): If True, check latest version even if recently checked
        quiet (bool): If True, don't chatter

    Returns:
        (pickley.TrackedManifest): Manifest is successfully installed (or was already up-to-date)
    """
    with SoftLock(pspec):
        started = time.time()
        pspec.resolve()
        skip_reason = pspec.skip_reason(force)
        if skip_reason:
            inform("Skipping installation of %s: %s" %
                   (pspec.dashed, runez.bold(skip_reason)))
            return None

        manifest = pspec.get_manifest()
        if is_upgrade and not manifest and not quiet:
            abort("'%s' is not installed" % runez.red(pspec))

        if not pspec.version:
            desired = pspec.get_desired_version_info(force=force)
            if desired.problem:
                action = "upgrade" if is_upgrade else "install"
                abort("Can't %s %s: %s" %
                      (action, pspec, runez.red(desired.problem)))

            pspec.version = desired.version

        if not force and manifest and manifest.version == pspec.version and pspec.is_healthily_installed(
        ):
            if not quiet:
                status = "up-to-date" if is_upgrade else "installed"
                inform("%s v%s is already %s" %
                       (pspec.dashed, runez.bold(pspec.version), status))

            pspec.groom_installation()
            return manifest

        setup_audit_log()
        manifest = PACKAGER.install(pspec)
        if manifest and not quiet:
            note = " in %s" % runez.represented_duration(time.time() - started)
            action = "Upgraded" if is_upgrade else "Installed"
            if runez.DRYRUN:
                action = "Would state: %s" % action

            inform("%s %s v%s%s" %
                   (action, pspec.dashed, runez.bold(
                       pspec.version), runez.dim(note)))

        if not pspec._pickley_dev_mode:
            pspec.groom_installation()

        return manifest
Example #3
0
    def represented(self):
        """str: Human readable representation of this configuration"""
        result = ["%s: %s" % (runez.bold("base"), self), ""]
        for c in self.configs:
            result.append(c.represented())

        return "\n".join(result).strip()
Example #4
0
    def find_python(self, pspec=None, fatal=True):
        """
        Args:
            pspec (PackageSpec | None): Package spec, when applicable
            fatal (bool): If True, abort execution is no valid python could be found

        Returns:
            (runez.pyenv.PythonInstallation): Object representing python installation
        """
        desired = self.get_value("python", pspec=pspec)
        desired = runez.flattened(desired, split=",")
        if not desired:
            # Edge case: configured empty python... just use invoker in that case
            return self.available_pythons.invoker

        issues = []
        python = None
        for d in desired:
            python = self.available_pythons.find_python(d)
            if not python.problem:
                return python

            issues.append(
                "Python '%s' skipped: %s" %
                (runez.bold(runez.short(d)), runez.red(python.problem)))

        for i in issues:  # Warn only if no python could be found at all
            LOG.warning(i)

        if fatal:
            abort("No suitable python installation found")

        return python
Example #5
0
def mv(sample, target):
    """Move a test sample (and its baseline) to a new place"""
    new_category, _, new_basename = target.partition("/")
    if "/" in new_basename:
        sys.exit("Invalid target '%s': use at most one / separator" %
                 runez.red(target))

    if not new_basename:
        new_basename = sample.basename

    if new_basename.endswith(".yml"):
        new_basename = new_basename[:-4]

    old_source = os.path.join(sample.category, sample.basename)
    new_target = os.path.join(new_category, new_basename)
    if old_source == new_target:
        print("%s is already in the right spot" % runez.bold(sample))
        sys.exit(0)

    existing = TestSamples.get_samples(new_target + ".yml")
    if existing:
        sys.exit("There is already a sample '%s'" % runez.red(new_target))

    TestSamples.move_sample_file(sample, new_category, new_basename)
    TestSamples.move_sample_file(sample,
                                 new_category,
                                 new_basename,
                                 kind=TestSamples.K_DESERIALIZED)
    TestSamples.move_sample_file(sample,
                                 new_category,
                                 new_basename,
                                 kind=TestSamples.K_TOKEN)
    TestSamples.clean_samples()
Example #6
0
def replay(existing, tokens, samples):
    """Rerun samples and compare them with their current baseline"""
    kinds = []
    if tokens:
        kinds.append(TestSamples.K_TOKEN)

    skipped = 0
    for sample in samples:
        report = sample.replay(*kinds)
        if report is runez.UNSET:
            skipped += 1
            report = None if existing else " %s" % runez.yellow("skipped")

        elif report:
            report = "\n%s" % "\n".join("  %s" % s
                                        for s in report.splitlines())

        else:
            report = " %s" % runez.green("OK")

        if report is not None:
            print("** %s:%s" % (runez.bold(sample.name), report))

    if skipped:
        print(runez.dim("-- %s skipped" % runez.plural(skipped, "sample")))
Example #7
0
def uninstall(all, packages):
    """Uninstall packages"""
    if packages and all:
        abort("Either specify packages to uninstall, or --all (but not both)")

    if not packages and not all:
        abort("Specify packages to uninstall, or --all")

    if packages and PICKLEY in packages:
        abort(
            "Run 'uninstall --all' if you wish to uninstall pickley itself (and everything it installed)"
        )

    setup_audit_log()
    for pspec in CFG.package_specs(packages):
        manifest = pspec.get_manifest()
        if not manifest or not manifest.version:
            abort("%s was not installed with pickley" %
                  runez.bold(pspec.dashed))

        if manifest.entrypoints:
            for ep in manifest.entrypoints:
                runez.delete(pspec.exe_path(ep))

        runez.delete(pspec.meta_path)
        action = "Would uninstall" if runez.DRYRUN else "Uninstalled"
        inform("%s %s" % (action, pspec.dashed))

    if all:
        runez.delete(CFG.base.full_path(PICKLEY))
        runez.delete(CFG.meta.path)
        inform("pickley is now %s" % runez.red("uninstalled"))
Example #8
0
    def header(self, report=None):
        """
        :param GitRunReport|None report: Optional report to show (defaults to self.git.report)
        :return str: Textual representation
        """
        report = GitRunReport(report or self.git.report(inspect_remotes=self.prefs.inspect_remotes))

        result = "%s:" % self.aligned_name

        if self.git.is_git_checkout:
            branch = runez.bold(self.git.branches.shortened_current_branch)
            n = len(self.git.branches.local)
            if n > 1:
                branch += " +%s" % (n - 1)

            result += " [%s]" % branch

            freshness = self.git.status.freshness
            if freshness:
                result += " %s" % freshness

        if not report.has_problems and self.parent and self.prefs and self.prefs.all and self.parent.predominant:
            if self.origin_project != self.parent.predominant:
                report.add(note="not part of %s" % self.parent.predominant)

        if report:
            rep = report.representation()
            if rep:
                result += "  %s" % rep

        return result
Example #9
0
File: cli.py Project: zsimic/mgit
def clean_show(target):
    """
    :param GitCheckout target: Target to show
    """
    print(target.header())
    if not target.git.local_cleanable_branches:
        print("  No local branches can be cleaned")

    else:
        for branch in target.git.local_cleanable_branches:
            print("  %s branch %s can be cleaned" %
                  (runez.bold("local"), runez.bold(branch)))

    if not target.git.remote_cleanable_branches:
        print("  No remote branches can be cleaned")

    else:
        for branch in target.git.remote_cleanable_branches:
            print("  %s can be cleaned" % (runez.bold(branch)))
Example #10
0
    def represented(self):
        """str: Human readable representation of this configuration"""
        result = ["%s:" % runez.bold(runez.short(self.source))]
        if self.values:
            self._add_dict_representation(result, self.values)

        else:
            result[0] += runez.dim("  # empty")

        result.append("")
        return "\n".join(result)
Example #11
0
    def show_result(self, data, tokens=False):
        rtype = "tokens" if tokens else data.__class__.__name__ if data is not None else "None"
        rep = data
        if not tokens or isinstance(data, Exception):
            rep = TestSettings.represented(data)

        message = "---- %s: %s" % (runez.bold(self.name), runez.dim(rtype))
        if isinstance(data, NotImplementedError):
            print("%s - %s" % (message, rep))
            return

        print(message)
        print(rep)
Example #12
0
def check(force, verbose, packages):
    """Check whether specified packages need an upgrade"""
    code = 0
    packages = CFG.package_specs(packages)
    if not packages:
        print("No packages installed")
        sys.exit(0)

    for pspec in packages:
        skip_reason = pspec.skip_reason(force)
        if skip_reason:
            print(
                "%s: %s, %s" %
                (pspec.dashed, runez.bold("skipped"), runez.dim(skip_reason)))
            continue

        desired = pspec.get_desired_version_info(force=force)
        dv = runez.bold(desired and desired.version)
        manifest = pspec.get_manifest()
        if desired.problem:
            msg = desired.problem
            code = 1

        elif not manifest or not manifest.version:
            msg = "v%s is not installed" % dv
            code = 1

        elif manifest.version == desired.version:
            msg = "v%s is installed" % dv

        else:
            action = "upgraded to" if desired.source == "latest" else "caught up to %s" % desired.source
            msg = "v%s installed, can be %s v%s" % (runez.dim(
                manifest.version), action, dv)

        print("%s: %s" % (pspec.dashed, msg))

    sys.exit(code)
Example #13
0
    def colored_key(key, indent):
        if (key in K_CLI or key in K_LEAVES) and indent in (1, 3):
            return runez.teal(key)

        if key in K_DIRECTIVES and indent == 1:
            return runez.dim(key)

        if key in K_GROUPS and indent == 1:
            return runez.purple(key)

        if indent == 2:
            return runez.bold(key)

        return runez.red(key)
Example #14
0
File: git.py Project: zsimic/mgit
    def run_raw_git_command(self, *args):
        """
        :param args: Execute git command with provided args, don't capture its output, but let it show through stdout/stderr
        :return GitRunReport: Report
        """
        cmd, pretty_args = self._git_command(args)
        pretty_args = "git %s" % " ".join(args)
        print("Running: %s" % runez.bold(pretty_args))
        proc = subprocess.Popen(cmd)  # nosec
        proc.communicate()
        if proc.returncode:
            return GitRunReport(problem="git exited with code %s" %
                                proc.returncode)

        return GitRunReport()
Example #15
0
    def header(self):
        result = "%s:" % runez.purple(runez.short(self.path))

        if not self.projects:
            return "%s %s" % (result, runez.orange("no git folders"))

        if self.predominant:
            result += runez.bold(" %s %s" % (len(self.projects[self.predominant]), self.predominant))

        else:
            result += runez.orange(" no predominant project")

        if self.additional:
            result += " (%s)" % runez.purple(", ".join("+%s %s" % (len(self.projects[project]), project) for project in self.additional))

        return result
Example #16
0
    def install(pspec, ping=True):
        delivery = DeliveryMethod.delivery_method_by_name(pspec.settings.delivery)
        delivery.ping = ping
        args = [pspec.specced]
        if pspec.folder:
            args = [pspec.folder]

        elif pspec._pickley_dev_mode:
            args = ["-e", pspec._pickley_dev_mode]  # pragma: no cover, convenience case for running pickley from .venv/

        venv = PythonVenv(pspec)
        venv.pip_install(*args)
        contents = PackageContents(venv, pspec)
        if not contents.entry_points:
            runez.delete(pspec.meta_path)
            abort("Can't install '%s', it is %s" % (runez.bold(pspec.dashed), runez.red("not a CLI")))

        return delivery.install(pspec, venv, contents.entry_points)
Example #17
0
def package(build, dist, symlink, no_compile, sanity_check, project,
            requirement):
    """Package a project from source checkout"""
    started = time.time()
    runez.log.spec.default_logger = LOG.info
    CFG.set_base(runez.resolved_path(build))
    finalizer = PackageFinalizer(project, dist, symlink)
    finalizer.sanity_check = sanity_check
    finalizer.requirements = requirement
    finalizer.compile = not no_compile
    finalizer.resolve()
    report = finalizer.finalize()
    if report:
        inform("")
        inform(report)
        inform("")

    elapsed = "in %s" % runez.represented_duration(time.time() - started)
    inform("Packaged %s successfully %s" %
           (runez.bold(runez.short(project)), runez.dim(elapsed)))
Example #18
0
def auto_uninstall(target):
    """
    Args:
        target (str): Path to executable to auto-uninstall if needed

    Returns:
        Aborts if uninstallation was not possible
    """
    brew, name = find_brew_name(target)
    if brew and name:
        result = runez.run(brew,
                           "uninstall",
                           "-f",
                           name,
                           fatal=False,
                           logger=LOG.info)
        if result.succeeded:
            LOG.info("Auto-uninstalled brew formula '%s'" % name)
            return  #

        command = "%s uninstall %s" % (brew, name)
        abort("'%s' failed, please check" % runez.bold(command))

    abort("Can't automatically uninstall %s" % runez.short(target))
Example #19
0
def cmd_progress_bar():
    """Show a progress bar sample"""
    names = AsciiAnimation.available_names()
    parser = runez.cli.parser()
    parser.add_argument(
        "--delay",
        "-d",
        type=float,
        default=100.0,
        help="Time in milliseconds to sleep between iterations.")
    parser.add_argument("--iterations",
                        "-i",
                        type=int,
                        default=100,
                        help="Number of iterations to run.")
    parser.add_argument("--log-every",
                        "-l",
                        type=int,
                        default=5,
                        help="Log a message every N iterations.")
    parser.add_argument("--spinner",
                        "-s",
                        choices=names,
                        default=None,
                        help="Pick spinner to use.")
    parser.add_argument(
        "--sleep",
        type=float,
        default=None,
        help=
        "Extra sleep when done, useful for inspecting animation a bit further."
    )
    parser.add_argument(
        "--no-spinner",
        "-n",
        action="store_true",
        help="Useful to compare CPU usage with and without spinner.")
    parser.add_argument("--verbose",
                        "-v",
                        action="store_true",
                        help="More chatty output.")
    parser.add_argument("name",
                        nargs="*",
                        help="Names of modules to show (by default: all).")
    args = parser.parse_args()

    process = None
    try:
        import psutil

        process = psutil.Process(os.getpid())
        process.cpu_percent()

    except ImportError:  # pragma: no cover
        pass

    runez.log.setup(console_format="%(levelname)s %(message)s",
                    console_level=logging.INFO,
                    trace="RUNEZ_DEBUG")
    if not args.no_spinner:
        runez.log.progress.start(frames=args.spinner,
                                 max_columns=40,
                                 spinner_color=runez.yellow)

    logger = logging.info if args.verbose else logging.debug
    for i in runez.ProgressBar(range(args.iterations)):
        i += 1
        if args.log_every and i % args.log_every == 0:
            logger("Running\niteration %s %s", runez.red(i), "-" * 50)
            logger = logging.debug

        else:
            runez.log.trace("At iteration %s" % i)

        if args.verbose and i % 10 == 0:  # pragma: no cover
            print("iteration %s" % runez.bold(i))

        if i == 42:  # pragma: no cover
            runez.log.progress.show(
                "some progress msg"
            )  # debug() and trace() messages don't appear any more after this
            for _ in runez.ProgressBar(range(10)):
                time.sleep(0.1)

        time.sleep(args.delay / 1000)

    msg = "done"
    if process:
        cpu_usage = ("%.2f" % process.cpu_percent()).rstrip("0")
        msg += " (%s%% CPU usage)" % cpu_usage

    print(msg)
    if args.sleep:
        runez.log.progress.show(msg)
        time.sleep(args.sleep)
Example #20
0
File: cli.py Project: zsimic/mgit
def handle_single_clean(target, what):
    """
    :param GitCheckout target: Single checkout to clean
    :param str what: Operation
    """
    report = target.git.fetch()
    if report.has_problems:
        if what != "reset":
            what = "clean"

        print(
            target.header(
                GitRunReport(report).add(problem="<can't %s" % what)))
        runez.abort("")

    if what == "reset":
        return clean_reset(target)

    if what == "show":
        return clean_show(target)

    total_cleaned = 0
    print(target.header())

    if what in "remote all":
        if not target.git.remote_cleanable_branches:
            print("  No remote branches can be cleaned")

        else:
            total = len(target.git.remote_cleanable_branches)
            cleaned = 0
            for branch in target.git.remote_cleanable_branches:
                remote, _, name = branch.partition("/")
                if not remote and name:
                    raise Exception("Unknown branch spec '%s'" % branch)

                if run_git(target, False, "branch", "--delete", "--remotes",
                           branch):
                    cleaned += run_git(target, False, "push", "--delete",
                                       remote, name)

            total_cleaned += cleaned
            if cleaned == total:
                print("%s cleaned" % runez.plural(cleaned, "remote branch"))

            else:
                print("%s/%s remote branches cleaned" % (cleaned, total))

            target.git.reset_cached_properties()
            if what == "all":
                # Fetch to update remote branches (and correctly detect new dangling local)
                target.git.fetch()

    if what in "local all":
        if not target.git.local_cleanable_branches:
            print("  No local branches can be cleaned")

        else:
            total = len(target.git.local_cleanable_branches)
            cleaned = 0
            for branch in target.git.local_cleanable_branches:
                if branch == target.git.branches.current:
                    fallback = target.git.fallback_branch()
                    if not fallback:
                        print(
                            "Skipping branch '%s', can't determine fallback branch"
                            % target.git.branches.current)
                        continue

                    run_git(target, True, "checkout", fallback)
                    run_git(target, True, "pull")

                cleaned += run_git(target, False, "branch", "--delete", branch)

            total_cleaned += cleaned
            if cleaned == total:
                print(
                    runez.bold("%s cleaned" %
                               runez.plural(cleaned, "local branch")))

            else:
                print(
                    runez.orange("%s/%s local branches cleaned" %
                                 (cleaned, total)))

            target.git.reset_cached_properties()

    if total_cleaned:
        print(target.header())
Example #21
0
def test_colors():
    dim = runez.color.style.dim
    assert runez.color.cast_style(dim) is dim
    assert runez.color.cast_style(runez.dim) is runez.dim
    assert runez.color.cast_style("dim") is dim
    assert runez.color.cast_color(dim) is dim
    assert runez.color.cast_color("dim") is dim
    assert runez.color.cast_color("blue") is runez.color.fg.blue

    msg1 = dim("hi")
    msg2 = runez.colored("hi", "dim")
    assert msg1 == msg2

    with pytest.raises(ValueError):
        runez.color.cast_style("foo")

    assert not runez.color.is_coloring()
    with runez.ActivateColors(terminal.Ansi16Backend):
        # Check that backend can be passed as class (flavor auto-determined in that case)
        assert runez.color.is_coloring()
        assert "ansi16" in runez.color.backend.name

        msg1 = runez.dim("hi")
        msg2 = runez.colored("hi", "dim")
        assert msg1 == msg2

    assert not runez.color.is_coloring()
    with runez.ActivateColors(terminal.Ansi16Backend(flavor="neutral")):
        assert runez.color.is_coloring()
        assert runez.red(None) == "\x1b[31mNone\x1b[39m"
        assert runez.blue("") == ""
        assert runez.plain("hello") == "hello"
        assert runez.yellow("hello") == "\x1b[33mhello\x1b[39m"
        assert runez.yellow("hello", size=4) == "\x1b[33mh...\x1b[39m"
        assert runez.bold(1) == "\x1b[1m1\x1b[22m"

        assert runez.color.bg.get(None) is None
        assert runez.color.bg.get("blue") is runez.color.bg.blue

        assert runez.dim("") == ""
        assert runez.dim("hello", size=4) == "\x1b[2mh...\x1b[22m"

        # Verify unicode char 'μ' from represented_duration() works
        assert "foo: %s" % runez.dim(runez.represented_duration(0.010049)) == "foo: \x1b[2m10 ms 49 μs\x1b[22m"
        assert "foo: %s" % runez.blue(runez.represented_duration(0.010049)) == "foo: \x1b[34m10 ms 49 μs\x1b[39m"

    assert not runez.color.is_coloring()
    assert runez.black("") == ""
    assert runez.blue("") == ""
    assert runez.brown("") == ""
    assert runez.gray("") == ""
    assert runez.green("") == ""
    assert runez.orange("") == ""
    assert runez.plain("hello") == "hello"
    assert runez.purple("") == ""
    assert runez.red(None) == "None"
    assert runez.teal("") == ""
    assert runez.white("") == ""
    assert runez.yellow("hello") == "hello"
    assert runez.blink("hello") == "hello"
    assert runez.bold(1) == "1"
    assert runez.dim("") == ""
    assert runez.invert("") == ""
    assert runez.italic("") == ""
    assert runez.strikethrough("") == ""
    assert runez.underline("") == ""

    assert str(runez.color.fg.black) == "black"