def get_fact_result(self) -> Result[str, Exception]: """Return a Result for a cat fact.""" return ( Result.of( requests.get, "https://cat-fact.herokuapp.com/facts/random", # this is the default, but sometimes the type checker wants us # to make it explicit. See python/mypy#3737 for deets. catch=Exception, ) .and_then(lambda resp: Result.of(resp.json)) .map( lambda parsed: t.cast( str, parsed.get("text", "Unexpected cat fact format!") ) ) )
def get_fact(self) -> str: """Get a cat fact!""" return ( # Create a Result from making our GET request. # Now we can start chaining! Result.of( requests.get, "https://cat-fact.herokuapp.com/facts/random" ) # Let's first consider the success path. # If we got a response, it should be JSON, so let's try to parse .and_then(lambda resp: Result.of(resp.json)) # If we successfully parsed JSON, we must have a dict, so let's # grab our cat fact, or a useful message. .map( lambda parsed: t.cast( str, parsed.get("text", "Unexpected cat fact format!") ) ) # From here, all we need to do to consider the error case is # convert our Err type (which for Result.of() is any exception # that was raised) into the expected return type, which we # do by passing the error to `str()` .unwrap_or_else(str) )
def test_of_with_kwargs(self) -> None: """Test getting a result from a callable with args.""" def foo(a: int, b: str = None) -> t.Optional[str]: return b assert Result.of(foo, 1, b="a").unwrap() == "a"
def test_of_with_args(self) -> None: """Test getting a result from a callable with args.""" assert Result.of(lambda x: bool(x > 0), 1).unwrap() is True
def test_of(self, fn: t.Callable, exp: Result) -> None: """Test getting a result from a callable.""" if exp.is_err(): assert isinstance(Result.of(fn).unwrap_err(), exp.unwrap_err()) else: assert Result.of(fn) == exp