Ejemplo n.º 1
0
    def entry_points(self):
        metadata_json = self.dist_info.files.get("metadata.json")
        if metadata_json:
            metadata = runez.read_json(metadata_json, default={})
            extensions = metadata.get("extensions")
            if isinstance(extensions, dict):
                commands = extensions.get("python.commands")
                if isinstance(commands, dict):
                    wrap_console = commands.get("wrap_console")
                    if wrap_console:
                        runez.log.trace("Found %s entry points in metadata.json" % len(wrap_console))
                        return wrap_console

        entry_points_txt = self.dist_info.files.get("entry_points.txt")
        if entry_points_txt:
            metadata = runez.file.ini_to_dict(entry_points_txt)
            console_scripts = metadata.get("console_scripts")
            if console_scripts:
                runez.log.trace("Found %s entry points in entry_points.txt" % len(console_scripts))
                return console_scripts

        if self.bin.files:
            runez.log.trace("Found %s bin/ scripts" % len(self.bin.files))

        return self.bin.files or None
Ejemplo n.º 2
0
def test_pathlib(temp_folder):
    subfolder = Path("subfolder")
    assert runez.to_path(subfolder) is subfolder
    assert not subfolder.is_dir()
    runez.ensure_folder(subfolder)
    assert subfolder.is_dir()

    with pytest.raises(Exception):
        runez.to_path("foo bar", no_spaces=Exception)

    with runez.CurrentFolder(subfolder, anchor=True):
        path = Path("foo")
        assert runez.short(path) == "foo"
        assert runez.short(path.absolute()) == "foo"

        assert runez.resolved_path(path)
        assert runez.parent_folder(path) == os.path.join(temp_folder, "subfolder")
        assert runez.touch(path) == 1
        assert runez.copy(path, Path("bar")) == 1
        assert runez.copy(Path("bar"), Path("baz")) == 1

        foo_json = Path("foo.json")
        runez.write(path, '{"a": "b"}')
        runez.symlink(path, foo_json)
        assert runez.read_json(foo_json) == {"a": "b"}
        assert list(runez.readlines(foo_json)) == ['{"a": "b"}']

        assert runez.basename(foo_json.absolute()) == "foo"
Ejemplo n.º 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
Ejemplo n.º 4
0
 def contents(self):
     """
     :return dict: Deserialized contents of settings file
     """
     if self._contents is None:
         self.set_contents(
             runez.read_json(self.path, default={}, fatal=False))
     return self._contents
Ejemplo n.º 5
0
 def from_file(cls, path):
     data = runez.read_json(path)
     if data:
         return cls(
             index=data.get("index"),
             install_info=TrackedInstallInfo.from_manifest_data(data),
             problem=data.get("problem"),
             source=data.get("source"),
             version=data.get("version"),
         )
Ejemplo n.º 6
0
    def cleanup(self):
        """Cleanup older installs"""
        cutoff = time.time() - system.SETTINGS.install_timeout * 60
        folder = system.SETTINGS.meta.full_path(self.name)

        removed_entry_points = runez.read_json(self.removed_entry_points_path,
                                               default=[],
                                               fatal=False)

        prefixes = {None: [], self.name: []}
        for name in self.entry_points:
            prefixes[name] = []
        for name in removed_entry_points:
            prefixes[name] = []

        if os.path.isdir(folder):
            for name in os.listdir(folder):
                if name.startswith("."):
                    continue
                target = find_prefix(prefixes, name)
                if target in prefixes:
                    fpath = os.path.join(folder, name)
                    prefixes[target].append((os.path.getmtime(fpath), fpath))

        # Sort each by last modified timestamp
        for target, cleanable in prefixes.items():
            prefixes[target] = sorted(cleanable, reverse=True)

        rem_cleaned = 0
        for target, cleanable in prefixes.items():
            if not cleanable:
                if target in removed_entry_points:
                    # No cleanable found for a removed entry-point -> count as cleaned
                    rem_cleaned += 1
                continue

            if target not in removed_entry_points:
                if cleanable[0][0] <= cutoff:
                    # Latest is old enough now, cleanup all except latest
                    cleanable = cleanable[1:]
                else:
                    # Latest is too young, keep the last 2
                    cleanable = cleanable[2:]
            elif cleanable[0][0] <= cutoff:
                # Delete all removed entry points when old enough
                rem_cleaned += 1
            else:
                # Removed entry point still too young, keep latest
                cleanable = cleanable[1:]

            for _, path in cleanable:
                runez.delete(path)

        if rem_cleaned >= len(removed_entry_points):
            runez.delete(self.removed_entry_points_path)
