Beispiel #1
0
    def package(pspec, build_folder, dist_folder, requirements, run_compile_all):
        runez.ensure_folder(build_folder, clean=True)
        if pspec.python.major < 3:  # pragma: no cover
            abort("Packaging with pex is not supported any more with python2")

        pex_root = os.path.join(build_folder, "pex-root")
        tmp = os.path.join(build_folder, "pex-tmp")
        wheels = os.path.join(build_folder, "wheels")
        runez.ensure_folder(tmp, logger=False)
        runez.ensure_folder(wheels, logger=False)
        pex_venv = PythonVenv(pspec, folder=os.path.join(build_folder, "pex-venv"))
        pex_venv.pip_install("pex==2.1.75", *requirements)
        pex_venv.pip_wheel("--cache-dir", wheels, "--wheel-dir", wheels, *requirements)
        contents = PackageContents(pex_venv, pspec)
        if contents.entry_points:
            wheel_path = pspec.find_wheel(wheels)
            result = []
            for name in contents.entry_points:
                target = os.path.join(dist_folder, name)
                runez.delete(target)
                pex_venv.run_python(
                    "-mpex", "-o%s" % target, "--pex-root", pex_root, "--tmpdir", tmp,
                    "--no-index", "--find-links", wheels,  # resolver options
                    None if run_compile_all else "--no-compile",  # output options
                    "-c%s" % name,  # entry point options
                    "--python-shebang", "/usr/bin/env python%s" % pspec.python.major,
                    wheel_path,
                )
                result.append(target)

            return result
Beispiel #2
0
    def resolve(self):
        if not os.path.isdir(self.folder):
            abort("Folder %s does not exist" %
                  runez.red(runez.short(self.folder)))

        req = self.requirements
        if not req:
            default_req = runez.resolved_path("requirements.txt",
                                              base=self.folder)
            if os.path.exists(default_req):
                req = [default_req]

        if req:
            req = [("-r", runez.resolved_path(r, base=self.folder))
                   for r in req]

        req = runez.flattened(req, shellify=True)
        req.append(self.folder)
        self.requirements = req
        self.pspec = PackageSpec(CFG, self.folder)
        LOG.info("Using python: %s" % self.pspec.python)
        if self.dist.startswith("root/"):
            # Special case: we're targeting 'root/...' probably for a debian, use target in that case to avoid venv relocation issues
            target = self.dist[4:]
            if os.path.isdir(target):
                LOG.debug("debian mode: %s -> %s", self.dist, target)
                self.dist = target

            parts = self.dist.split("/")
            if len(parts) <= 2:
                # Auto-add package name to targets of the form root/subfolder (most typical case)
                self.dist = os.path.join(self.dist, self.pspec.dashed)
Beispiel #3
0
    def __init__(self, spec):
        self.base, _, self.target = spec.partition(":")
        if not self.base or not self.target:
            abort("Invalid symlink specification '%s'" % spec)

        self.base = runez.resolved_path(self.base)
        self.target = runez.resolved_path(self.target)
Beispiel #4
0
def base(what):
    """Show pickley base folder"""
    path = CFG.base.path
    if what == "bootstrap-own-wrapper":
        # Internal: called by bootstrap script
        from pickley.delivery import DeliveryMethodWrap

        pspec = PackageSpec(CFG, PICKLEY, version=__version__)
        venv = PythonVenv(pspec, create=False)
        wrap = DeliveryMethodWrap()
        wrap.install(pspec, venv, {PICKLEY: PICKLEY})
        return

    if what:
        paths = {
            "audit": CFG.meta.full_path("audit.log"),
            "cache": CFG.cache.path,
            "config": CFG.meta.full_path("config.json"),
            "meta": CFG.meta.path,
        }
        paths["audit.log"] = paths["audit"]
        paths["config.json"] = paths["config"]
        path = paths.get(what)
        if not path:
            options = [runez.green(s) for s in sorted(paths)]
            abort("Unknown base folder reference '%s', try one of: %s" %
                  (runez.red(what), ", ".join(options)))

    print(path)
Beispiel #5
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
Beispiel #6
0
    def pip_install(self, *args):
        """Allows to not forget to state the -i index..."""
        # bin_marker = ":all:" if runez.SYS_INFO.platform_id.is_macos and runez.SYS_INFO.platform_id.arch == "arm64" else None
        # r = self.run_pip("install", "-i", self.index, "--no-binary", bin_marker, *args, fatal=False)
        r = self.run_pip("install", "-i", self.index, *args, fatal=False)
        if r.failed:
            message = "\n".join(simplified_pip_error(r.error, r.output))
            abort(message)

        return r
Beispiel #7
0
def find_base():
    base_path = runez.resolved_path(os.environ.get("PICKLEY_ROOT"))
    if base_path:
        if not os.path.isdir(base_path):
            abort("PICKLEY_ROOT points to non-existing directory %s" %
                  runez.red(base_path))

        return runez.resolved_path(base_path)

    program_path = PickleyConfig.program_path
    return _find_base_from_program_path(program_path) or os.path.dirname(
        program_path)
Beispiel #8
0
    def validate_sanity_check(exe, sanity_check):
        if not exe or not sanity_check:
            return None

        r = runez.run(exe, sanity_check, fatal=False)
        if r.failed:
            if does_not_implement_cli_flag(r.output, r.error):
                return "does not respond to %s" % sanity_check

            abort("'%s' failed %s sanity check: %s" %
                  (exe, sanity_check, r.full_output))

        return runez.first_line(r.output or r.error)
Beispiel #9
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"))
Beispiel #10
0
    def install(self, pspec, venv, entry_points):
        """
        Args:
            pspec (pickley.PackageSpec): Package spec this installation is for
            venv (pickley.package.PythonVenv): Virtual env where executables reside (DOT_META/<package>/...)
            entry_points (dict | list): Full path of executable to deliver (<base>/<entry_point>)
        """
        if not pspec.is_clear_for_installation():
            auto_uninstall(pspec.exe_path(pspec.dashed))

        try:
            prev_manifest = pspec.get_manifest()
            for name in entry_points:
                src = venv.bin_path(name)
                dest = pspec.exe_path(name)
                if runez.DRYRUN:
                    print("Would %s %s -> %s" %
                          (self.short_name, short(dest), short(src)))
                    continue

                if not os.path.exists(src):
                    abort(
                        "Can't %s %s -> %s: source does not exist" %
                        (self.short_name, short(dest), runez.red(short(src))))

                LOG.debug("%s %s -> %s" %
                          (self.action, short(dest), short(src)))
                self._install(pspec, dest, src)

            manifest = pspec.save_manifest(entry_points)
            if not runez.DRYRUN and prev_manifest and prev_manifest.entrypoints:
                for old_ep in prev_manifest.entrypoints:
                    if old_ep and old_ep not in entry_points:
                        # Remove old entry points that are not in new manifest any more
                        runez.delete(pspec.exe_path(old_ep))

            if self.ping:
                # Touch the .ping file since this is a fresh install (no need to check for upgrades right away)
                runez.touch(pspec.ping_path)

            return manifest

        except Exception as e:
            abort("Failed to %s %s: %s" %
                  (self.short_name, short(pspec), runez.red(e)))
Beispiel #11
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)
Beispiel #12
0
    def delivery_method_by_name(cls, name):
        """
        Args:
            name (str): Name of delivery method

        Returns:
            (DeliveryMethod): Associated delivery method
        """
        if name == "wrap":
            return DeliveryMethodWrap()

        if name == "symlink":
            return DeliveryMethodSymlink()

        return abort("Unknown delivery method '%s'" % runez.red(name))
Beispiel #13
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))