コード例 #1
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"
コード例 #2
0
ファイル: cli.py プロジェクト: codrsquad/pickley
    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
コード例 #3
0
def mk_python(basename,
              prefix=None,
              base_prefix=None,
              executable=True,
              content=None,
              folder=None,
              version=None):
    if version is None:
        m = RE_VERSION.match(basename)
        if m:
            if not folder:
                folder = os.path.join(".pyenv/versions", basename)

            version = m.group(2)
            basename = "python"

    if not folder:
        folder = ".pyenv/versions"

    path = runez.resolved_path(folder)
    if not prefix:
        prefix = path

    if not base_prefix:
        base_prefix = prefix

    path = os.path.join(path, "bin", basename)
    if not content:
        content = [version, prefix, base_prefix]

    content = "#!/bin/bash\n%s\n" % "\n".join("echo %s" % s for s in content)
    runez.write(path, content, logger=None)
    if executable:
        runez.make_executable(path, logger=None)
コード例 #4
0
def mock_git_clone(pspec):
    basename = runez.basename(pspec.original)
    pspec.folder = pspec.cfg.cache.full_path("checkout", basename)
    setup_py = os.path.join(pspec.folder, "setup.py")
    runez.write(
        setup_py,
        "from setuptools import setup\nsetup(name='%s', version='1.0')\n" %
        basename,
        dryrun=False)
コード例 #5
0
def test_default_index(temp_folder, logged):
    assert get_default_index() == (None, None)

    # Verify that we try 'a' (no such file), then find a configured index in 'b'
    runez.write("b",
                "[global]\nindex-url = https://example.com/pypi",
                logger=False)
    assert get_default_index("a", "b") == ("b", "https://example.com/pypi")

    # Not logging, since default is pypi, and which index is used can be configured and seen via diagnostics command
    assert not logged
コード例 #6
0
ファイル: test_delivery.py プロジェクト: codrsquad/pickley
 def __init__(self, cfg, name, version):
     self.cfg = cfg
     self.name = name
     self.version = version
     self.entry_points = {name: name}
     self.pspec = PackageSpec(cfg, name, version=version)
     self.pspec.save_manifest(self.entry_points)
     self.venv = PythonVenv(self.pspec, create=False)
     self.venv_exe = os.path.join(self.pspec.install_path, "bin", name)
     runez.write(self.venv_exe, "#!/bin/bash\necho %s" % version)
     runez.make_executable(self.venv_exe)
コード例 #7
0
 def _install(self, target, source):
     wrapper = PICKLEY_WRAPPER if self.package_name == system.PICKLEY else GENERIC_WRAPPER
     contents = wrapper.lstrip().format(
         hook=self.hook,
         bg=self.bg,
         name=runez.quoted(self.package_name),
         pickley=runez.quoted(system.SETTINGS.base.full_path(
             system.PICKLEY)),
         source=runez.quoted(source),
     )
     runez.write(target, contents)
     runez.make_executable(target)
コード例 #8
0
def test_file_operations(temp_folder):
    runez.symlink("foo", "dangling-symlink", must_exist=False)
    runez.move("dangling-symlink", "dangling-symlink2")
    assert os.path.islink("dangling-symlink2")

    runez.write("README.md", "hello")
    runez.copy("README.md", "sample1/README.md")
    runez.copy("sample1", "sample2")
    runez.move("sample1/README.md", "sample1/foo")

    # overwrite=None "merges" dir contents
    runez.copy("sample1", "sample2", overwrite=None)
    assert dir_contents("sample2") == {"README.md": ["hello"], "foo": ["hello"]}

    # overwrite=True replaces dir
    runez.copy("sample1", "sample2", overwrite=True)
    assert dir_contents("sample2") == {"foo": ["hello"]}

    # overwrite=None, source is a dir, existing destination file gets replaced by source directory
    runez.copy("sample1", "sample2/foo", overwrite=None)
    assert dir_contents("sample2") == {"foo": {"foo": ["hello"]}}

    with runez.CaptureOutput(dryrun=True) as logged:
        assert runez.ensure_folder("some-folder", fatal=False) == 1
        assert "Would create" in logged.pop()

        assert runez.touch("some-file", logger=logging.debug) == 1
        assert "Would touch some-file" in logged.pop()

        assert runez.copy("some-file", "bar") == 1
        assert "Would copy some-file -> bar" in logged.pop()

        assert runez.move("some-file", "bar") == 1
        assert "Would move some-file -> bar" in logged.pop()

        assert runez.symlink("some-file", "bar") == 1
        assert "Would symlink some-file <- bar" in logged.pop()

        assert runez.delete(temp_folder) == 1
        assert "Would delete" in logged.pop()

        assert runez.copy("some-folder/bar", "some-folder", fatal=False) == -1
        assert "source contained in destination" in logged.pop()

        assert runez.move("some-folder/bar/baz", "some-folder", fatal=False) == -1
        assert "source contained in destination" in logged.pop()

        assert runez.symlink("some-folder/bar/baz", "some-folder", fatal=False) == -1
        assert "source contained in destination" in logged.pop()