Ejemplo n.º 7
0
 def from_file(cls, path):
     data = runez.read_json(path)
     if data:
         return cls(
             path,
             TrackedSettings.from_manifest_data(data),
             data.get("entrypoints"),
             install_info=TrackedInstallInfo.from_manifest_data(data),
             pinned=data.get("pinned"),
             version=data.get("version"),
         )
Ejemplo n.º 8
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
Ejemplo n.º 9
0
 def _add_config_file(self, path, base=None):
     path = runez.resolved_path(path, base=base)
     if path and all(c.source != path
                     for c in self.configs) and os.path.exists(path):
         values = runez.read_json(path, logger=LOG.warning)
         if values:
             self.configs.append(RawConfig(self, path, values))
             included = values.get("include")
             if included:
                 for additional in runez.flattened(included):
                     self._add_config_file(additional,
                                           base=os.path.dirname(path))
Ejemplo n.º 10
0
    def expected_content(self, kind):
        path = self.expected_path(kind)
        content = self._expected.get(kind)
        if content is not None:
            return content

        content = runez.UNSET
        if os.path.exists(path):
            content = runez.read_json(path)

        self._expected[kind] = content
        return content
Ejemplo n.º 11
0
 def entry_points(self):
     """
     :return dict: Determined entry points from produced wheel, if available
     """
     if self._entry_points is None:
         self._entry_points = runez.read_json(self.entry_points_path, fatal=None, default=None)
         if isinstance(self._entry_points, list):
             # For backwards compatibility with pickley <= v1.4.2
             self._entry_points = dict((k, "") for k in self._entry_points)
         if self._entry_points is None:
             return {self.package_spec.dashed: ""} if runez.DRYRUN else {}
     return self._entry_points
Ejemplo n.º 12
0
def test_with_tty(monkeypatch, logged):
    with patch("runez.prompt.input", side_effect=mocked_input):
        monkeypatch.setattr(runez.SYS_INFO.terminal, "is_stdout_tty", True)
        expected = {"value": "foo"}
        with runez.TempFolder() as tmp:
            assert ask_once("test",
                            "foo",
                            base=tmp,
                            serializer=custom_serializer) == expected

            assert runez.read_json("test.json", logger=None) == expected
            assert ask_once(
                "test", "bar",
                base=tmp) == expected  # Ask a 2nd time, same response

            # Verify that if `serializer` returns None, value is not returned/stored
            with pytest.raises(Exception) as exc:
                ask_once("test-invalid",
                         "invalid",
                         base=tmp,
                         serializer=custom_serializer,
                         fatal=True,
                         logger=None)
            assert "Invalid value provided for test-invalid" in str(exc)
            assert not os.path.exists("test-invalid.json")

            # Same, but don't raise exception (returns default)
            assert ask_once("test-invalid",
                            "invalid",
                            base=tmp,
                            serializer=custom_serializer) is None
            assert not logged  # Traced by default

            # Simulate no value provided
            with pytest.raises(Exception) as exc:
                ask_once("test-invalid",
                         "",
                         base=tmp,
                         serializer=custom_serializer,
                         fatal=True)
            assert "No value provided" in str(exc)
            assert "No value provided" in logged.pop()  # Logged if fatal=True

    with patch("runez.prompt.input", side_effect=KeyboardInterrupt):
        # Simulate CTRL+C
        with pytest.raises(Exception) as exc:
            ask_once("test2",
                     "test2",
                     base=tmp,
                     serializer=custom_serializer,
                     fatal=True)
        assert "Cancelled by user" in str(exc)
Ejemplo n.º 13
0
 def load(self):
     path = self._path
     old_path = None
     if path is None and self._suffix == "current":  # pragma: no cover
         if self._package_spec.multi_named and not os.path.exists(self._path):
             # Temporary fix: pickley <v1.8 didn't standardize on dashed package name
             p = system.SETTINGS.meta.full_path(self._package_spec.pythonified, ".%s.json" % self._suffix)
             if os.path.exists(p):
                 path = p
                 old_path = self._path
     data = runez.read_json(path, default={}, fatal=False)
     self.set_from_dict(data, source=runez.short(path))
     if old_path:  # pragma: no cover
         self._path = old_path
Ejemplo n.º 14
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)))
Ejemplo n.º 15
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()
Ejemplo n.º 16
0
 def frozen(self):
     if self._frozen is None:
         self._frozen = runez.read_json(self.frozen_path, default={})
     return self._frozen or {}
Ejemplo n.º 17
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")