Example #1
0
def test_temp_folder():
    cwd = os.getcwd()

    with runez.CaptureOutput(
            anchors=[os.path.join("/tmp"),
                     os.path.join("/etc")]) as logged:
        with runez.TempFolder() as tmp:
            assert os.path.isdir(tmp)
            assert tmp != runez.system.SYMBOLIC_TMP
        assert not os.path.isdir(tmp)
        assert os.getcwd() == cwd

        assert runez.short(os.path.join("/tmp", "some-file")) == "some-file"
        assert runez.short(os.path.join("/etc", "some-file")) == "some-file"

        assert not logged

    symbolic = os.path.join(runez.system.SYMBOLIC_TMP, "some-file")
    with runez.CaptureOutput(dryrun=True) as logged:
        assert os.getcwd() == cwd
        with runez.TempFolder() as tmp:
            assert tmp == runez.system.SYMBOLIC_TMP
            assert runez.short(symbolic) == "some-file"

        assert os.getcwd() == cwd
        with runez.TempFolder(anchor=False) as tmp:
            assert tmp == runez.system.SYMBOLIC_TMP
            assert runez.short(symbolic) == symbolic

        assert not logged

    assert os.getcwd() == cwd
Example #2
0
    def __enter__(self):
        """Acquire lock"""
        if CFG.base:
            runez.Anchored.add(CFG.base.path)

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

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

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

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

        runez.write(self.lock_path,
                    "%s\n%s\n" % (os.getpid(), runez.quoted(sys.argv[1:])),
                    logger=False)
        self.pspec.resolve()
        return self
Example #3
0
def test_temp():
    cwd = os.getcwd()

    with runez.CaptureOutput(anchors=["/tmp", "/etc"]) as logged:
        with runez.TempFolder() as tmp:
            assert os.path.isdir(tmp)
            assert tmp != runez.convert.SYMBOLIC_TMP
        assert not os.path.isdir(tmp)
        assert os.getcwd() == cwd

        assert runez.short("/tmp/some-file") == "some-file"
        assert runez.short("/etc/some-file") == "some-file"

        assert not logged

    symbolic = "%s/some-file" % runez.convert.SYMBOLIC_TMP
    with runez.CaptureOutput(dryrun=True) as logged:
        assert os.getcwd() == cwd
        with runez.TempFolder() as tmp:
            assert tmp == runez.convert.SYMBOLIC_TMP
            assert runez.short(symbolic) == "some-file"

        assert os.getcwd() == cwd
        with runez.TempFolder(anchor=False) as tmp:
            assert tmp == runez.convert.SYMBOLIC_TMP
            assert runez.short(symbolic) == symbolic

        assert not logged

    assert os.getcwd() == cwd
Example #4
0
def test_bogus_config(temp_folder, logged):
    cfg = grab_sample("bogus-config")
    assert cfg.pyenv() == "/dev/null"  # from custom.json
    assert cfg.resolved_bundle("") == []
    assert cfg.resolved_bundle("foo") == ["foo"]
    assert cfg.resolved_bundle("bundle:dev") == ["tox", "mgit"]
    assert cfg.resolved_bundle("bundle:dev2") == ["tox", "mgit", "pipenv"]
    actual = cfg.represented().strip()
    expected = SAMPLE_CONFIG.strip().format(
        base=runez.short(cfg.base),
        meta=runez.short(cfg.meta),
        DEFAULT_PYTHONS=DEFAULT_PYTHONS,
    )
    assert actual == expected

    p = cfg.find_python(pspec=None, fatal=False)
    assert p.executable == "/dev/null/foo"
    assert p.problem == "not an executable"
    assert "skipped: not an executable" in logged.pop()

    assert not logged
    with pytest.raises(SystemExit):
        # Fails to resolve due to desired python configured to be /dev/null
        PackageSpec(cfg, "mgit")

    assert "No suitable python" in logged.pop()