コード例 #9
0
    def __enter__(self):
        """
        Acquire lock
        """
        cutoff = time.time() + self.timeout
        while self._locked():
            if time.time() >= cutoff:
                raise SoftLockException(self.folder)
            time.sleep(1)

        # We got the soft lock
        runez.write(self.lock, "%s\n" % os.getpid())

        if not self._should_keep():
            runez.delete(self.folder, logger=LOG.debug if self.keep else None)

        return self
コード例 #10
0
ファイル: test_delivery.py プロジェクト: reallistic/pickley
def test_wrapper(temp_base):
    repeater = os.path.join(temp_base, "repeat.sh")
    target = os.path.join(temp_base, system.PICKLEY)

    runez.write(repeater, "#!/bin/bash\n\necho :: $*\n")
    runez.make_executable(repeater)

    # Actual wrapper
    d = DeliveryMethodWrap(system.PackageSpec(system.PICKLEY))
    d.install(target, repeater)
    assert runez.run(target, "auto-upgrade",
                     "foo") == RunResult(":: auto-upgrade foo", "", 0)
    assert runez.run(target, "--debug", "auto-upgrade",
                     "foo") == RunResult(":: --debug auto-upgrade foo", "", 0)
    assert runez.run(target, "settings",
                     "-d") == RunResult(":: settings -d", "", 0)

    # Verify that we're triggering background auto-upgrade as expected
    d.hook = "echo "
    d.bg = ""
    d.install(target, repeater)

    result = runez.run(target, "settings", "-d")
    assert "nohup" in result.output
    assert "repeat.sh settings -d" in result.output

    result = runez.run(target, "auto-upgrade", "foo")
    assert "nohup" not in result.output
    assert "repeat.sh auto-upgrade foo" in result.output

    result = runez.run(target, "--debug", "auto-upgrade", "foo")
    assert "nohup" not in result.output
    assert "repeat.sh --debug auto-upgrade foo" in result.output

    runez.delete(repeater)
    result = runez.run(target, "foo", fatal=False)
    assert result.failed
    assert "Please reinstall with" in result.full_output

    assert os.path.exists(target)
    assert uninstall_existing(target, fatal=False) == 1
    assert not os.path.exists(target)
コード例 #11
0
    def _install(self, pspec, target, source):
        pickley = pspec.cfg.base.full_path(PICKLEY)
        if pspec.dashed == PICKLEY:
            wrapper = PICKLEY_WRAPPER

        else:
            wrapper = GENERIC_WRAPPER
            if runez.DEV.project_folder and not os.path.exists(pickley):
                # We're running from development venv
                pickley = pspec.cfg.program_path

        contents = wrapper.lstrip().format(
            hook=self.hook,
            bg=self.bg,
            name=runez.quoted(pspec.dashed, adapter=None),
            pickley=runez.quoted(pickley, adapter=None),
            source=runez.quoted(source, adapter=None),
        )
        runez.delete(target, logger=False)
        runez.write(target, contents, logger=False)
        runez.make_executable(target, logger=False)
コード例 #12
0
ファイル: test_logsetup.py プロジェクト: codrsquad/runez
def test_convenience(temp_log):
    fmt = "f:%(filename)s mod:%(module)s func:%(funcName)s %(levelname)s %(message)s "
    fmt += " path:%(pathname)s"
    runez.log.setup(console_format=fmt, console_level=logging.DEBUG, file_format=None)

    assert temp_log.logfile is None
    runez.write("some-file", "some content", logger=logging.info)
    logging.info("hello")
    logging.exception("oops")

    assert "f:system.py mod:system func:hlog INFO Wrote 12 bytes" in temp_log.stderr
    assert "f:test_logsetup.py mod:test_logsetup func:test_convenience INFO hello" in temp_log.stderr
    assert "f:test_logsetup.py mod:test_logsetup func:test_convenience ERROR oops" in temp_log.stderr
    temp_log.stderr.clear()

    runez.write("some-file", "some content", logger=LOG.info)
    LOG.info("hello")
    LOG.exception("oops")
    assert "f:system.py mod:system func:hlog INFO Wrote 12 bytes" in temp_log.stderr
    assert "f:test_logsetup.py mod:test_logsetup func:test_convenience INFO hello" in temp_log.stderr
    assert "f:test_logsetup.py mod:test_logsetup func:test_convenience ERROR oops" in temp_log.stderr
コード例 #13
0
def test_capture(temp_folder, logged):
    chatter = runez.resolved_path("chatter")
    assert runez.write(chatter, CHATTER.strip(), fatal=False) == 1
    assert runez.make_executable(chatter, fatal=False) == 1

    assert runez.run(chatter, fatal=False) == "chatter"

    r = runez.run(chatter, include_error=True, fatal=False)
    assert r.startswith("chatter")
    assert "No such file" in r

    assert "Running: chatter" in logged
