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 auto_upgrade(force, package): """ Auto-upgrade a package """ package = system.PackageSpec(package) p = PACKAGERS.resolved(package) if not p.current.valid: sys.exit("%s is not currently installed" % package) ping = system.SETTINGS.meta.full_path(package.dashed, ".ping") if not force and runez.file.is_younger( ping, system.SETTINGS.version_check_seconds): # We checked for auto-upgrade recently, no need to check again yet print("Skipping auto-upgrade, checked recently") sys.exit(0) runez.touch(ping) try: p.internal_install() except SoftLockException: print( "Skipping auto-upgrade, %s is currently being installed by another process" % package) sys.exit(0)
def test_ensure_freeze(_, __, temp_base): # Test edge case for _installed_module() with SoftLock(temp_base) as lock: fake_pex = os.path.join(temp_base, "bin/pex") runez.touch(fake_pex) runez.make_executable(fake_pex) v = SharedVenv(lock, None) assert v._installed_module("pex")
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 perform_delivery(self, template): """ :param str template: Template describing how to name delivered files, example: {meta}/{name}-{version} """ # Touch the .ping file since this is a fresh install (no need to check for upgrades right away) runez.touch(system.SETTINGS.meta.full_path(self.package_spec.dashed, ".ping")) self.executables = [] deliverer = DELIVERERS.resolved(self.package_spec, default=self.desired.delivery) for name in self.entry_points: target = system.SETTINGS.base.full_path(name) if self.package_spec.dashed != system.PICKLEY and not self.current.file_exists: uninstall_existing(target) path = template.format(meta=system.SETTINGS.meta.full_path(self.package_spec.dashed), name=name, version=self.desired.version) deliverer.install(target, path) self.executables.append(target)
def test_edge_cases(temp_folder, logged): venv = MagicMock(bin_path=lambda x: os.path.join("some-package/bin", x)) entry_points = {"some-source": ""} cfg = PickleyConfig() cfg.set_base(".") pspec = PackageSpec(cfg, "mgit", "1.0.0") d = DeliveryMethod() with pytest.raises(SystemExit): d.install(pspec, venv, entry_points) assert "Can't deliver some-source -> some-package/bin/some-source: source does not exist" in logged.pop( ) runez.touch("some-package/bin/some-source") with pytest.raises(SystemExit): d.install(pspec, venv, entry_points) assert "Failed to deliver" in logged.pop()
def auto_upgrade(force, package): """Background auto-upgrade command (called by wrapper)""" pspec = PackageSpec(CFG, package) ping = pspec.ping_path if not force and runez.file.is_younger( ping, 5): # 5 seconds cool down on version check to avoid bursts LOG.debug("Skipping auto-upgrade, checked recently") sys.exit(0) runez.touch(ping) lock_path = pspec.get_lock_path() if runez.file.is_younger(lock_path, CFG.install_timeout(pspec)): LOG.debug("Lock file present, another installation is in progress") sys.exit(0) perform_install(pspec, is_upgrade=True, force=False, quiet=True)
def test_run(temp_folder): assert runez.program.added_env_paths(None) is None ls = runez.which("ls") with runez.CaptureOutput(dryrun=True) as logged: assert "Would run: /dev/null" in runez.run("/dev/null", fatal=False) assert "Would run: /dev/null" in logged.pop() assert "Would run:" in runez.run(ls, "--invalid-flag", None, ".") assert "Would run: %s ." % ls in logged.pop() with runez.CaptureOutput() as logged: assert runez.run("/dev/null", fatal=False) is False assert "/dev/null is not installed" in logged.pop() assert runez.touch("sample") == 1 assert runez.run(ls, "--invalid-flag", None, ".", path_env={"PATH": ":."}) == "sample" assert "Running: %s ." % ls in logged.pop() assert runez.run(ls, "some-file", fatal=False) is False assert "Running: %s some-file" % ls in logged assert "exited with code" in logged assert "No such file" in logged.pop()
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)))
def test_install_pypi(cli): cli.expect_failure("--color install six", "it is not a CLI") assert not os.path.exists(dot_meta("six")) cli.expect_failure("install mgit+foo", "not a valid pypi package name") runez.touch( dot_meta("mgit/.foo")) # Should stay because name starts with '.' runez.touch(dot_meta("mgit/mgit-foo")) # Bogus installation runez.touch(dot_meta("mgit/mgit-0.0.1/foo")) # Oldest should be deleted # Simulate the presence of an old entry point manifest_path = dot_meta("mgit/.manifest.json") runez.save_json(dict(entrypoints=["mgit", "old-mgit-entrypoint"]), manifest_path) runez.touch("old-mgit-entrypoint") assert os.path.exists("old-mgit-entrypoint") time.sleep(0.01) # Ensure 0.0.1 is older than 0.0.2 runez.touch( dot_meta("mgit/mgit-0.0.2/foo")) # Youngest should remain for an hour check_install_from_pypi(cli, "symlink", "mgit") assert not os.path.exists("old-mgit-entrypoint") assert os.path.islink("mgit") assert os.path.exists(dot_meta("mgit/.manifest.json")) assert os.path.exists(dot_meta("mgit/.foo")) assert os.path.exists(dot_meta("mgit/mgit-0.0.2")) assert not os.path.exists(dot_meta("mgit/mgit-foo")) assert not os.path.exists(dot_meta("mgit/mgit-0.0.1")) cfg = PickleyConfig() cfg.set_base(".") pspec = PackageSpec(cfg, "mgit") pspec.groom_installation(keep_for=0) assert not os.path.exists(dot_meta("mgit/mgit-0.0.2")) cli.expect_success("uninstall mgit", "Uninstalled mgit") assert not runez.is_executable("mgit") assert not os.path.exists(dot_meta("mgit")) assert os.path.exists(dot_meta("audit.log")) check_install_from_pypi(cli, "wrap", "mgit", simulate_version="0.0.0") check_is_wrapper("mgit", True)
def test_bogus_install(cli): cli.expect_failure("-b foo/bar settings", "Can't use foo/bar as base: folder does not exist") 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("-b{base} check", "No packages installed", base=cli.context) cli.expect_success("-b{base} list", "No packages installed", base=cli.context) cli.expect_success("settings -d", "base: %s" % short(cli.context))
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_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()
def test_edge_cases(): # Don't crash for no-ops 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.delete("non-existing") == 0 assert runez.touch(None) == 0 assert not runez.file.is_younger("", None) assert not runez.file.is_younger("", 1) assert not runez.file.is_younger("/dev/null/not-there", 1)
def test_executable(temp_folder): with runez.CaptureOutput(dryrun=True) as logged: assert runez.make_executable("some-file") == 1 assert "Would make some-file executable" in logged.pop() assert runez.make_executable("some-file", logger=False) == 1 assert not logged with runez.CaptureOutput() as logged: assert runez.touch("some-file") == 1 assert "Touched some-file" in logged.pop() assert runez.delete("some-file") == 1 assert "Deleted some-file" in logged.pop() assert runez.touch("some-file", logger=logging.debug) == 1 assert "Touched some-file" in logged.pop() assert runez.make_executable("some-file", logger=logging.debug) == 1 assert "Made 'some-file' executable" in logged.pop() assert runez.is_executable("some-file") assert runez.make_executable("some-file") == 0 assert not logged assert runez.touch("some-file", logger=False) == 1 assert runez.delete("some-file", logger=False) == 1 assert not runez.is_executable("some-file") assert not logged assert runez.make_executable("/dev/null/some-file", fatal=False) == -1 assert "does not exist, can't make it executable" in logged.pop() assert runez.make_executable("/dev/null/some-file", fatal=False, logger=None) == -1 # Don't log anything assert not logged assert runez.make_executable("/dev/null/some-file", fatal=False, logger=False) == -1 # Log errors only assert "does not exist, can't make it executable" in logged.pop()
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")
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 test_executable(temp_folder): with runez.CaptureOutput(dryrun=True) as logged: assert runez.make_executable("some-file") == 1 assert "Would make some-file executable" in logged assert runez.touch("some-file") == 1 assert runez.make_executable("some-file") == 1 assert runez.is_executable("some-file") assert runez.make_executable("some-file") == 0 assert runez.delete("some-file") == 1 assert not runez.is_executable("some-file") with runez.CaptureOutput() as logged: assert runez.make_executable("/dev/null/some-file", fatal=False) == -1 assert "does not exist, can't make it executable" in logged
def test_delivery(temp_base): # Test copy folder tox = system.PackageSpec("tox") deliver = DELIVERERS.get("copy")(tox) target = os.path.join(temp_base, "t1") source = os.path.join(temp_base, "t1-source") source_file = os.path.join(source, "foo") runez.touch(source_file) deliver.install(target, source) assert os.path.isdir(target) assert os.path.isfile(os.path.join(target, "foo")) # Test copy file deliver = DELIVERERS.get("copy")(tox) target = os.path.join(temp_base, "t2") source = os.path.join(temp_base, "t2-source") runez.touch(source) deliver.install(target, source) assert os.path.isfile(target) # Test symlink deliver = DELIVERERS.get("symlink")(tox) target = os.path.join(temp_base, "l2") source = os.path.join(temp_base, "l2-source") runez.touch(source) deliver.install(target, source) assert os.path.islink(target) # Test wrapper p = PACKAGERS.get(system.VENV_PACKAGER)(tox) assert p.create_symlinks(None) == 0 assert p.create_symlinks("foo", fatal=False) == 0 p.executables = ["foo"] assert p.create_symlinks("foo:bar", fatal=False) == -1 assert str(p) == "venv tox" target = os.path.join(temp_base, "tox") source = os.path.join(temp_base, "tox-source") runez.touch(source) deliver = DELIVERERS.get("wrap")(system.PackageSpec("tox")) deliver.install(target, source) assert runez.is_executable(target)
def test_edge_cases(temp_cfg, monkeypatch, logged): monkeypatch.setattr(PickleyConfig, "_pickley_dev_path", None) pspec = PackageSpec(temp_cfg, PICKLEY) assert pspec._pickley_dev_mode == runez.DEV.project_folder assert pspec.install_path.endswith("%s-dev" % PICKLEY) assert pspec.find_wheel(".", fatal=False) is None assert "Expecting 1 wheel" in logged.pop() runez.touch("%s-1.0.0.whl" % PICKLEY) w = pspec.find_wheel(".", fatal=False) assert w == "./%s-1.0.0.whl" % PICKLEY with pytest.raises(NotImplementedError): Packager.package(None, None, None, None, False) runez.touch("share/python-wheels/some-wheel.whl") runez.touch("__pycache__/some_module.py") runez.touch("some_module.pyc") logged.pop() clean_compiled_artifacts(".") assert "Deleted 3 compiled artifacts" in logged.pop() assert not os.path.exists("share/python-wheels") assert os.path.isdir("share")
def test_dryrun(cli, monkeypatch): cli.run("-n --debug auto-upgrade mgit") assert cli.succeeded assert "Would wrap mgit" in cli.logged runez.touch(dot_meta("mgit.lock")) cli.run("-n --debug auto-upgrade mgit") assert cli.succeeded assert "Lock file present, another installation is in progress" in cli.logged cli.expect_success("-n check", "No packages installed") cli.expect_failure("-n check foo+bar", "'foo+bar' is not a valid pypi package name") cli.expect_failure("-n check mgit pickley2-a", "is not installed", "pickley2-a: does not exist") cli.run("-n config") assert cli.succeeded assert not cli.logged.stderr assert "cli: # empty" in cli.logged.stdout assert "defaults:" in cli.logged.stdout cli.run("-n --color config") assert cli.succeeded cli.expect_failure("-n -Pfoo install bundle:bar", "No suitable python") # Simulate an old entry point that was now removed runez.write(dot_meta("mgit/.manifest.json"), '{"entrypoints": ["bogus-mgit"]}') cli.expect_failure("-n install mgit pickley2.a", "Would state: Installed mgit v", "'pickley2.a' is not pypi canonical") runez.delete(dot_meta("mgit")) cli.expect_success("-n -Pfoo diagnostics", "desired python : foo", "foo [not available]", "sys.executable") with patch("runez.run", return_value=runez.program.RunResult("failed")): cli.run("-n install [email protected]:zsimic/mgit.git") assert cli.failed assert cli.match("No setup.py") with patch("pickley.git_clone", side_effect=mock_git_clone): cli.run("-n install [email protected]:zsimic/mgit.git") assert cli.succeeded assert " install .pickley/.cache/checkout/mgit" in cli.logged cli.run("-n install mgit") assert cli.succeeded assert cli.match("Would wrap mgit -> %s" % dot_meta("mgit")) assert cli.match("Would save %s" % dot_meta("mgit/.manifest.json")) assert cli.match("Would state: Installed mgit v") cli.expect_failure("-n -dfoo install mgit", "Unknown delivery method 'foo'") cli.expect_success("-n list", "No packages installed") cli.expect_failure("-n package foo", "Folder ... does not exist") cli.expect_failure("-n package . -sfoo", "Invalid symlink specification") cli.expect_failure("-n package . -sroot:root/usr/local/bin", "No setup.py in ") runez.touch("setup.py") cli.expect_failure("-n package .", "Could not determine package name") runez.write( "setup.py", "import sys\nfrom setuptools import setup\nif sys.argv[1]=='--version': sys.exit(1)\nsetup(name='foo')" ) cli.expect_failure("-n package .", "Could not determine package version") cli.expect_success(["-n", "package", cli.project_folder], "Would run: ...pip... install -r requirements.txt") cli.expect_failure("-n uninstall", "Specify packages to uninstall, or --all") cli.expect_failure( "-n uninstall pickley", "Run 'uninstall --all' if you wish to uninstall pickley itself") cli.expect_failure("-n uninstall mgit", "mgit was not installed with pickley") cli.expect_failure( "-n uninstall mgit --all", "Either specify packages to uninstall, or --all (but not both)") cli.expect_success("-n uninstall --all", "pickley is now uninstalled") cli.expect_success("-n upgrade", "No packages installed, nothing to upgrade") cli.expect_failure("-n upgrade mgit", "'mgit' is not installed")
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")
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")
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_python_installation(_, __, ___, ____, temp_base): system.DESIRED_PYTHON = "/dev/null/foo" p = system.target_python(fatal=False) assert not p.is_valid assert p.shebang() == "/dev/null/foo" system.DESIRED_PYTHON = None assert system.target_python(fatal=False).is_valid assert not system.PythonInstallation("").is_valid p = system.PythonInstallation("foo") assert str(p) == "python 'foo'" assert not p.is_valid assert p.problem == "No python installation 'foo' found" assert p.program_name == "python 'foo'" p = system.PythonInstallation("pythonx") assert not p.is_valid # assert p.problem == "pythonx is not installed" assert p.program_name == "pythonx" p = system.PythonInstallation("/usr/bin/python") assert str(p) == "/usr/bin/python [2.7]" assert p.is_valid assert p.problem is None assert p.program_name == "python2.7" assert p.short_name == "py27" assert p.executable == "/usr/bin/python" assert p.shebang(universal=True) == "/usr/bin/env python" assert p.shebang() == "/usr/bin/python" p = system.PythonInstallation("3.6") assert str(p) == "/test/python3.6/bin/python [3.6]" assert p.is_valid assert p.problem is None assert p.program_name == "python3.6" assert p.short_name == "py36" assert p.executable == "/test/python3.6/bin/python" assert p.shebang() == "/usr/bin/env python3.6" system.SETTINGS.cli.contents["python_installs"] = temp_base runez.touch("foo") runez.touch("python3.5") runez.touch("python3.7") p = system.PythonInstallation("python3") assert not p.is_valid assert p.problem == "'/test/python3' is not a valid python installation" assert p.program_name == "python3" p = system.PythonInstallation("py3.7") assert not p.is_valid assert p.problem == "python3.7 is not installed" runez.delete("python3.7") runez.touch("3.7.0/bin/python") runez.make_executable("3.7.0/bin/python") p = system.PythonInstallation("3.7") assert p.is_valid assert p.short_name == "py37" assert p.executable == os.path.join(temp_base, "3.7.0/bin/python")
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_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)