Beispiel #1
0
 def refresh_entry_points(self):
     """Refresh entry point from saved json and/or build folder"""
     if runez.DRYRUN:
         return
     self._entry_points = self.get_entry_points()
     if self._entry_points:
         runez.save_json(self._entry_points, self.entry_points_path, fatal=False)
Beispiel #2
0
def check_install_from_pypi(cli, delivery, package, simulate_version=None):
    cli.run("--debug", "-d%s" % delivery, "install", package)
    assert cli.succeeded
    assert cli.match("Installed %s" % package)
    assert runez.is_executable(package)
    m = TrackedManifest.from_file(dot_meta("%s/.manifest.json" % package))
    assert str(m)
    assert m.entrypoints[package]
    assert m.install_info.args == runez.quoted(cli.args)
    assert m.install_info.timestamp
    assert m.install_info.vpickley == __version__
    assert m.settings.delivery == delivery
    assert m.settings.python
    assert m.version

    r = runez.run(package, "--version")
    assert r.succeeded

    cli.expect_success("--debug auto-upgrade %s" % package,
                       "Skipping auto-upgrade, checked recently")
    cli.expect_success("install %s" % package, "is already installed")
    cli.expect_success("check", "is installed")
    cli.expect_success("list", package)
    cli.expect_success("upgrade", "is already up-to-date")

    if simulate_version:
        m.version = simulate_version
        runez.save_json(m.to_dict(), dot_meta("%s/.manifest.json" % package))
        cli.expect_success(
            "check", "v%s installed, can be upgraded to" % simulate_version)
Beispiel #3
0
def test_json(temp_folder, monkeypatch):
    assert runez.read_json(None) is None

    assert runez.represented_json(None) == "null\n"
    assert runez.represented_json([]) == "[]\n"
    assert runez.represented_json({}) == "{}\n"
    assert runez.represented_json("foo") == '"foo"\n'

    assert runez.represented_json({None: 2}, none=True) == '{\n  "null": 2\n}\n'
    assert runez.represented_json({None: 2}, none="None") == '{\n  "None": 2\n}\n'
    assert runez.represented_json({None: None}, none=True) == '{\n  "null": null\n}\n'
    assert runez.represented_json({None: 1, "foo": None}, none="_null") == '{\n  "_null": 1,\n  "foo": null\n}\n'

    with pytest.raises(TypeError):
        # py3 stdlib can't sort with None key...
        runez.represented_json({None: 2, "foo": "bar"}, none=True)

    data = {"a": "x", "b": "y"}
    assert runez.represented_json(data) == '{\n  "a": "x",\n  "b": "y"\n}\n'
    assert runez.represented_json(data, indent=None) == '{"a": "x", "b": "y"}'

    assert runez.save_json(None, None, fatal=False) == 0

    assert not runez.DRYRUN
    with runez.CaptureOutput(dryrun=True) as logged:
        assert runez.save_json(data, "sample.json") == 1
        assert "Would save" in logged.pop()
    assert not runez.DRYRUN

    with runez.CaptureOutput() as logged:
        with pytest.raises(runez.system.AbortException) as exc:
            runez.read_json(None, fatal=True)
        assert "Can't read None" in str(exc)
        assert "Can't read None" in logged.pop()

        assert runez.read_json("sample.json") is None
        assert not logged

        assert runez.read_json("sample.json", default={}, logger=None) == {}
        assert not logged

        with monkeypatch.context() as m:
            m.setattr(runez.serialize, "open", runez.conftest.exception_raiser(), raising=False)
            assert runez.save_json(data, "sample.json", fatal=False) == -1
            assert "Can't save" in logged.pop()

        assert runez.save_json(data, "sample.json", logger=logging.debug) == 1
        assert "Saved " in logged.pop()

        with monkeypatch.context() as m:
            m.setattr(io, "open", runez.conftest.exception_raiser())
            with pytest.raises(runez.system.AbortException) as exc:
                runez.read_json("sample.json", fatal=True, logger=None)
            assert "Can't read sample.json" in str(exc)

            assert runez.read_json("sample.json") is None
            assert not logged
Beispiel #4
0
 def _refresh_frozen(self):
     output = self._run_pip("freeze", fatal=False)
     versions = {}
     if output:
         for line in output.split("\n"):
             name, version = system.despecced(line)
             versions[name] = version
     if versions:
         runez.save_json(versions, self.frozen_path)
     return versions