コード例 #14
0
def textual_diff(kind, actual, expected):
    actual_error = isinstance(actual, dict) and actual.get("_error") or None
    expected_error = isinstance(expected,
                                dict) and expected.get("_error") or None
    if actual_error != expected_error:
        if actual_error:
            return diff_overview(kind, actual_error, expected_error,
                                 "deserialization failed")

        return diff_overview(kind, actual_error, expected_error,
                             "deserialization did NOT yield expected error")

    if type(actual) != type(expected):
        return diff_overview(kind, type(actual), type(expected),
                             "differing types")

    if kind == TestSamples.K_TOKEN:
        actual = "%s\n" % "\n".join(actual)
        expected = "%s\n" % "\n".join(expected)

    else:
        actual = runez.represented_json(actual,
                                        keep_none=True,
                                        none_key="-null-")
        expected = runez.represented_json(expected,
                                          keep_none=True,
                                          none_key="-null-")

    if actual != expected:
        with runez.TempFolder(dryrun=False):
            runez.write("actual", actual)
            runez.write("expected", expected)
            r = runez.run("diff",
                          "-br",
                          "-U1",
                          "expected",
                          "actual",
                          fatal=None,
                          dryrun=False)
            return formatted_diff(r.full_output)
コード例 #15
0
def test_entry_points(temp_cfg):
    venv = PythonVenv(folder="", cfg=temp_cfg)
    with runez.CaptureOutput(dryrun=True):
        pspec = PackageSpec(temp_cfg, "mgit")
        contents = PackageContents(venv, pspec)
        assert str(contents) == "mgit [None]"
        assert str(contents.bin) == "bin [1 files]"
        assert contents.entry_points == {"mgit": "dryrun"}

    runez.write(
        "ansible.dist-info/metadata.json",
        '{"extensions": {"python.commands": {"wrap_console": ["ansible"]}}}')
    with patch("runez.run", side_effect=simulated_run):
        pspec = PackageSpec(temp_cfg,
                            "ansible")  # Used to trigger ansible edge case
        contents = PackageContents(venv, pspec)
        assert str(contents) == "ansible [.]"
        assert str(contents.bin) == "bin [0 files]"
        assert str(contents.completers) == "bin [1 files]"
        assert str(contents.dist_info) == "ansible.dist-info [1 files]"
        assert contents.entry_points == ["ansible"]
        assert str(contents.files) == " [1 files]"
        assert contents.files.files.get("foo/bar.py")
        assert contents.info == {
            "Name": "ansible",
            "Version": "1.0.0",
            "Location": "."
        }
        assert contents.location == "."
        assert contents.pspec is pspec
        assert contents.venv is venv

        contents = PackageContents(venv, PackageSpec(temp_cfg, "no-location"))
        assert contents.files is None
        assert contents.entry_points is None

        contents = PackageContents(venv,
                                   PackageSpec(temp_cfg, "no-such-package"))
        assert contents.files is None
        assert contents.entry_points is None
コード例 #16
0
def test_debian_mode(temp_folder, logged):
    runez.write(
        "foo/setup.py",
        "import setuptools\nsetuptools.setup(name='foo', version='1.0')")
    p = dummy_finalizer("root/apps")
    assert p.dist == "root/apps/foo"
    assert p.requirements == [runez.resolved_path("foo")]
    assert "Using python:" in logged.pop()

    # Symlink not created unless source effectively exists
    p.symlink.apply("root/foo")
    assert "skipping symlink" in logged.pop()
    assert not os.path.isdir("root/usr/local/bin")

    foo = runez.resolved_path("root/foo")
    runez.touch(foo)
    logged.pop()

    # Simulate symlink
    p.symlink.apply(foo)
    assert "Symlinked root/usr/local/bin/foo -> root/foo" in logged.pop()
    assert os.path.isdir("root/usr/local/bin")
    assert os.path.islink("root/usr/local/bin/foo")

    with patch("os.path.isdir", return_value=True):  # pretend /apps exists
        p = dummy_finalizer("root/apps")
        assert "debian mode" in logged.pop()
        assert p.dist == "/apps/foo"

    with patch("runez.run",
               return_value=runez.program.RunResult("usage: ...")):
        assert p.validate_sanity_check(
            "foo", "--version") == "does not respond to --version"

    with patch("runez.run", return_value=runez.program.RunResult("failed")):
        with pytest.raises(SystemExit):
            p.validate_sanity_check("foo", "--version")

        assert "'foo' failed --version sanity check" in logged.pop()
コード例 #17
0
ファイル: delivery.py プロジェクト: reallistic/pickley
def relocate_venv(path, source, destination, fatal=True, _seen=None):
    """
    :param str path: Path of file or folder to relocate (change mentions of 'source' to 'destination')
    :param str source: Where venv used to be
    :param str destination: Where venv is moved to
    :param bool fatal: Abort execution on failure if True
    :return int: Number of relocated files (0 if no-op, -1 on failure)
    """
    original_call = False
    if _seen is None:
        original_call = True
        _seen = set()

    if not path or path in _seen:
        return 0

    _seen.add(path)
    if os.path.isdir(path):
        relocated = 0
        if original_call:
            for bin_folder in find_venvs(path):
                for name in os.listdir(bin_folder):
                    fpath = os.path.join(bin_folder, name)
                    r = relocate_venv(fpath,
                                      source,
                                      destination,
                                      fatal=fatal,
                                      _seen=_seen)
                    if r < 0:
                        return r
                    relocated += r
        return relocated

    modified = False
    lines = []
    try:
        for line in runez.readlines(path):
            if source in line:
                line = line.replace(source, destination)
                modified = True

            lines.append(line)

    except Exception:
        return 0  # If binary file, skip

    if not modified:
        return 0

    return runez.write(path, "\n".join(lines), fatal=fatal)
