def eff_map(self): a, b = self._r c = -1 t = Right(List(Just(Right(a)), Just(Left(c)), Empty())) target = Right(List(Just(Right(a + b)), Just(Left(c)), Empty())) res = t.effs(3).map(_ + b) res.value.should.equal(target)
def read_result(result: TmuxCmdResult) -> Either[List[str], List[str]]: return ( Right(result.output.output) if isinstance(result, TmuxCmdSuccess) else Left(result.output.output.cons(f'tmux command {result.cmd} failed:')) if isinstance(result, TmuxCmdError) else Left( result.output.output.cons( f'fatal tmux command execution in {result.cmds}:')))
def optional(self) -> None: a = 'a' b = 'b' Maybe.optional(a).to_maybe.should.just_contain(a) Empty().to_maybe.should.be.a(Empty) Maybe.optional(a).to_either(b).should.equal(Right(a)) Empty().to_either(b).should.equal(Left(b)) Empty().to_either(lambda: b).should.equal(Left(b))
def dispatch_command(self, client, cmd_name, params): try: command = getattr(client, cmd_name) except AttributeError: return Left('No such command: {}'.format(cmd_name)) else: try: return command(*params) except TypeError as e: return Left(e)
def decode(self, tpe: Type[Mapping], data: Json) -> Either[JsonError, Map[str, A]]: def dec() -> Either[JsonError, Map[str, A]]: return Map(data.data).traverse(decode.match, Either) return data.object.c(dec, lambda: Left(f'invalid type for `Map`: {data}'))
def decode(self, tpe: Type[Collection], data: Json) -> Either[JsonError, List[A]]: def dec() -> Either[JsonError, List[A]]: return Lists.wrap(data.data).traverse(decode.match, Either) return data.array.c(dec, lambda: Left(f'invalid type for `List`: {data}'))
def decode_instance(data: Json, desc: str) -> Either[JsonError, A]: @do(Either[JsonError, A]) def run(data: Json) -> Do: type_info = yield decode_json_type_json(data, TypeInfo) yield select_type(type_info) return (run(data) if data.object else Left( JsonError(data, f'invalid type for `{desc}`')))
def parse_magnet(magnet) -> Either[str, Magnet]: pr = urlparse(magnet) if pr.scheme == 'magnet': q = Map(parse_qs(pr.query)).valmap(List.wrap) name = q.get('dn') // _.head return Right(Magnet(name, q)) else: return Left('not a magnet')
def type_arg(tpe: type, index: int) -> Do: def error() -> str: return f'{tpe} has no type args' raw = yield Maybe.getattr(tpe, '__args__').to_either_f(error) types = yield Right(Lists.wrap(raw)) if isinstance( raw, Iterable) else Left(error()) yield types.lift(index).to_either_f( lambda: f'{tpe} has less than {index + 1} args')
def run(data: Json) -> Do: mod_field = yield data.field('mod') mod_path = yield mod_field.as_scalar names_field = yield data.field('names') names_json = yield names_field.as_array names = Lists.wrap(names_json.native) mod = yield (Either.import_module(mod_path.native) if isinstance( mod_path.native, str) else Left( JsonError(data, 'module is not a string'))) yield names.fold_m(Right(mod))(Either.getattr)
def decode_instance(data: Json, desc: str) -> Either[JsonError, A]: @do(Either[JsonError, A]) def run(data: Json) -> Do: mod_field = yield data.field('mod') mod_path = yield mod_field.as_scalar names_field = yield data.field('names') names_json = yield names_field.as_array names = Lists.wrap(names_json.native) mod = yield (Either.import_module(mod_path.native) if isinstance( mod_path.native, str) else Left( JsonError(data, 'module is not a string'))) yield names.fold_m(Right(mod))(Either.getattr) return (run(data) if data.object else Left( JsonError(data, f'invalid type for `{desc}`')))
def decode(self, tpe: Type[Collection], data: Json) -> Either[JsonError, List[A]]: tpe_decoder = list_type_decoder(tpe) def dec_tpe(a: Json, err: str) -> Either[JsonError, A]: return (tpe_decoder.map2(lambda t, dec: dec.decode(t, a)).get_or( lambda: Left( JsonError(a, f'{err} and no type information is available') ))) def dec_elem(a: Json) -> Either[JsonError, A]: return decode.match(a).recover_with( lambda err: dec_tpe(a, err.error)) def dec() -> Either[JsonError, List[A]]: return Lists.wrap(data.data).traverse(dec_elem, Either) return data.array.c(dec, lambda: Left(f'invalid type for `List`: {data}'))
def e(self) -> Either[str, Node]: return Left(self._error)
def recover(est: EitherState[str, Files, Entry]) -> State[Map, Either[str, Entry]]: def fix(s: Map, r: Map) -> Id[Tuple[Map, Either[str, Map]]]: return Id((s, Right(r))) return State.apply(lambda s: est.run(s).map2(fix).value_or(lambda err: Id((s, Left(err)))))
def ensure_ident(spec: IdentSpec) -> Either[str, Ident]: return (Right(spec) if isinstance(spec, Ident) else Right(UUIDIdent(spec)) if isinstance(spec, UUID) else Right(StrIdent(spec)) if isinstance(spec, str) else Right(KeyIdent(spec)) if isinstance( spec, Key) else Left(f'invalid ident spec: {spec}'))
def as_object(self) -> Either[JsonError, 'JsonObject']: return Right(self) if self.object else Left( self.error('not an object'))
def field(self, key: str) -> Either[JsonError, Json]: return Left(self.error('JsonArray has no fields'))
def parse_bool(data: str) -> Do: as_int = yield parse_int(data) yield (Right(as_int == 1) if as_int in [0, 1] else Left(f'invalid number for boolean: {as_int}'))
def parse_int(i): return Right(i) if isinstance( i, int) else (Right(int(i)) if isinstance(i, str) and i.isdigit() else Left('could not parse int {}'.format(i)))
def decode(self, tpe: Type[Either], data: Json) -> Do: err = JsonError(data, f'too few types in Either') ltype, rtype = yield Lists.wrap(tpe.__args__).lift_all( 0, 1).to_either(err) yield (either_from_object(data, ltype, rtype) if data.object else Left( JsonError(data, f'invalid type for `Either`')))
def to_either(self) -> Either[Exception, A]: return Left(self.exception)
def either(self, tmux: Tmux) -> Either[TmuxIOException, A]: try: return self.run(tmux).to_either except TmuxIOException as e: return Left(e)
def Try(f: Callable[..., A], *a: Any, **kw: Any) -> Either[Exception, A]: try: return Right(f(*a, **kw)) except Exception as e: return Left(e)
def _attempt(self) -> Either[IOException, A]: try: return Right(self.run()) except IOException as e: return Left(e)
def to_either(self) -> Either[Exception, A]: return Left(Exception(self.error))
def as_scalar(self) -> Either[JsonError, 'JsonScalar']: return Right(self) if self.scalar else Left(self.error('not a scalar'))
def failed(self, err: B) -> 'StateT[Either, S, A]': return EitherState.lift(Left(err))
def as_array(self) -> Either[JsonError, 'JsonArray']: return Right(self) if self.array else Left(self.error('not an array'))
def eff_flat_io_left(self): a, b = self._r t = IO.now(Left(Just(a))) target = Left(Just(a)) res = t.effs(1, Either, Maybe) // (lambda x: IO.now(Right(Just(b)))) res.value.run().should.equal(target)
def optional(self) -> None: r = Regex('(?P<path>.*?\.py)(:(?P<lnum>\d+))?$') m = r.match('/foo/bar/file.py') m.should.be.right m.value.group('lnum').should.equal(Left('group `lnum` did not match'))