Beispiel #5
0
 def save_manifest(self, entry_points):
     manifest = TrackedManifest(
         self.manifest_path,
         self.settings,
         entry_points,
         pinned=self.pinned,
         version=self.version,
     )
     payload = manifest.to_dict()
     runez.save_json(payload, self.manifest_path)
     runez.save_json(payload,
                     os.path.join(self.install_path, ".manifest.json"))
     return manifest
Beispiel #6
0
    def _refresh_frozen(self):
        result = self._run_builtin_module("pip",
                                          "freeze",
                                          "--all",
                                          fatal=False)
        self._frozen = {}
        if result.output:
            for line in result.output.split("\n"):
                name, version = system.despecced(line)
                self._frozen[name] = version

        if self._frozen:
            runez.save_json(self._frozen, self.frozen_path)
Beispiel #7
0
    def get_latest(self, force=False):
        """Tracked in DOT_META/.cache/<package>.latest"""
        path = self.cfg.cache.full_path("%s.latest" % self.dashed)
        age = self.cfg.version_check_delay(self)
        if not force and age and runez.file.is_younger(path, age):
            latest = TrackedVersion.from_file(path)
            if latest:
                return latest

        latest = TrackedVersion.from_pypi(self)
        if not latest.problem:
            runez.save_json(latest.to_dict(), path, fatal=None)

        return latest
Beispiel #8
0
def test_json(temp_folder):
    assert runez.read_json(None, fatal=False) is None
    assert runez.save_json(None, None, fatal=False) == 0

    data = {"a": "b"}

    assert not runez.DRYRUN
    with runez.CaptureOutput(dryrun=True) as logged:
        assert runez.save_json(data, "sample.json") == 1
        assert "Would save" in logged.pop()
    assert not runez.DRYRUN

    with runez.CaptureOutput() as logged:
        assert runez.read_json("sample.json", fatal=False) is None
        assert "No file" in logged.pop()

        assert runez.read_json("sample.json", default={}, fatal=False) == {}
        assert not logged

        with patch("runez.serialize.open", side_effect=Exception):
            assert runez.save_json(data, "sample.json", fatal=False) == -1
            assert "Couldn't save" in logged.pop()

        assert runez.save_json(data, "sample.json", logger=logging.debug) == 1
        assert "Saved " in logged.pop()

        with patch("io.open", side_effect=Exception):
            assert runez.read_json("sample.json", fatal=False) is None
            assert "Couldn't read" in logged.pop()

        assert runez.read_json("sample.json", logger=logging.debug) == data
        assert "Read " in logged.pop()

        assert runez.read_json("sample.json", default=[], fatal=False) == []
        assert "Wrong type" in logged.pop()

    with runez.CaptureOutput() as logged:
        # Try with an object that isn't directly serializable, but has a to_dict() function
        obj = SomeRecord()
        obj.to_dict = lambda *_: data

        assert runez.save_json(obj, "sample2.json", logger=logging.debug) == 1
        assert "Saved " in logged.pop()

        assert runez.read_json("sample2.json", logger=logging.debug) == data
        assert "Read " in logged.pop()
Beispiel #9
0
    def internal_install(self, force=False, verbose=True):
        """
        :param bool force: If True, re-install even if package is already installed
        :param bool verbose: If True, show more extensive info
        """
        with SoftLock(self.dist_folder,
                      timeout=system.SETTINGS.install_timeout):
            self.refresh_desired(force=force)
            self.version = self.desired.version
            if not self.desired.valid:
                return runez.abort("Can't install %s: %s", self.name,
                                   self.desired.problem)

            if not force and self.current.equivalent(self.desired):
                system.inform(
                    self.desired.representation(verbose=verbose,
                                                note="is already installed"))
                self.cleanup()
                return

            prev_entry_points = self.entry_points
            self.effective_install()

            new_entry_points = self.entry_points
            removed = set(prev_entry_points).difference(new_entry_points)
            if removed:
                old_removed = runez.read_json(self.removed_entry_points_path,
                                              default=[],
                                              fatal=False)
                removed = sorted(removed.union(old_removed))
                runez.save_json(removed,
                                self.removed_entry_points_path,
                                fatal=False)

            # Delete wrapper/symlinks of removed entry points immediately
            for name in removed:
                runez.delete(system.SETTINGS.base.full_path(name))

            self.cleanup()

            self.current.set_from(self.desired)
            self.current.save(fatal=False)

            msg = "Would install" if runez.DRYRUN else "Installed"
            system.inform("%s %s" %
                          (msg, self.desired.representation(verbose=verbose)))