コード例 #18
0
ファイル: test_path.py プロジェクト: pombredanne/runez
def test_failed_read(*_):
    with runez.CaptureOutput() as logged:
        assert runez.get_lines("bar", fatal=False) is None
        assert "Can't read" in logged.pop()

        assert runez.write("bar", "some content", fatal=False)
        assert "Can't write" in logged.pop()

        assert runez.copy("some-file", "bar", fatal=False) == -1
        assert "Can't delete" in logged
        assert "Can't copy" in logged.pop()

        assert runez.make_executable("some-file", fatal=False) == -1
        assert "Can't chmod" in logged.pop()
コード例 #19
0
def test_ini_to_dict(temp_folder, logged):
    assert runez.file.ini_to_dict(None) == {}
    assert runez.file.ini_to_dict("foo") == {}
    assert not logged

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

    expected = {None: {"root": "some-value"}, "": {"ek": "ev"}, "s1": {"k1": "v1"}, "s2": {"k2": ""}}
    runez.write("test.ini", SAMPLE_CONF, logger=None)

    actual = runez.file.ini_to_dict("test.ini", keep_empty=True, logger=None)
    assert not logged
    assert actual == expected

    del expected[None]
    del expected[""]
    del expected["s2"]
    actual = runez.file.ini_to_dict("test.ini", keep_empty=False)
    assert not logged
    assert actual == expected
コード例 #20
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")
コード例 #21
0
def test_lock(temp_cfg, logged):
    pspec = PackageSpec(temp_cfg, "foo")
    lock_path = dot_meta("foo.lock")
    with SoftLock(pspec, give_up=600) as lock:
        assert str(lock) == "lock foo"
        assert os.path.exists(lock_path)
        try:
            # Try to grab same lock a seconds time, give up after 1 second
            with SoftLock(pspec, give_up=1, invalid=600):
                assert False, "Should not grab same lock twice!"

        except SoftLockException as e:
            assert "giving up" in str(e)

    assert not os.path.exists(lock_path)  # Check that lock was released

    # Check that lock detects bogus (or dead) PID
    runez.write(lock_path, "0\nbar\n")
    with SoftLock(pspec, give_up=600):
        lines = list(runez.readlines(lock_path))
        assert lines[0] == str(
            os.getpid())  # Lock file replaced with correct stuff

    assert not os.path.exists(lock_path)  # Lock released
コード例 #22
0
ファイル: test_behavior.py プロジェクト: pombredanne/pickley
def test_relocate_venv_successfully(temp_base):
    with runez.CaptureOutput() as logged:
        original = "line 1: source\nline 2\n"
        runez.write("foo/bar/bin/baz", original, logger=logging.debug)
        runez.write("foo/bar/bin/empty", "", logger=logging.debug)
        runez.write("foo/bar/bin/python", "", logger=logging.debug)
        runez.make_executable("foo/bar/bin/baz")
        runez.make_executable("foo/bar/bin/empty")
        runez.make_executable("foo/bar/bin/python")
        assert "Created" in logged.pop()

        # Simulate already seen
        expected = ["line 1: source\n", "line 2\n"]
        assert system.relocate_venv("foo",
                                    "source",
                                    "dest",
                                    fatal=False,
                                    _seen={"foo"}) == 0
        assert runez.get_lines("foo/bar/bin/baz") == expected
        assert not logged

        # Simulate failure to write
        with patch("runez.write", return_value=-1):
            assert system.relocate_venv("foo", "source", "dest",
                                        fatal=False) == -1
        assert runez.get_lines("foo/bar/bin/baz") == expected
        assert not logged

        # Simulate effective relocation, by folder
        expected = ["line 1: dest\n", "line 2\n"]
        assert system.relocate_venv("foo", "source", "dest", fatal=False) == 1
        assert runez.get_lines("foo/bar/bin/baz") == expected
        assert "Relocated " in logged

        # Second relocation is a no-op
        assert system.relocate_venv("foo", "source", "dest", fatal=False) == 0

        # Test relocating a single file
        runez.write("foo/bar/bin/baz", original, logger=logging.debug)
        assert system.relocate_venv("foo/bar/bin/baz",
                                    "source",
                                    "dest",
                                    fatal=False) == 1
        assert "Relocated " in logged
