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"
def setup_audit_log(cfg=CFG): """Setup audit.log log file handler""" if runez.DRYRUN: if not runez.log.console_handler or runez.log.spec.console_level > logging.INFO: runez.log.setup(console_level=logging.INFO) return if not runez.log.file_handler: if runez.color.is_coloring(): runez.log.progress.start(message_color=runez.dim, spinner_color=runez.bold) log_path = cfg.meta.full_path("audit.log") runez.log.trace("Logging to %s", log_path) runez.ensure_folder(cfg.meta.path) runez.log.setup( file_format= "%(asctime)s %(timezone)s [%(process)s] %(context)s%(levelname)s - %(message)s", file_level=logging.DEBUG, file_location=log_path, greetings=":: {argv}", rotate="size:500k", rotate_count=1, )
def finalize(self): """Run sanity check and/or symlinks, and return a report""" with runez.Anchored(self.folder, CFG.base.path): runez.ensure_folder(CFG.base.path, clean=True, logger=False) dist_folder = runez.resolved_path(self.dist) exes = PACKAGER.package(self.pspec, CFG.base.path, dist_folder, self.requirements, self.compile) if exes: report = PrettyTable( ["Packaged executable", self.sanity_check], border=self.border) report.header.style = "bold" if not self.sanity_check: report.header[1].shown = False for exe in exes: exe_info = self.validate_sanity_check( exe, self.sanity_check) report.add_row(runez.quoted(exe), exe_info) if self.symlink and exe: self.symlink.apply(exe) if not self.compile and not runez.DRYRUN: clean_compiled_artifacts(dist_folder) return report
def effective_package(self, template): """ :param str template: Template describing how to name delivered files, example: {meta}/{name}-{version} """ folder = os.path.join( self.dist_folder, template.format(name=self.name, version=self.version)) runez.delete(folder, logger=None) runez.ensure_folder(folder, folder=True, logger=None) vrun(self.name, "virtualenv", folder) bin_folder = os.path.join(folder, "bin") pip = os.path.join(bin_folder, "pip") spec = self.source_folder if self.source_folder else "%s==%s" % ( self.name, self.version) runez.run(pip, "install", "-i", system.SETTINGS.index, "-f", self.build_folder, spec) if self.relocatable: python = system.target_python(package_name=self.name).executable vrun(self.name, "virtualenv", "--relocatable", "--python=%s" % python, folder) self.packaged.append(folder) self.executables = [ os.path.join(bin_folder, name) for name in self.entry_points ]
def pex_build(self, name, destination): """ Run pex build :param str name: Name of entry point :param str destination: Path to file where to produce pex :return str: None if successful, error message otherwise """ runez.ensure_folder(self.build_folder, folder=True) runez.delete(destination) args = ["--cache-dir", self.build_folder, "--repo", self.build_folder] args.extend([ "-c%s" % name, "-o%s" % destination, "%s==%s" % (self.name, self.version) ]) python = system.target_python(package_name=self.name) shebang = python.shebang( universal=system.is_universal(self.build_folder)) if shebang: args.append("--python-shebang") args.append(shebang) vrun(self.name, self.specced_command(), *args, path_env=C_COMPILATION_HELP)
def package(self): """Package pypi module with 'self.name'""" if not self.version and not self.source_folder: return runez.abort( "Need either source_folder or version in order to package", fatal=(True, [])) if not self.version: setup_py = os.path.join(self.source_folder, "setup.py") if not os.path.isfile(setup_py): return runez.abort("No setup.py in %s", short(self.source_folder), fatal=(True, [])) self.version = system.run_python(setup_py, "--version", dryrun=False, fatal=False, package_name=self.name) if not self.version: return runez.abort("Could not determine version from %s", short(setup_py), fatal=(True, [])) self.pip_wheel() self.refresh_entry_points() runez.ensure_folder(self.dist_folder, folder=True) template = "{name}" if self.source_folder else "{name}-{version}" self.packaged = [] self.effective_package(template)
def test_base(cli, monkeypatch): monkeypatch.setenv("__PYVENV_LAUNCHER__", "foo") folder = os.getcwd() cli.expect_success("-n base", folder) cli.expect_success("-n base audit", dot_meta("audit.log", parent=folder)) cli.expect_success("-n base cache", dot_meta(".cache", parent=folder)) cli.expect_success("-n base meta", dot_meta(parent=folder)) cli.expect_failure("-n base foo", "Unknown base folder reference") cli.run("-n base bootstrap-own-wrapper") assert cli.succeeded assert "Would wrap pickley" in cli.logged monkeypatch.setenv("PICKLEY_ROOT", "temp-base") with pytest.raises(SystemExit): # Env var points to a non-existing folder find_base() runez.ensure_folder("temp-base") assert find_base() == runez.resolved_path("temp-base") assert sys.prefix in get_program_path("foo/bar.py") monkeypatch.delenv("PICKLEY_ROOT") monkeypatch.setattr(PickleyConfig, "program_path", "/foo/.venv/bin/pickley") assert find_base() == "/foo/.venv/root" monkeypatch.setattr(PickleyConfig, "program_path", dot_meta("pickley-0.0.0/bin/pickley", parent="foo")) assert find_base() == "foo" monkeypatch.setattr(PickleyConfig, "program_path", "foo/bar") assert find_base() == "foo"
def clean_folder(folder): """Clean contents of 'folder', if any""" if os.path.isdir(folder): for fname in os.listdir(folder): runez.delete(os.path.join(folder, fname)) else: runez.ensure_folder(folder, folder=True)
def git_clone(pspec): basename = runez.basename(pspec.original) pspec.folder = pspec.cfg.cache.full_path("checkout", basename) runez.ensure_folder(pspec.folder, clean=True, dryrun=False) logger = LOG.info if runez.DRYRUN else runez.UNSET runez.run("git", "clone", pspec.original, pspec.folder, dryrun=False, logger=logger)
def pip_wheel(self): """ Run pip wheel :return str: None if successful, error message otherwise """ runez.ensure_folder(self.build_folder, folder=True) return vrun( self.name, "pip", "wheel", "-i", system.SETTINGS.index, "--cache-dir", self.build_folder, "--wheel-dir", self.build_folder, self.source_folder if self.source_folder else "%s==%s" % (self.name, self.version))
def package(pspec, build_folder, dist_folder, requirements, run_compile_all): runez.ensure_folder(dist_folder, clean=True, logger=False) venv = PythonVenv(pspec, folder=dist_folder) venv.pip_install(*requirements) if run_compile_all: venv.run_python("-mcompileall", dist_folder) contents = PackageContents(venv, pspec) if contents.entry_points: result = [] for name in contents.entry_points: result.append(venv.bin_path(name)) return result
def test_locations(temp_log): runez.log.setup(locations=None) assert runez.log.file_handler is None # Verify that a non-writeable folder is not used runez.ensure_folder("foo/bar", logger=None) os.chmod("foo/bar", 0o400) runez.log.setup(locations=["foo/bar"]) os.chmod("foo/bar", 0o700) assert runez.log.file_handler is None runez.log.setup(locations=["{dev}/test-location.log"]) assert runez.log.file_handler runez.log.setup(locations=["{project}/.venv/test-location.log"]) assert runez.log.file_handler
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
def package(pspec, build_folder, dist_folder, requirements, run_compile_all): runez.ensure_folder(build_folder, clean=True) if pspec.python.major < 3: # pragma: no cover abort("Packaging with pex is not supported any more with python2") pex_root = os.path.join(build_folder, "pex-root") tmp = os.path.join(build_folder, "pex-tmp") wheels = os.path.join(build_folder, "wheels") runez.ensure_folder(tmp, logger=False) runez.ensure_folder(wheels, logger=False) pex_venv = PythonVenv(pspec, folder=os.path.join(build_folder, "pex-venv")) pex_venv.pip_install("pex==2.1.75", *requirements) pex_venv.pip_wheel("--cache-dir", wheels, "--wheel-dir", wheels, *requirements) contents = PackageContents(pex_venv, pspec) if contents.entry_points: wheel_path = pspec.find_wheel(wheels) result = [] for name in contents.entry_points: target = os.path.join(dist_folder, name) runez.delete(target) pex_venv.run_python( "-mpex", "-o%s" % target, "--pex-root", pex_root, "--tmpdir", tmp, "--no-index", "--find-links", wheels, # resolver options None if run_compile_all else "--no-compile", # output options "-c%s" % name, # entry point options "--python-shebang", "/usr/bin/env python%s" % pspec.python.major, wheel_path, ) result.append(target) return result
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()
def __init__(self, pspec=None, folder=None, python=None, index=None, cfg=None, create=True): """ Args: pspec (pickley.PackageSpec | None): Package spec to install folder (str | None): Target folder (default: pspec.install_path) python (pickley.env.PythonInstallation): Python to use (default: pspec.python) index (str | None): Optional custom pypi index to use (default: pspec.index) cfg (pickley.PickleyConfig | None): Config to use create (bool): Create venv if True """ if folder is None and pspec: folder = pspec.install_path if not python and pspec: python = pspec.python if not index and pspec: index = pspec.index self.folder = folder self.index = index self.py_path = os.path.join(folder, "bin", "python3") self.pip_path = os.path.join(folder, "bin", "pip3") if create and folder: cfg = cfg or pspec.cfg python = python or cfg.find_python(pspec=pspec) runez.ensure_folder(folder, clean=True, logger=False) if python.version > "3.7": runez.run(python.executable, "-mvenv", folder) else: import virtualenv.__main__ runez.run(sys.executable, virtualenv.__main__.__file__, "-p", python.executable, folder) self.run_pip("install", "-U", "pip")
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
def test_bogus_install(cli): cli.expect_success("settings -d", "base: %s" % short(cli.context)) cli.expect_success("check", "No packages installed") cli.expect_success("list", "No packages installed") cli.expect_failure("-b foo/bar settings", "Can't use foo/bar as base: folder does not exist") cli.expect_failure("--dryrun check -- -bogus", "not a valid pypi package name") cli.expect_failure("--dryrun check this-package-does-not-exist", "can't determine latest version") cli.expect_failure("--dryrun --delivery foo install tox", "invalid choice: foo") cli.expect_failure("--dryrun uninstall --force /dev/null", "is not a valid pypi package name") cli.expect_success( "--dryrun uninstall --force -- this-package-does-not-exist ", "Nothing to uninstall") runez.touch("foo") assert os.path.exists("foo") cli.expect_failure("uninstall foo", "foo was not installed with pickley") cli.expect_success("uninstall foo --force", "Uninstalled foo") assert not os.path.exists("foo") assert runez.ensure_folder("foo", folder=True) == 1 cli.expect_failure("uninstall foo --force", "Can't automatically uninstall") cli.expect_failure("auto-upgrade foo", "not currently installed") cli.expect_failure("package foo/bar", "Folder", "does not exist") cli.expect_failure(["package", cli.context], "No setup.py") runez.touch(os.path.join(cli.context, "setup.py")) cli.expect_failure(["package", cli.context], "Could not determine package name") cli.expect_success("check", "No packages installed") cli.expect_success("list", "No packages installed") cli.expect_success("settings -d", "base: %s" % short(cli.context))
def test_install(cli): tox = system.SETTINGS.base.full_path("tox") p = PACKAGERS.resolved("tox") p.refresh_desired() tox_version = p.desired.version assert not os.path.exists(tox) assert runez.first_line(tox) is None cli.expect_success("--dryrun -b{base} --delivery wrap install tox", "Would wrap", "Would install tox", base=cli.context) cli.expect_success("--dryrun -b{base} --delivery symlink install tox", "Would symlink", "Would install tox", base=cli.context) cli.expect_failure("--dryrun -b{base} --delivery foo install tox", "invalid choice: foo", base=cli.context) cli.expect_success("--dryrun uninstall /dev/null --force", "Nothing to uninstall") runez.touch("foo") assert os.path.exists("foo") cli.expect_failure("uninstall foo", "foo was not installed with pickley") cli.expect_success("uninstall foo --force", "Uninstalled foo") assert not os.path.exists("foo") assert runez.ensure_folder("foo", folder=True) == 1 cli.expect_failure("uninstall foo --force", "Can't automatically uninstall") cli.expect_failure("-b{base} check tox foo/bar", "is not installed", "can't determine latest version", base=cli.context) cli.expect_failure("-b{base} install six", "'six' is not a CLI", base=cli.context) # Install tox, but add a few files + a bogus previous entry point to test cleanup wep1 = system.SETTINGS.base.full_path("tox-old-entrypoint1") tep10 = system.SETTINGS.meta.full_path("tox", "tox-old-entrypoint1-1.0") tep11 = system.SETTINGS.meta.full_path("tox", "tox-old-entrypoint1-1.1") t00 = system.SETTINGS.meta.full_path("tox", "tox-0.0.0") tfoo = system.SETTINGS.meta.full_path("tox", "tox-foo") runez.touch(wep1) runez.touch(tep10) runez.touch(tep11) runez.touch(t00) runez.touch(tfoo) eppath = system.SETTINGS.meta.full_path("tox", ".entry-points.json") runez.write(eppath, '["tox-old-entrypoint1", "tox-old-entrypoint2"]\n') cli.expect_success("-b{base} --delivery wrap install tox", "Installed tox", base=cli.context) # Old entry point removed immediately assert not os.path.exists(wep1) # Only 1 cleaned up immediately (latest + 1 kept) assert not os.path.exists(tep10) assert os.path.exists(tep11) assert not os.path.exists(t00) assert os.path.exists(tfoo) assert runez.is_executable(tox) output = run_program(tox, "--version") assert "tox" in output assert tox_version in output cli.expect_success("-b{base} auto-upgrade tox", "Skipping auto-upgrade", base=cli.context) runez.delete(system.SETTINGS.meta.full_path("tox", ".ping")) cli.expect_success("-b{base} auto-upgrade tox", "already installed", base=cli.context) version = output.partition(" ")[0] cli.expect_success("copy .pickley/tox/tox-%s tox-copy" % version, "Copied") cli.expect_success("move tox-copy tox-relocated", "Moved") # Verify that older versions and removed entry-points do get cleaned up runez.save_json({"install_timeout": 0}, "custom-timeout.json") cli.expect_success("-b{base} -ccustom-timeout.json install tox", "already installed", base=cli.context) # All cleaned up when enough time went by assert not os.path.exists(tep10) assert not os.path.exists(tep11) assert not os.path.exists(t00) assert not os.path.exists(tfoo) cli.expect_success("-b{base} check", "tox", "is installed", base=cli.context) cli.expect_success( "-b{base} check --verbose", "tox", "is installed (as %s wrap, channel: " % system.VENV_PACKAGER, base=cli.context, ) p = PACKAGERS.get(system.VENV_PACKAGER)("tox") p.refresh_latest() p.latest.version = "10000.0" p.latest.save() cli.expect_failure("-b{base} check", "tox", "can be upgraded to 10000.0", base=cli.context) cli.expect_success("-b{base} -ppex install twine", "Installed twine", base=cli.context) cli.expect_success("-b{base} list", "tox", "twine", base=cli.context) cli.expect_success("-b{base} list --verbose", "tox", "twine", base=cli.context) tmp = os.path.realpath(cli.context) assert find_uninstaller(os.path.join(tmp, "tox")) assert find_uninstaller(os.path.join(tmp, "twine")) cli.expect_success("-b{base} uninstall twine", "Uninstalled twine", base=cli.context) runez.delete(p.current._path) runez.touch(p.current._path) cli.expect_failure("-b{base} check", "tox", "Couldn't read", "is not installed", base=cli.context) cli.expect_success("-b{base} uninstall tox", "Uninstalled tox", "entry points", base=cli.context)
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
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
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)
def test_edge_cases(temp_cfg, logged): runez.touch("dummy.whl") runez.ensure_folder(".", clean=True) assert "Cleaned 1 file from" in logged.pop() assert not os.path.exists("dummy.whl")
def test_ensure_folder(temp_folder, logged): assert runez.ensure_folder(None) == 0 assert runez.ensure_folder("") == 0 assert runez.ensure_folder(".") == 0 assert not logged assert runez.ensure_folder(".", clean=True) == 0 assert not logged assert runez.touch("some-file", logger=None) == 1 with pytest.raises(Exception): runez.ensure_folder("some-file") assert "Can't create folder" in logged.pop() assert runez.ensure_folder("some-dir", dryrun=True) == 1 assert "Would create some-dir" in logged.pop() assert runez.ensure_folder("some-dir") == 1 assert "Created folder some-dir" in logged.pop() assert runez.ensure_folder("some-dir") == 0 assert not logged assert runez.touch("some-dir/a/b") == 1 assert "Created folder" not in logged assert "Touched some-dir/a/b" in logged.pop() assert runez.ensure_folder("some-dir", clean=True, dryrun=True) == 1 assert "Would clean 1 file from some-dir" in logged.pop() assert runez.touch("some-dir/b", logger=False) == 1 assert not logged assert runez.ensure_folder("some-dir", clean=True) == 2 assert "Cleaned 2 files from some-dir" in logged
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")