def test_same_child_names(self, envo_prompt, init_2_same_childs): root_dir = Path(".").absolute() os.chdir(root_dir / "sandbox/sandbox") nested_prompt = envo_prompt.replace(b"sandbox", b"sandbox.sandbox.sandbox") utils.shell(nested_prompt)
def test_decorator_kwargs_validation(self, envo_prompt): utils.add_command(""" @command(unexistent_arg1=False, unexistent_arg2=False, prop=True) def flake(self) -> None: print("Flake all good") return "Flake return value" """) utils.shell( envo_prompt.replace( r"🛠\(sandbox\)".encode("utf-8"), r"got an unexpected keyword argument.*❌".encode("utf-8"), ))
def test_fun_args_validation_missing_arg(self, envo_prompt): utils.add_hook(r""" @precmd(cmd_regex=r"print\(.*\)") def pre_print(self) -> str: print("test") return "cmd" """) utils.shell( envo_prompt.replace( r"🛠\(sandbox\)".encode("utf-8"), r"Missing magic function args \['command'\].*" r"pre_print\(\) -> str.*" r'In file ".*".*' r"Line number: \d\d.*.*❌".encode("utf-8"), ))
def test_multiple_contexts(self): context1 = { "str_var1": "str test1 value", "int_var1": 8, } utils.add_context(context1, name="context1") context2 = { "str_var2": "str test2 value", "int_var2": 28, } utils.add_context(context2, name="context2") s = utils.shell() s.sendline("print(str_var1)") s.expect(r"str test1 value") s.sendline("print(int_var1)") s.expect(r"8") s.sendline("print(str_var2)") s.expect(r"str test2 value") s.sendline("print(int_var2)") s.expect(r"28")
def test_fun_args_validation(self, envo_prompt): utils.add_hook(r""" @precmd(cmd_regex=r"print\(.*\)") def pre_print(self, cmd: str) -> str: assert command == 'print("pancake");' print("pre") return command * 2 """) utils.shell( envo_prompt.replace( r"🛠\(sandbox\)".encode("utf-8"), r"Unexpected magic function args \['cmd'\], should be \['command'\].*" r"pre_print\(cmd: str\) -> str.*" r'In file ".*".*' r"Line number: \d\d.*.*❌".encode("utf-8"), ))
def test_contexts_inheritance(self): context1 = { "str_var1": "str test1 value", "int_var1": 8, "other_var": "other var value", } utils.add_context(context1, name="context1") context2 = { "str_var2": "str test2 value", "str_var1": "str test1 new value", "int_var2": 28, } utils.add_context(context2, name="context2", file=Path("env_test.py")) s = utils.shell() s.sendline("print(str_var1)") s.expect(r"str test1 new value") s.sendline("print(int_var1)") s.expect(r"8") s.sendline("print(str_var2)") s.expect(r"str test2 value") s.sendline("print(int_var2)") s.expect(r"28") s.sendline("print(other_var)") s.expect(r"other var value")
def test_command_no_prop_no_glob(self, envo_prompt): utils.flake_cmd(prop=False, glob=False) utils.mypy_cmd(prop=False, glob=False) s = utils.shell() s.sendline("repr(env.flake)") s.expect(r"Command\(name=\\'flake\\', type=\\'command\\'") s.expect(envo_prompt) s.sendline("env.flake()") s.expect("Flake all good") s.expect("Flake return value") s.expect(envo_prompt) s.sendline("env.mypy()") s.expect("Mypy all good") s.expect(envo_prompt) s.sendline("flake") s.expect("not found") s.expect(envo_prompt) s.sendline("flake()") s.expect("NameError: name 'flake' is not defined") s.expect(envo_prompt)
def test_cmd_without_args(self, envo_prompt): utils.add_command(""" @command def flake(self) -> None: print("Flake all good") return "Flake return value" """) s = utils.shell() s.sendline("repr(env.flake)") s.expect("Flake all good") s.expect("Flake return value") s.expect(envo_prompt) s.sendline("env.flake()") s.expect("Flake all good") s.expect("Flake return value") s.expect(envo_prompt) s.sendline("flake") s.expect("Flake all good") s.expect("Flake return value") s.expect(envo_prompt) s.sendline("flake()") s.expect("Flake all good") s.expect("Flake return value") s.expect(envo_prompt)
def test_multiple_instances(self, envo_prompt): shells = [utils.shell() for i in range(6)] new_content = Path("env_comm.py").read_text() + "\n" utils.change_file(Path("env_comm.py"), 0.5, new_content) [s.expect(envo_prompt, timeout=10) for s in shells]
def test_cmd_execution_with_args(self, envo_prompt): utils.flake_cmd(prop=True, glob=True) s = utils.shell() s.sendline('flake("dd")') s.expect("Flake all gooddd") s.expect("Flake return value") s.expect(envo_prompt)
def test_venv_addon(self): Path("env_comm.py").unlink() Path("env_test.py").unlink() utils.run("poetry run python -m venv .venv") utils.run("./.venv/bin/pip install rhei==0.5.2") utils.run("envo test --init=venv") s = utils.shell() s.sendline("import rhei") s.sendline("print(rhei.stopwatch)") s.expect(r"module 'rhei\.stopwatch'")
def test_autodiscovery(self, envo_prompt): Path("./test_dir").mkdir() os.chdir("./test_dir") s = utils.shell() s.sendline("print('test')") s.expect(b"test") s.expect(envo_prompt) s.sendcontrol("d") assert list(Path(".").glob(".*")) == []
def test_precmd_access_env_vars(self): utils.add_hook(r""" @precmd(cmd_regex=r"print\(.*\)") def pre_print(self, command: str) -> str: print(self.stage); return command """) s = utils.shell() s.sendline('print("pancake");') s.expect(r"test\r\n") s.expect(r"pancake\r\n")
def test_onstdout(self): utils.add_hook(r""" @onstdout(cmd_regex=r"print\(.*\)") def on_print(self, command: str, out: str) -> str: assert command == 'print("pancake");print("banana")' return " sweet " + out """) s = utils.shell() s.sendline('print("pancake");print("banana")') s.expect(r" sweet pancake sweet \r\n") s.expect(r" sweet banana sweet \r\n")
def test_onstderr(self): utils.add_hook(r""" @onstderr(cmd_regex=r"print\(.*\)") def post_print(self, command: str, out: str) -> str: print("not good :/") print(out) return "" """) s = utils.shell() s.sendline("print(1/0)") s.expect(r"not good :/") s.expect(r"ZeroDivisionError: division by zero")
def test_precmd_print_and_modify(self): utils.add_hook(r""" @precmd(cmd_regex=r"print\(.*\)") def pre_print(self, command: str) -> str: assert command == 'print("pancake");' print("pre") return command * 2 """) s = utils.shell() s.sendline('print("pancake");') s.expect(r"pre\r\n") s.expect(r"pancake\r\n") s.expect(r"pancake\r\n")
def test_post_hook_print(self): utils.add_hook(r""" @postcmd(cmd_regex=r"print\(.*\)") def post_print(self, command: str, stdout: List[str], stderr: List[str]) -> None: assert command == 'print("pancake");print("banana")' assert stderr == [] assert stdout == ["pancake", "\n", "banana", "\n"] print("post") """) s = utils.shell() s.sendline('print("pancake");print("banana")') s.expect(r"pancake\r\n") s.expect(r"banana\r\n") s.expect(r"post\r\n")
def test_precmd_not_matching_not_run(self): utils.add_hook(r""" @precmd(cmd_regex=r"some_cmd\(.*\)") def pre_cmd(self, command: str) -> str: print("pre") return command """) s = utils.shell() s.sendline('print("pancake");') with pytest.raises(TIMEOUT): s.expect(r"pre\r\n", timeout=0.5) s.expect(r"pancake\r\n")
def test_cmd_in_non_root_dir(self, envo_prompt): utils.add_command(""" @command(glob=True, prop=True) def flake(self) -> None: print("flake good") """) s = utils.shell() child_dir = Path("child_dir") child_dir.mkdir() os.chdir(str(child_dir)) s.sendline("flake") s.expect("flake good") s.expect(envo_prompt)
def test_child_importable(self, envo_prompt, init_child_env): Path("__init__.py").touch() os.chdir("child") Path("__init__.py").touch() nested_prompt = envo_prompt.replace(b"sandbox", b"sandbox.child") s = utils.shell(nested_prompt) test_script = Path("test_script.py") content = "from env_test import Env\n" content += "env = Env()\n" content += 'print("ok")\n' test_script.write_text(content) s.sendline("python3 test_script.py") s.expect("ok")
def test_onload_onunload_reload(self, envo_prompt): utils.add_hook(r""" @onload def init_sth(self) -> None: print("on load") @onunload def deinit_sth(self) -> None: print("on unload") """) s = utils.shell(rb"on load.*" + envo_prompt) Path("env_comm.py").write_text(Path("env_comm.py").read_text()) s.expect(r"on unload") s.expect(r"on load") s.sendcontrol("d") s.expect(r"on unload") s.expect(EOF)
def test_simple_context(self): context = { "str_var": "str test value", "int_var": 8, "dict_var": { "nested_var": "some nested value" }, } utils.add_context(context) s = utils.shell() s.sendline("print(str_var)") s.expect(r"str test value") s.sendline("print(int_var)") s.expect(r"8") s.sendline('print(dict_var["nested_var"])') s.expect(r"some nested value")
def test_onload_onunload_hook(self, envo_prompt): utils.add_hook(r""" @oncreate def on_create(self) -> None: print("on create") @onload def init_sth(self) -> None: print("on load") @onunload def deinit_sth(self) -> None: print("on unload") @ondestroy def on_destroy(self) -> None: print("on destroy") """) s = utils.shell(rb"on create.*on load.*" + envo_prompt) s.sendcontrol("d") s.expect(r"on unload") s.expect(r"on destroy") s.expect(EOF)
def test_hot_reload(self, envo_prompt, init_child_env): os.chdir("child") nested_prompt = envo_prompt.replace(b"sandbox", b"sandbox.child") s = utils.shell(nested_prompt) child_file = Path("env_comm.py") content = child_file.read_text() content = content.replace("child", "ch") child_file.write_text(content) new_prompt1 = nested_prompt.replace(b"child", b"ch") s.expect(new_prompt1) parent_file = Path("../env_comm.py") content = parent_file.read_text() content = content.replace("sandbox", "sb") parent_file.write_text(content) new_prompt2 = new_prompt1.replace(b"sandbox", b"sb") s.expect(new_prompt2)
def test_command_prop_glob(self, envo_prompt): utils.flake_cmd(prop=True, glob=True) utils.mypy_cmd(prop=True, glob=True) s = utils.shell() s.sendline("repr(env.flake)") s.expect("Flake all good") s.expect("Flake return value") s.expect(envo_prompt) s.sendline("repr(env.mypy)") s.expect("Mypy all good") s.expect(envo_prompt) s.sendline("env.flake()") s.expect("Flake all good") s.expect("Flake return value") s.expect(envo_prompt) s.sendline("env.mypy()") s.expect("Mypy all good") s.expect(envo_prompt) s.sendline("flake") s.expect("Flake all good") s.expect("Flake return value") s.expect(envo_prompt) s.sendline("mypy") s.expect("Mypy all good") s.expect(envo_prompt) s.sendline("flake()") s.expect("Flake all good") s.expect("Flake return value") s.expect(envo_prompt) s.sendline("mypy()") s.expect("Mypy all good") s.expect(envo_prompt)
def test_if_reproductible(self, envo_prompt): os.environ["PATH"] = "/already_existing_path:" + os.environ["PATH"] shell = utils.shell() utils.add_declaration("path: Raw[str]") utils.add_definition( """ import os self.path = os.environ["PATH"] self.path = "/some_path:" + self.path """ ) Path("env_comm.py").write_text(Path("env_comm.py").read_text() + "\n") time.sleep(0.2) Path("env_comm.py").write_text(Path("env_comm.py").read_text() + "\n") time.sleep(0.2) Path("env_comm.py").write_text(Path("env_comm.py").read_text() + "\n") time.sleep(0.2) shell.sendline("print($PATH)") time.sleep(0.5) shell.expect(r"\['/some_path', '/already_existing_path'.*\]", timeout=2)
def test_slow_context(self, envo_prompt): utils.add_command(""" @context def some_context(self) -> Dict[str, Any]: from time import sleep sleep(1) return {"slow_var": "slow var value"} """) s = utils.shell("⏳".encode("utf-8") + envo_prompt) s.sendline("print(slow_var)") s.expect(r"is not defined") sleep(1) s.sendline("print(slow_var)") s.expect(r"slow var value") from pexpect import TIMEOUT with pytest.raises(TIMEOUT): s.expect("⏳".encode("utf-8") + envo_prompt, timeout=0.1) s.expect(envo_prompt)
def test_init(self, envo_prompt, init_child_env): os.chdir("child") nested_prompt = envo_prompt.replace(b"sandbox", b"sandbox.child") utils.shell(nested_prompt)
def shell() -> pexpect.spawn: from tests.e2e.utils import shell return shell()