コード例 #23
0
def test_failure(monkeypatch):
    monkeypatch.setattr(io, "open", runez.conftest.exception_raiser())
    monkeypatch.setattr(os, "unlink", runez.conftest.exception_raiser("bad unlink"))
    monkeypatch.setattr(shutil, "copy", runez.conftest.exception_raiser())
    monkeypatch.setattr(os.path, "exists", lambda _: True)
    monkeypatch.setattr(os.path, "isfile", lambda _: True)
    monkeypatch.setattr(os.path, "getsize", lambda _: 10)
    with runez.CaptureOutput() as logged:
        with patch("runez.file._do_delete"):
            with patch("pathlib.Path.exists", return_value=True):
                assert runez.copy("some-file", "bar", fatal=False) == -1
                assert "Can't copy" in logged.pop()

        assert runez.delete("some-file", fatal=False) == -1
        assert "Can't delete" in logged
        assert "bad unlink" in logged.pop()

        assert runez.write("bar", "some content", fatal=False)
        assert "Can't write" in logged.pop()

        if not runez.SYS_INFO.platform_id.is_windows:
            assert runez.make_executable("some-file", fatal=False) == -1
            assert "Can't chmod" in logged.pop()
コード例 #24
0
def test_bootstrap(cli, monkeypatch):
    with patch("pickley.bstrap.which", side_effect=mocked_which):
        with patch("pickley.bstrap.os.path.expanduser",
                   side_effect=mocked_expanduser):
            runez.write(
                ".local/bin/pickley",
                "#!/bin/sh\necho 0.1")  # Pretend we have an old pickley
            runez.make_executable(".local/bin/pickley")

            with patch("pickley.bstrap.get_python_version",
                       return_value=(3, 6)):  # urllib fails
                monkeypatch.setenv("__PYVENV_LAUNCHER__", "oh apple, why?"
                                   )  # macos oddity env var, should be removed
                cli.run("-n", main=bstrap.main)
                assert cli.succeeded
                assert "__PYVENV_LAUNCHER__" not in os.environ
                assert "Replacing older pickley 0.1" in cli.logged
                assert "Would run: python virtualenv.pyz" in cli.logged
                assert "Would run: .local/bin/.pickley/pickley/pickley-" in cli.logged

            # Simulate multiple base candidates given
            cli.run("-n", "-b", "~/.local/bin:foo/bar", main=bstrap.main)
            assert cli.failed
            assert "not suitable: ~/.local/bin, foo/bar" in cli.logged

            # Simulate seeding
            cli.run("0.1",
                    "-b",
                    "~/.local/bin",
                    "-m",
                    "my-mirror",
                    "-c",
                    '{"pyenv":"~/.pyenv"}',
                    main=bstrap.main)
            assert cli.succeeded
            assert "Seeding .local/bin/.pickley/config.json with {'pyenv': '~/.pyenv'}" in cli.logged
            assert "Seeding .config/pip/pip.conf with my-mirror" in cli.logged
            assert "pickley version 0.1 is already installed" in cli.logged
            assert list(runez.readlines(".config/pip/pip.conf")) == [
                "[global]", "index-url = my-mirror"
            ]
            assert list(
                runez.readlines(".local/bin/.pickley/config.json")) == [
                    "{", '  "pyenv": "~/.pyenv"', "}"
                ]

            monkeypatch.setenv("PATH", "foo/bar:%s" % os.environ["PATH"])
            runez.ensure_folder("foo/bar", logger=None)
            cli.run("-n", "-b", "~/.local/bin:foo/bar", main=bstrap.main)
            assert cli.succeeded
            assert "base: foo/bar" in cli.logged

            with patch("pickley.bstrap.which", return_value=None):
                with patch("pickley.bstrap.is_executable", return_value=False):
                    # Simulate no python 3
                    cli.run("-n", main=bstrap.main)
                    assert cli.failed
                    assert "Could not find python3 on this machine" in cli.logged

            with patch("pickley.bstrap.get_python_version",
                       return_value=(3, 9)):  # urllib fails
                cli.run("-n", main=bstrap.main)
                assert cli.succeeded
                assert " -mvenv " in cli.logged
コード例 #25
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")
コード例 #26
0
ファイル: system.py プロジェクト: pombredanne/pickley
def relocate_venv(path,
                  source,
                  destination,
                  fatal=True,
                  logger=LOG.debug,
                  _seen=None):
    """
    :param str path: Path of file or folder to relocate (change mentions of 'source' to 'destination')
    :param str source: Where venv used to be
    :param str destination: Where venv is moved to
    :param bool fatal: Abort execution on failure if True
    :param callable|None logger: Logger to use
    :return int: Number of relocated files (0 if no-op, -1 on failure)
    """
    original_call = False
    if _seen is None:
        original_call = True
        _seen = set()

    if not path or path in _seen:
        return 0

    _seen.add(path)
    if os.path.isdir(path):
        relocated = 0
        if original_call:
            for bin_folder in find_venvs(path):
                for name in os.listdir(bin_folder):
                    fpath = os.path.join(bin_folder, name)
                    r = relocate_venv(fpath,
                                      source,
                                      destination,
                                      fatal=fatal,
                                      logger=logger,
                                      _seen=_seen)
                    if r < 0:
                        return r
                    relocated += r
            if logger and relocated:
                logger("Relocated %s files in %s: %s -> %s", relocated,
                       short(path), short(source), short(destination))
        return relocated

    content = runez.get_lines(path, fatal=fatal)
    if not content:
        return 0

    modified = False
    lines = []
    for line in content:
        if source in line:
            line = line.replace(source, destination)
            modified = True
        lines.append(line)

    if not modified:
        return 0

    r = runez.write(path, "".join(lines), fatal=fatal)
    if r > 0 and logger and original_call:
        logger("Relocated %s: %s -> %s", short(path), short(source),
               short(destination))
    return r