Beispiel #10
0
    def refresh(self, *kinds, **kwargs):
        """
        Args:
            kinds: Kinds to replay (json and/or token)
        """
        existing = kwargs.pop("existing", False)
        if not kinds:
            kinds = (TestSamples.K_DESERIALIZED, TestSamples.K_TOKEN)

        for kind in kinds:
            if existing:
                expected = self.expected_content(kind)
                if expected is runez.UNSET:
                    continue

            actual = self.deserialized(kind)
            path = self.expected_path(kind)
            runez.save_json(actual, path, keep_none=True, logger=logging.info)
Beispiel #11
0
def test_install_pypi(cli):
    cli.expect_failure("--color install six", "it is not a CLI")
    assert not os.path.exists(dot_meta("six"))

    cli.expect_failure("install mgit+foo", "not a valid pypi package name")

    runez.touch(
        dot_meta("mgit/.foo"))  # Should stay because name starts with '.'
    runez.touch(dot_meta("mgit/mgit-foo"))  # Bogus installation
    runez.touch(dot_meta("mgit/mgit-0.0.1/foo"))  # Oldest should be deleted

    # Simulate the presence of an old entry point
    manifest_path = dot_meta("mgit/.manifest.json")
    runez.save_json(dict(entrypoints=["mgit", "old-mgit-entrypoint"]),
                    manifest_path)
    runez.touch("old-mgit-entrypoint")
    assert os.path.exists("old-mgit-entrypoint")

    time.sleep(0.01)  # Ensure 0.0.1 is older than 0.0.2
    runez.touch(
        dot_meta("mgit/mgit-0.0.2/foo"))  # Youngest should remain for an hour
    check_install_from_pypi(cli, "symlink", "mgit")
    assert not os.path.exists("old-mgit-entrypoint")
    assert os.path.islink("mgit")
    assert os.path.exists(dot_meta("mgit/.manifest.json"))
    assert os.path.exists(dot_meta("mgit/.foo"))
    assert os.path.exists(dot_meta("mgit/mgit-0.0.2"))
    assert not os.path.exists(dot_meta("mgit/mgit-foo"))
    assert not os.path.exists(dot_meta("mgit/mgit-0.0.1"))

    cfg = PickleyConfig()
    cfg.set_base(".")
    pspec = PackageSpec(cfg, "mgit")
    pspec.groom_installation(keep_for=0)
    assert not os.path.exists(dot_meta("mgit/mgit-0.0.2"))

    cli.expect_success("uninstall mgit", "Uninstalled mgit")
    assert not runez.is_executable("mgit")
    assert not os.path.exists(dot_meta("mgit"))
    assert os.path.exists(dot_meta("audit.log"))

    check_install_from_pypi(cli, "wrap", "mgit", simulate_version="0.0.0")
    check_is_wrapper("mgit", True)
Beispiel #12
0
def test_to_dict(temp_folder):
    with runez.CaptureOutput() as logged:
        # Try with an object that isn't directly serializable, but has a to_dict() function
        data = {"a": "b"}
        obj = SomeRecord()
        obj.to_dict = lambda *_: data

        assert runez.save_json(obj, "sample2.json", logger=logging.debug) == 1
        assert "Saved " in logged.pop()
        assert runez.read_json("sample2.json") == data
        assert not logged
Beispiel #13
0
def test_facultative(cli):
    runez.save_json({"pinned": {
        "virtualenv": {
            "facultative": True
        }
    }}, dot_meta("config.json"))

    # Empty file -> proceed with install as if it wasn't there
    runez.touch("virtualenv")
    cli.expect_success("-n install virtualenv",
                       "Would state: Installed virtualenv")

    # Simulate pickley wrapper
    runez.write("virtualenv", "echo installed by pickley")
    runez.make_executable("virtualenv")
    cli.expect_success("-n install virtualenv",
                       "Would state: Installed virtualenv")

    # Unknown executable -> skip pickley installation (since facultative)
    runez.write("virtualenv", "echo foo")
    runez.make_executable("virtualenv")
    cli.expect_success(
        "-n install virtualenv",
        "Skipping installation of virtualenv: not installed by pickley")
    cli.expect_success("-n check virtualenv",
                       "skipped, not installed by pickley")

    # --force ignores 'facultative' setting
    cli.expect_failure("-n install --force virtualenv",
                       "Can't automatically uninstall virtualenv")

    # Simulate pickley symlink delivery
    dummy_target = dot_meta("foo")
    runez.touch(dummy_target)
    runez.symlink(dummy_target, "virtualenv")
    cli.expect_success("-n install virtualenv",
                       "Would state: Installed virtualenv")