Example #5
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"
Example #6
0
    def apply(self, exe):
        dest = os.path.join(self.target, os.path.basename(exe))
        if os.path.exists(exe):
            r = runez.symlink(exe, dest, must_exist=False)
            if r > 0:
                inform("Symlinked %s -> %s" %
                       (runez.short(dest), runez.short(exe)))

        else:
            LOG.debug("'%s' does not exist, skipping symlink" % exe)
Example #7
0
def test_anchored():
    user_path = runez.resolved_path("~/some-folder/bar")
    current_path = runez.resolved_path("./some-folder/bar")

    assert user_path != "~/some-folder/bar"
    assert runez.short(user_path) == "~/some-folder/bar"
    assert runez.short(current_path) != "some-folder/bar"

    with runez.Anchored(os.getcwd()):
        assert runez.short(current_path) == "some-folder/bar"
Example #8
0
    def __exit__(self, *_):
        """Release lock"""
        if runez.DRYRUN:
            print("Would release %s" % runez.short(self.lock_path))

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

        if CFG.base:
            runez.Anchored.pop(CFG.base.path)

        runez.delete(self.lock_path, logger=False)
Example #9
0
    def represented(cls, value, size=runez.UNSET, stringify=runez.stringified, dt=str):
        if isinstance(value, NotImplementedError):
            if size is None:
                return {"_error": "not implemented"}

            return runez.orange("not implemented")

        if isinstance(value, Exception):
            if size is None:
                return {"_error": runez.short(value, size=256)}

            return runez.red(runez.short(value, size=size))

        return runez.represented_json(value, stringify=stringify, dt=dt, keep_none=True, none_key="-null-")