コード例 #27
0
ファイル: test_path.py プロジェクト: pombredanne/runez
def test_paths(temp_folder):
    assert runez.resolved_path(None) is None
    assert runez.resolved_path("some-file") == os.path.join(temp_folder, "some-file")
    assert runez.resolved_path("some-file", base="bar") == os.path.join(temp_folder, "bar", "some-file")

    assert runez.short(None) is None
    assert runez.short("") == ""
    assert runez.short(temp_folder) == temp_folder

    assert runez.short(temp_folder + "/some-file") == "some-file"
    assert runez.short(temp_folder + "/some-file") == "some-file"

    assert runez.parent_folder(None) is None
    assert runez.parent_folder(temp_folder + "/some-file") == temp_folder

    assert runez.represented_args(["ls", temp_folder + "/some-file bar", "-a"]) == 'ls "some-file bar" -a'

    # Don't crash for no-ops
    assert runez.ensure_folder(None) == 0
    assert runez.ensure_folder("") == 0
    assert runez.copy(None, None) == 0
    assert runez.move(None, None) == 0
    assert runez.symlink(None, None) == 0
    assert runez.copy("some-file", "some-file") == 0
    assert runez.move("some-file", "some-file") == 0
    assert runez.symlink("some-file", "some-file") == 0

    assert runez.ensure_folder("some-folder") == 0  # 'some-folder' would be in temp_folder, which already exists

    with runez.CaptureOutput(dryrun=True) as logged:
        assert runez.ensure_folder("some-folder", folder=True, fatal=False) == 1
        assert "Would create" in logged.pop()

        assert runez.touch("some-file", logger=logging.debug) == 1
        assert "Would touch some-file" in logged.pop()

        assert runez.copy("some-file", "bar") == 1
        assert "Would copy some-file -> bar" in logged.pop()

        assert runez.move("some-file", "bar") == 1
        assert "Would move some-file -> bar" in logged.pop()

        assert runez.symlink("some-file", "bar") == 1
        assert "Would symlink some-file <- bar" in logged.pop()

        assert runez.delete(temp_folder) == 1
        assert "Would delete" in logged.pop()

        assert runez.copy("some-folder/bar/baz", "some-folder", fatal=False) == -1
        assert "source contained in destination" in logged.pop()

        assert runez.move("some-folder/bar/baz", "some-folder", fatal=False) == -1
        assert "source contained in destination" in logged.pop()

        assert runez.symlink("some-folder/bar/baz", "some-folder", fatal=False) == -1
        assert "source contained in destination" in logged.pop()

    with runez.CaptureOutput():
        assert runez.touch("sample") == 1
        assert "Can't create folder" in runez.verify_abort(runez.ensure_folder, "sample", folder=True)
        custom = runez.verify_abort(runez.ensure_folder, "sample", folder=True, fatal=SystemExit, expected_exception=SystemExit)
        assert "Can't create folder" in custom
        with pytest.raises(AssertionError):
            assert runez.verify_abort(runez.ensure_folder, None)

        assert runez.delete("sample") == 1
        assert runez.ensure_folder("sample", folder=True) == 1
        assert os.getcwd() == temp_folder

    with runez.CurrentFolder("sample", anchor=False):
        cwd = os.getcwd()
        sample = os.path.join(temp_folder, "sample")
        assert cwd == sample
        assert runez.short(os.path.join(cwd, "some-file")) == "sample/some-file"

    with runez.CurrentFolder("sample", anchor=True):
        cwd = os.getcwd()
        sample = os.path.join(temp_folder, "sample")
        assert cwd == sample
        assert runez.short(os.path.join(cwd, "some-file")) == "some-file"

    assert os.getcwd() == temp_folder

    assert runez.delete("sample") == 1

    with runez.CaptureOutput() as logged:
        sample = os.path.join(os.path.dirname(__file__), "sample.txt")
        content = runez.get_lines(sample)

        assert runez.write("sample", "".join(content), fatal=False, logger=logging.debug) == 1
        assert runez.get_lines("sample") == content
        assert "Writing 13 bytes" in logged.pop()

        assert runez.first_line("sample") == "Fred"
        assert runez.is_younger("sample", age=10)
        assert not runez.is_younger("sample", age=-1)

        assert runez.copy("bar", "baz", fatal=False) == -1
        assert "does not exist" in logged.pop()
        assert runez.move("bar", "baz", fatal=False) == -1
        assert "does not exist" in logged.pop()
        assert runez.symlink("bar", "baz", fatal=False) == -1
        assert "does not exist" in logged.pop()

        # Creating dangling symlinks is possible
        assert runez.symlink("bar", "baz", fatal=False, must_exist=False) == 1
        assert "Symlink bar <- baz" in logged.pop()
        assert os.path.islink("baz")
        assert not os.path.exists("baz")

        assert runez.copy("sample", "x/y/sample") == 1
        assert runez.symlink("sample", "x/y/sample3", fatal=False) == 1

        assert os.path.exists("sample")
        assert runez.move("sample", "x/y/sample2") == 1
        assert not os.path.exists("sample")

        assert runez.copy("x/y", "x/z") == 1
        assert os.path.exists("x/z/sample")
        assert os.path.exists("x/z/sample2")
        assert os.path.exists("x/z/sample3")
        assert os.path.islink("x/z/sample3")

    assert runez.touch(None) == 0
    assert not runez.is_younger(None, 1)
    assert not runez.is_younger("/dev/null/not-there", 1)
    assert runez.first_line("/dev/null/not-there") is None

    assert runez.get_lines(None) is None