Beispiel #14
0
 def save(self):
     runez.save_json(self.to_dict(), self._path, fatal=False)
Beispiel #15
0
def test_install(cli):
    cli.expect_success("--dryrun --delivery wrap install tox", "Would wrap",
                       "Would install tox")
    cli.expect_success("--dryrun --delivery symlink install tox",
                       "Would symlink", "Would install tox")
    assert not os.path.exists(".pickley/audit.log")

    cli.expect_failure("check tox", "is not installed")
    cli.expect_failure("install six", "'six' is not a CLI")

    # Install tox, but add a few files + a bogus previous entry point to test cleanup
    runez.write(".pickley/tox/.entry-points.json",
                '["tox-old1", "tox-old2"]\n')
    runez.touch("tox-old1")
    runez.touch(".pickley/tox/tox-0.1/bin")
    runez.touch(".pickley/tox/tox-0.2/bin")
    runez.touch(".pickley/tox/tox-0.3/bin")
    runez.touch(".pickley/tox/tox-old1-0.1")
    runez.touch(".pickley/tox/tox-old1-0.2")
    cli.expect_success("--delivery wrap install tox", "Installed tox")

    # Old entry point removed immediately
    assert not os.path.exists("tox-old1")

    # Only 1 cleaned up immediately (latest + 1 kept)
    assert not os.path.exists(".pickley/tox/tox-0.1")
    assert not os.path.exists(".pickley/tox/tox-0.2")
    assert os.path.exists(".pickley/tox/tox-0.3")
    assert not os.path.exists(".pickley/tox/tox-old1-0.1")
    assert os.path.exists(".pickley/tox/tox-old1-0.2")

    assert runez.is_executable("tox")
    result = run_program("tox", "--version")
    assert "tox" in result.output

    cli.expect_success("auto-upgrade tox", "Skipping auto-upgrade")
    runez.delete(system.SETTINGS.meta.full_path("tox", ".ping"))
    cli.expect_success("auto-upgrade tox", "already installed")

    cli.expect_success("copy .pickley/tox tox-copy", "Copied")
    cli.expect_success("move tox-copy tox-relocated", "Moved")
    runez.delete("tox-relocated")

    # Verify that older versions and removed entry-points do get cleaned up
    runez.save_json({"install_timeout": 0}, "custom-timeout.json")
    cli.expect_success("-ccustom-timeout.json install tox",
                       "already installed")

    # All cleaned up when enough time went by
    assert not os.path.exists(".pickley/tox/tox-0.3")
    assert not os.path.exists(".pickley/tox/tox-old1-0.2")

    cli.expect_success("check", "tox", "is installed")
    cli.expect_success(
        "check --verbose", "tox",
        "is installed (as %s wrap, channel: " % system.VENV_PACKAGER)

    # Simulate new version available
    latest = runez.read_json(".pickley/tox/.latest.json")
    latest["version"] = "10000.0"
    runez.save_json(latest, ".pickley/tox/.latest.json")
    cli.expect_failure("check", "tox", "can be upgraded to 10000.0")

    # Latest twine 2.0 requires py3
    cli.expect_success("-ppex install twine==1.14.0", "Installed twine")

    cli.expect_success("list", "tox", "twine")
    cli.expect_success("list --verbose", "tox", "twine")

    assert find_uninstaller("tox")
    assert find_uninstaller("twine")

    cli.expect_success("uninstall twine", "Uninstalled twine")

    runez.write(".pickley/tox/.current.json", "")
    cli.expect_failure("check", "tox", "Couldn't read", "is not installed")

    cli.expect_success("uninstall --all", "Uninstalled tox", "entry points")
    assert not os.path.exists("tox")
    assert not os.path.exists(".pickley")