Example #10
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)
Example #11
0
    def find_python(self, pspec=None, fatal=True):
        """
        Args:
            pspec (PackageSpec | None): Package spec, when applicable
            fatal (bool): If True, abort execution is no valid python could be found

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

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

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

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

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

        return python
Example #12
0
def test_current_folder(temp_folder):
    sample = os.path.join(temp_folder, "sample")
    assert os.getcwd() == temp_folder
    assert runez.ensure_folder("sample") == 1

    with runez.CurrentFolder("sample", anchor=False):
        cwd = os.getcwd()
        assert cwd == sample
        assert runez.short(os.path.join(cwd, "some-file")) == os.path.join(
            "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
Example #13
0
 def __init__(self, path):
     self.path = os.path.abspath(path)
     self.basename = os.path.basename(self.path)
     self.basename, _, self.extension = self.basename.rpartition(
         os.path.extsep)
     self.folder = os.path.dirname(self.path)
     self.name = runez.short(self.path)
     self.category = os.path.dirname(self.name)
     self.key = self.name if "/" in self.name else "./%s" % self.name
     self._expected = {}
Example #14
0
    def represented(self):
        """str: Human readable representation of this configuration"""
        result = ["%s:" % runez.bold(runez.short(self.source))]
        if self.values:
            self._add_dict_representation(result, self.values)

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

        result.append("")
        return "\n".join(result)
Example #15
0
def version_check(programs):
    """Check that programs are present with a minimum version"""
    if not programs:
        runez.abort("Specify at least one program to check")

    specs = []
    for program_spec in programs:
        program, _, min_version = program_spec.partition(":")
        min_version = Version(min_version)
        if not program or not min_version.is_valid:
            runez.abort(
                "Invalid argument '%s', expecting format <program>:<version>" %
                program_spec)

        specs.append((program, min_version))

    overview = []
    for program, min_version in specs:
        if runez.DRYRUN:
            runez.run(program, "--version")
            continue

        full_path = runez.which(program)
        if not full_path:
            runez.abort("%s is not installed" % program)

        r = runez.run(full_path, "--version", fatal=False, logger=None)
        if not r.succeeded:
            runez.abort("%s --version failed: %s" %
                        (runez.short(full_path), runez.short(r.full_output)))

        version = Version.from_text(r.full_output)
        if not version or version < min_version:
            runez.abort("%s version too low: %s (need %s+)" %
                        (runez.short(full_path), version, min_version))

        overview.append("%s %s" % (program, version))

    print(runez.short(runez.joined(overview, delimiter=" ; ")))
Example #16
0
    def _add_dict_representation(self, result, data, indent=1):
        """
        Args:
            result (list): Where to add lines representing 'data'
            data (dict): Data to represent
            indent (int): Indentation to use
        """
        padding = "  " * indent
        for key, value in sorted(data.items()):
            key = self.parent.colored_key(key, indent)
            if isinstance(value, dict):
                result.append("%s%s:" % (padding, key))
                self._add_dict_representation(result, value, indent=indent + 1)

            elif isinstance(value, list):
                result.append("%s%s:" % (padding, key))
                for item in value:
                    result.append("%s- %s" %
                                  (padding + "  ", runez.short(item)))

            else:
                result.append("%s%s: %s" % (padding, key, runez.short(value)))
Example #17
0
def short(path, meta=True):
    """
    :param path: Path to represent in its short form
    :param bool meta: If True, shorten paths relatively to SYSTEM.meta as well
    :return str: Short form, using '~' if applicable
    """
    if not path:
        return path
    if not meta:
        runez.Anchored.pop(SETTINGS.meta.path)
    result = runez.short(str(path))
    if not meta:
        runez.Anchored.add(SETTINGS.meta.path)
    return result
Example #18
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
Example #19
0
def get_target(path, **kwargs):
    """
    :param str path: Path to target
    :param kwargs: Optional preferences
    """
    prefs = MgitPreferences(**kwargs)
    actual_path = find_actual_path(path)
    if not actual_path or not os.path.isdir(actual_path):
        runez.abort("No folder '%s'" % runez.short(actual_path))

    if os.path.isdir(os.path.join(actual_path, ".git")):
        return GitCheckout(actual_path, prefs=prefs)

    return ProjectDir(actual_path, prefs=prefs)
Example #20
0
def test_run_description():
    short_py = runez.short(sys.executable)
    audit = RunAudit(sys.executable, ["-mpip", "--help"], {})
    assert str(audit) == "pip --help"
    assert audit.run_description() == "pip --help"
    assert audit.run_description(
        short_exe=None) == "%s -mpip --help" % short_py
    assert audit.run_description(
        short_exe=False) == "%s -mpip --help" % short_py
    assert audit.run_description(short_exe=True) == "pip --help"
    assert audit.run_description(short_exe="foo") == "foo -mpip --help"

    audit = RunAudit(sys.executable, ["-m", "pip", "--help"], {})
    assert audit.run_description() == "pip --help"
    assert audit.run_description(
        short_exe=None) == "%s -m pip --help" % short_py
    assert audit.run_description(
        short_exe=False) == "%s -m pip --help" % short_py
    assert audit.run_description(short_exe=True) == "pip --help"
    assert audit.run_description(short_exe="foo") == "foo -m pip --help"

    audit = RunAudit(sys.executable, ["bin/pip/__main__.py", "--help"], {})
    assert audit.run_description() == "pip --help"
    assert audit.run_description(
        short_exe=None) == "%s bin/pip/__main__.py --help" % short_py
    assert audit.run_description(
        short_exe=False) == "%s bin/pip/__main__.py --help" % short_py
    assert audit.run_description(short_exe=True) == "pip --help"
    assert audit.run_description(
        short_exe="foo") == "foo bin/pip/__main__.py --help"

    audit = RunAudit("foo/python3", ["-mpip", "--help"], {})
    assert audit.run_description() == "foo/python3 -mpip --help"
    assert audit.run_description(short_exe=None) == "foo/python3 -mpip --help"
    assert audit.run_description(short_exe=False) == "foo/python3 -mpip --help"
    assert audit.run_description(short_exe=True) == "pip --help"
    assert audit.run_description(short_exe="foo") == "foo -mpip --help"

    audit = RunAudit("foo/bar", ["-mpip", "--help"], {})
    assert audit.run_description() == "foo/bar -mpip --help"
    assert audit.run_description(short_exe=None) == "foo/bar -mpip --help"
    assert audit.run_description(short_exe=False) == "foo/bar -mpip --help"
    assert audit.run_description(short_exe=True) == "foo/bar -mpip --help"
    assert audit.run_description(short_exe="foo") == "foo -mpip --help"

    cmd = runez.to_path(runez.SYS_INFO.venv_bin_path("foo"))
    audit = RunAudit(cmd, ["--help"], {})
    assert str(audit) == "foo --help"
    assert audit.run_description() == "foo --help"
Example #21
0
    def header(self):
        result = "%s:" % runez.purple(runez.short(self.path))

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

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

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

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

        return result
Example #22
0
    def deserialized(self, kind):
        try:
            if kind == TestSamples.K_TOKEN:
                tokens = tokens_from_path(self.path)
                actual = [str(t) for t in tokens]

            else:
                actual = load_path(self.path)
                actual = runez.serialize.json_sanitized(actual,
                                                        stringify=decode,
                                                        none_key="-null-")

        except Exception as e:
            actual = {"_error": runez.short(e)}

        return actual
Example #23
0
File: git.py Project: zsimic/mgit
    def _git_command(self, args):
        """
        :param list|tuple args: Git command + args to use
        :return list, str: Full git invocation + human friendly representation
        """
        cmd = ["git"]
        if args and args[0] == "clone":
            args_represented = "git %s" % " ".join(args)

        else:
            args_represented = "git -C %s %s" % (runez.short(
                self.path), " ".join(args))
            cmd.extend(["-C", self.path])

        cmd.extend(args)
        return cmd, args_represented
Example #24
0
def main(debug, log, lines, profile, stacktrace):
    """Troubleshooting commands, useful for iterating on this library"""
    TestSettings.line_numbers = lines
    TestSettings.stacktrace = stacktrace
    runez.log.setup(debug=debug,
                    console_level=logging.INFO,
                    file_location=log,
                    locations=None)
    logging.debug("Running with %s, v%s", runez.short(sys.executable),
                  ".".join(str(s) for s in sys.version_info[:3]))
    runez.Anchored.add([runez.DEV.project_folder, TestSamples.SAMPLE_FOLDER])
    if profile:
        import atexit
        import cProfile

        TestSettings.profiler = cProfile.Profile()
        TestSettings.profiler.enable()
        atexit.register(TestSettings.stop_profiler)
Example #25
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)))
Example #26
0
def my_group(debug):
    # By default, --config value is NOT exposed, the global runez.config.CONFIG is altered
    runez.system.AbortException = SystemExit
    runez.log.setup(
        debug=debug,
        console_format="%(levelname)s %(message)s",
        console_level=logging.INFO,
        locations=None,
        greetings=":: {argv}",
    )
    config = runez.config.CONFIG
    cd = config.get("g.cd")
    if cd:
        logging.info("Changed folder to %s" % runez.short(cd))
        runez.ensure_folder(cd)
        os.chdir(cd)

    assert len(config.providers) == 1
    assert "--config: " in config.overview()
    assert config.provider_by_name("--config") is not None
Example #27
0
def package(build, dist, symlink, no_compile, sanity_check, project,
            requirement):
    """Package a project from source checkout"""
    started = time.time()
    runez.log.spec.default_logger = LOG.info
    CFG.set_base(runez.resolved_path(build))
    finalizer = PackageFinalizer(project, dist, symlink)
    finalizer.sanity_check = sanity_check
    finalizer.requirements = requirement
    finalizer.compile = not no_compile
    finalizer.resolve()
    report = finalizer.finalize()
    if report:
        inform("")
        inform(report)
        inform("")

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

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

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

    abort("Can't automatically uninstall %s" % runez.short(target))
Example #29
0
 def __repr__(self):
     return runez.short(self.path)
Example #30
0
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