コード例 #28
0
def test_versions(_, __, temp_base):
    p = PACKAGERS.get("pex")("foo")
    p.pip_wheel = lambda *_: None

    assert p.specced_command() == "pex"
    p.implementation_version = "1.4.5"
    assert p.specced_command() == "pex==1.4.5"
    p.refresh_desired()
    assert p.desired.representation(
        verbose=True
    ) == "foo: can't determine latest version from pypi (channel: latest, source: pypi)"

    with patch("pickley.package.latest_pypi_version",
               return_value="error: test failed"):
        p.refresh_desired()
        assert p.desired.representation() == "foo: test failed"

    system.SETTINGS.cli.contents["channel"] = "stable"
    p.refresh_desired()
    assert p.desired.representation() == "foo: can't determine stable version"

    p.version = None
    assert "can't determine stable version" in verify_abort(p.install)

    # Without a build folder
    assert p.get_entry_points() is None

    # With an empty build fodler
    runez.ensure_folder(p.build_folder, folder=True)
    assert p.get_entry_points() is None

    # With a bogus wheel
    with runez.CaptureOutput() as logged:
        p.version = "0.0.0"
        whl = os.path.join(p.build_folder, "foo-0.0.0-py2.py3-none-any.whl")
        runez.touch(whl)
        assert p.get_entry_points() is None
        assert "Can't read wheel" in logged
        runez.delete(whl)

        p.refresh_desired()
        assert p.desired.channel == "adhoc"
        assert p.desired.source == "cli"
        assert p.desired.version == "0.0.0"
        assert not p.desired.problem
        p.version = None
        p.refresh_desired()
        assert p.desired.problem

    # Ambiguous package() call
    assert "Need either source_folder or version in order to package" in verify_abort(
        p.package)

    # Package bogus folder without a setup.py
    p.source_folder = temp_base
    assert "No setup.py" in verify_abort(p.package)

    # Package with a bogus setup.py
    setup_py = os.path.join(temp_base, "setup.py")
    runez.touch(setup_py)
    assert "Could not determine version" in verify_abort(p.package)

    # Provide a minimal setup.py
    runez.write(
        setup_py,
        "from setuptools import setup\nsetup(name='foo', version='0.0.0')\n")

    # Package project without entry points
    p.get_entry_points = lambda *_: None
    assert "is not a CLI" in verify_abort(p.required_entry_points)
コード例 #29
0
def test_file_inspection(temp_folder, logged):
    assert runez.touch("sample") == 1
    assert runez.delete("sample") == 1
    assert "Deleted sample" in logged.pop()

    assert runez.ensure_folder("sample") == 1
    assert runez.delete("sample") == 1
    assert "Deleted sample" in logged.pop()

    sample = runez.DEV.tests_path("sample.txt")
    assert len(list(runez.readlines(sample))) == 4
    assert len(list(runez.readlines(sample, first=1))) == 1
    assert not logged

    cc = "%s\n" % "\n".join(runez.readlines(sample))
    assert runez.write("sample", cc, fatal=False, logger=logging.debug) == 1
    cc2 = "%s\n" % "\n".join(runez.readlines("sample"))
    assert cc2 == cc
    assert "bytes to sample" in logged.pop()  # Wrote 13 bytes on linux... but 14 on windows...

    assert list(runez.readlines("sample", first=2)) == ["", "Fred"]
    assert runez.file.is_younger("sample", age=10)
    assert not runez.file.is_younger("sample", age=-1)

    # Verify that readlines() can ignore encoding errors
    with io.open("not-a-text-file", "wb") as fh:
        fh.write(b"\x89 hello\nworld")

    assert list(runez.readlines("not-a-text-file", first=1)) == [" hello"]
    assert not logged

    assert runez.copy("bar", "baz", fatal=False) == -1
    assert "does not exist" in logged.pop()
    assert runez.move("bar", "baz", fatal=False) == -1
    assert "does not exist" in logged.pop()
    assert runez.symlink("bar", "baz", fatal=False) == -1
    assert "does not exist" in logged.pop()

    # Creating dangling symlinks is possible
    assert runez.symlink("s/bar", "s/baz", fatal=False, must_exist=False) == 1
    assert "Symlink s/bar <- s/baz" in logged.pop()
    assert os.path.islink("s/baz")
    assert not os.path.exists("s/baz")
    runez.touch("s/bar")
    assert os.path.exists("s/baz")

    assert runez.copy("sample", "x/y/sample") == 1
    assert runez.symlink("sample", "x/y/sample3", fatal=False) == 1

    assert os.path.exists("sample")
    assert runez.move("sample", "x/y/sample2") == 1
    assert not os.path.exists("sample")

    assert runez.copy("x/y", "x/z1") == 1
    assert os.path.exists("x/z1/sample")
    assert os.path.exists("x/z1/sample2")
    assert os.path.exists("x/z1/sample3")
    assert os.path.islink("x/z1/sample3")

    assert runez.copy("x/y", "x/z2", ignore={"sample2"}) == 1
    assert os.path.exists("x/z2/sample")
    assert not os.path.exists("x/z2/sample2")
    assert os.path.exists("x/z2/sample3")
    assert os.path.islink("x/z2/sample3")

    def should_ignore(src, dest):
        if src == "x/y" and "sample3" in dest:
            return {"sample3"}

    assert runez.copy("x/y", "x/z3", ignore=should_ignore) == 1
    assert os.path.exists("x/z3/sample")
    assert os.path.exists("x/z3/sample2")
    assert not os.path.exists("x/z3/sample3")

    assert runez.copy("x/y", "x/z2") == 1
    assert os.path.exists("x/z2/sample2")

    # Copy a folder over an existing file
    runez.touch("x2")
    assert not os.path.exists("x2/z2/sample2")
    assert runez.copy("x", "x2") == 1
    assert os.path.exists("x2/z2/sample2")