Beispiel #16
0
def test_install(cli):
    tox = system.SETTINGS.base.full_path("tox")
    p = PACKAGERS.resolved("tox")
    p.refresh_desired()
    tox_version = p.desired.version
    assert not os.path.exists(tox)
    assert runez.first_line(tox) is None

    cli.expect_success("--dryrun -b{base} --delivery wrap install tox",
                       "Would wrap",
                       "Would install tox",
                       base=cli.context)
    cli.expect_success("--dryrun -b{base} --delivery symlink install tox",
                       "Would symlink",
                       "Would install tox",
                       base=cli.context)
    cli.expect_failure("--dryrun -b{base} --delivery foo install tox",
                       "invalid choice: foo",
                       base=cli.context)

    cli.expect_success("--dryrun uninstall /dev/null --force",
                       "Nothing to uninstall")

    runez.touch("foo")
    assert os.path.exists("foo")
    cli.expect_failure("uninstall foo", "foo was not installed with pickley")
    cli.expect_success("uninstall foo --force", "Uninstalled foo")

    assert not os.path.exists("foo")
    assert runez.ensure_folder("foo", folder=True) == 1
    cli.expect_failure("uninstall foo --force",
                       "Can't automatically uninstall")

    cli.expect_failure("-b{base} check tox foo/bar",
                       "is not installed",
                       "can't determine latest version",
                       base=cli.context)
    cli.expect_failure("-b{base} install six",
                       "'six' is not a CLI",
                       base=cli.context)

    # Install tox, but add a few files + a bogus previous entry point to test cleanup
    wep1 = system.SETTINGS.base.full_path("tox-old-entrypoint1")
    tep10 = system.SETTINGS.meta.full_path("tox", "tox-old-entrypoint1-1.0")
    tep11 = system.SETTINGS.meta.full_path("tox", "tox-old-entrypoint1-1.1")
    t00 = system.SETTINGS.meta.full_path("tox", "tox-0.0.0")
    tfoo = system.SETTINGS.meta.full_path("tox", "tox-foo")
    runez.touch(wep1)
    runez.touch(tep10)
    runez.touch(tep11)
    runez.touch(t00)
    runez.touch(tfoo)
    eppath = system.SETTINGS.meta.full_path("tox", ".entry-points.json")
    runez.write(eppath, '["tox-old-entrypoint1", "tox-old-entrypoint2"]\n')
    cli.expect_success("-b{base} --delivery wrap install tox",
                       "Installed tox",
                       base=cli.context)

    # Old entry point removed immediately
    assert not os.path.exists(wep1)

    # Only 1 cleaned up immediately (latest + 1 kept)
    assert not os.path.exists(tep10)
    assert os.path.exists(tep11)
    assert not os.path.exists(t00)
    assert os.path.exists(tfoo)

    assert runez.is_executable(tox)
    output = run_program(tox, "--version")
    assert "tox" in output
    assert tox_version in output

    cli.expect_success("-b{base} auto-upgrade tox",
                       "Skipping auto-upgrade",
                       base=cli.context)
    runez.delete(system.SETTINGS.meta.full_path("tox", ".ping"))
    cli.expect_success("-b{base} auto-upgrade tox",
                       "already installed",
                       base=cli.context)

    version = output.partition(" ")[0]
    cli.expect_success("copy .pickley/tox/tox-%s tox-copy" % version, "Copied")
    cli.expect_success("move tox-copy tox-relocated", "Moved")

    # Verify that older versions and removed entry-points do get cleaned up
    runez.save_json({"install_timeout": 0}, "custom-timeout.json")
    cli.expect_success("-b{base} -ccustom-timeout.json install tox",
                       "already installed",
                       base=cli.context)

    # All cleaned up when enough time went by
    assert not os.path.exists(tep10)
    assert not os.path.exists(tep11)
    assert not os.path.exists(t00)
    assert not os.path.exists(tfoo)

    cli.expect_success("-b{base} check",
                       "tox",
                       "is installed",
                       base=cli.context)
    cli.expect_success(
        "-b{base} check --verbose",
        "tox",
        "is installed (as %s wrap, channel: " % system.VENV_PACKAGER,
        base=cli.context,
    )

    p = PACKAGERS.get(system.VENV_PACKAGER)("tox")
    p.refresh_latest()
    p.latest.version = "10000.0"
    p.latest.save()
    cli.expect_failure("-b{base} check",
                       "tox",
                       "can be upgraded to 10000.0",
                       base=cli.context)

    cli.expect_success("-b{base} -ppex install twine",
                       "Installed twine",
                       base=cli.context)

    cli.expect_success("-b{base} list", "tox", "twine", base=cli.context)
    cli.expect_success("-b{base} list --verbose",
                       "tox",
                       "twine",
                       base=cli.context)

    tmp = os.path.realpath(cli.context)
    assert find_uninstaller(os.path.join(tmp, "tox"))
    assert find_uninstaller(os.path.join(tmp, "twine"))

    cli.expect_success("-b{base} uninstall twine",
                       "Uninstalled twine",
                       base=cli.context)

    runez.delete(p.current._path)
    runez.touch(p.current._path)
    cli.expect_failure("-b{base} check",
                       "tox",
                       "Couldn't read",
                       "is not installed",
                       base=cli.context)

    cli.expect_success("-b{base} uninstall tox",
                       "Uninstalled tox",
                       "entry points",
                       base=cli.context)