def test_get_input_from_console_eof_error() -> None: program = console.get_input_from_console( prompt="How much wood would a woodchuck chuck?", parse_value=ZIO.from_callable(str).map(int).catch( ValueError).either().to_callable(), default_value=None) exception = EOFError() mock_console = MockConsole(["bad", "input", exception]) mock_system = MockSystem() with pytest.raises(SystemExit): unsafe_run( program.provide( ConsoleSystemEnvironment(console=mock_console, system=mock_system))) assert mock_console.effects == [ console_effect.Input("How much wood would a woodchuck chuck?", "bad"), console_effect.Input("How much wood would a woodchuck chuck?", "input"), console_effect.Input("How much wood would a woodchuck chuck?", exception), console_effect.Print("") ] assert mock_console.user_input == [] assert mock_system.effects == [system_effect.Exit(None)]
def test_from_callable() -> None: def _f(arg_1: int, arg_2: str, *, arg_3: float) -> str: return f"{arg_1} {arg_2} {arg_3}" program = ZIO.from_callable(_f) assert unsafe_run(program.provide(FunctionArguments( 42, "foo", arg_3=3.14))) == "42 foo 3.14"
def ask(self, prompt: str, default: Literal['y', 'n'], do: ZIOMonad[System, NoReturn]) -> ZIO[System, NoReturn, bool]: default_str = 'Y/n' if default == 'y' else 'y/N' choice = do << self.get_input_from_console( prompt=f"{prompt} [{default_str}]: ", parse_value=(ZIO.from_callable(str).map(str.lower).require( lambda s: s in {'y', 'n'}, lambda s: s).either().to_callable()), default_value=default) return ZIO.succeed(choice == 'y')
def prog( do: ZIOMonad[ConsoleSystemEnvironment, NoReturn] ) -> ZIO[ConsoleSystemEnvironment, NoReturn, int]: age = do << console.get_input_from_console( prompt="How old are you?\n", parse_value=ZIO.from_callable(str).map(int).catch( ValueError).either().to_callable(), default_value=21) do << console.print(f"You are {age} years old.") return ZIO.succeed(age)
def test_from_to_callable_1() -> None: class Cat: def meow(self, *, volume: int) -> str: if volume < 10: return "meow" else: return "MEOW!" meow_to_callable = (Environment[Cat]().map(lambda cat: ZIO.from_callable( cat.meow)).swap_environments().to_callable()) assert unsafe_run(meow_to_callable(volume=11).provide(Cat())) == "MEOW!"
def test_from_to_callable_2() -> None: @dataclass(frozen=True) class SomeException(Exception): message: str class SomeAPI: def thing_that_may_fail(self, *, bippy: str) -> int: raise SomeException("Murphy's Law") safer_thing = (Environment[SomeAPI]().map( lambda api: (ZIO.from_callable(api.thing_that_may_fail).catch( SomeException).either())).swap_environments().to_callable()) assert unsafe_run(safer_thing(bippy="bippy").provide(SomeAPI())) == Left( SomeException("Murphy's Law"))
def test_get_input_from_console_1() -> None: program = console.get_input_from_console( prompt="How much wood would a woodchuck chuck?", parse_value=ZIO.from_callable(str).map(int).catch( ValueError).either().to_callable(), default_value=None) mock_console = MockConsole(["42"]) mock_system = MockSystem() output = unsafe_run( program.provide( ConsoleSystemEnvironment(console=mock_console, system=mock_system))) assert output == 42 assert mock_console.effects == [ console_effect.Input("How much wood would a woodchuck chuck?", "42") ] assert mock_console.user_input == []
def effects( self) -> List[Union[console_effect.Print, console_effect.Input]]: return self._effects @property def user_input(self) -> List[Union[EOFError, KeyboardInterrupt, str]]: return self._user_input class HasConsole(Protocol): @property def console(self) -> Console: pass # pragma: nocover print = (Environment[HasConsole]().map(lambda env: ZIO.from_callable( env.console.print).flatten()).swap_environments().to_callable()) input = (Environment[HasConsole]().map(lambda env: ZIO.from_callable( env.console.input).flatten()).swap_environments().to_callable()) class HasConsoleSystem(HasConsole, HasSystem, Protocol): pass def get_input_from_console( prompt: str, parse_value: Callable[[str], Either[E, A]], default_value: Optional[A]) -> ZIO[HasConsoleSystem, NoReturn, A]: return (Environment[HasConsoleSystem] ().flat_map(lambda env: env.console.get_input_from_console( prompt, parse_value, default_value).provide(env.system)))
def test_to_callable() -> None: def _f(arg_1: int, arg_2: str, *, arg_3: float) -> str: return f"{arg_1} {arg_2} {arg_3}" g = ZIO.from_callable(_f).to_callable() assert g(42, "foo", arg_3=3.14) == "42 foo 3.14"