コード例 #30
0
def test_decompress(temp_folder, logged):
    runez.write("test/README.md", "hello", logger=None)
    runez.write("test/a/b", "c", logger=None)
    expected = dir_contents("test")
    test_folder = runez.to_path("test/")
    assert runez.filesize(test_folder) == 6
    assert runez.represented_bytesize(test_folder) == "6 B"
    assert runez.represented_bytesize(runez.to_path("no-such-file")) == "0 B"

    # Unknown extension
    assert runez.compress("test", "test.foo", overwrite=False, fatal=False) == -1
    assert "Unknown extension 'test.foo'" in logged.pop()
    assert runez.decompress("test.foo", "somewhere", fatal=False) == -1
    assert "Unknown extension 'test.foo'" in logged.pop()

    assert runez.compress("test", "test.tar.gz", dryrun=True) == 1
    assert "Would tar test -> test.tar.gz" in logged.pop()

    assert runez.compress("test", "test.tar") == 1
    assert runez.compress("test", "test.tar.gz") == 1
    assert runez.compress("test", "test.tar.xz") == 1
    assert runez.compress("test", "test.zip") == 1
    assert "Tar test -> test.tar.gz" in logged.pop()
    size_raw = runez.filesize("test.tar")
    size_gz = runez.filesize("test.tar.gz")
    size_xz = runez.filesize("test.tar.xz")
    size_zip = runez.filesize("test.zip")
    assert size_raw > size_gz
    assert size_gz != size_xz
    if sys.version_info[:2] > (3, 8):
        # Flakey for some reason on 3.6... not sure why (.gz and .zip sizes are sometimes equal...)
        assert size_gz != size_zip

    # Tar on top of existing file
    assert runez.compress("test", "test.tar.gz", overwrite=False, fatal=False) == -1
    assert "test.tar.gz exists, can't tar" in logged.pop()

    assert runez.decompress("test.tar.gz", "unpacked", dryrun=True) == 1
    assert "Would untar test.tar.gz -> unpacked" in logged.pop()

    assert runez.decompress("test.tar.gz", "unpacked", simplify=True) == 1
    assert "Untar test.tar.gz -> unpacked" in logged.pop()
    assert dir_contents("unpacked") == expected

    # Second attempt fails without overwrite
    assert runez.decompress("test.tar.gz", "unpacked", overwrite=False, fatal=False) == -1
    assert "unpacked exists, can't untar" in logged.pop()

    # Second attempt succeeds with overwrite
    assert runez.decompress("test.tar.gz", "unpacked", simplify=True, logger=None) == 1
    assert dir_contents("unpacked") == expected

    # Check .xz file
    assert runez.decompress("test.tar.gz", "unpacked", simplify=True, logger=None) == 1
    assert dir_contents("unpacked") == expected

    # Check .zip file
    assert runez.decompress("test.zip", "unpacked", simplify=True, logger=None) == 1
    assert dir_contents("unpacked") == expected
    assert not logged

    assert runez.decompress("test.zip", "unpacked2", logger=None) == 1
    assert dir_contents("unpacked2") == {"test": expected}

    # Verify that arcname=None works correctly
    assert runez.compress("test", "test-flat.tar.gz", arcname=None) == 1
    assert runez.compress("test", "test-flat.zip", arcname=None) == 1
    assert runez.decompress("test-flat.tar.gz", "unpacked-flat-gz", logger=None) == 1
    assert runez.decompress("test-flat.zip", "unpacked-flat-zip", logger=None) == 1
    assert dir_contents("unpacked-flat-gz") == expected
    assert dir_contents("unpacked-flat-zip") == expected