def is_handler(name: str, f: Callable) -> Do: effective = getattr(f, '__do_original', f) spec = yield Try(inspect.getfullargspec, effective).to_maybe param_name = yield Lists.wrap(spec.args).lift(1) param_type = yield Map(spec.annotations).lift(param_name) yield (Just((normalize_type(param_type), f)) if issubclass(param_type, alg) else Nothing)
def object_from_module(mod: ModuleType, pred: Callable[[Any], bool], desc: str) -> Do: all = yield Maybe.getattr(mod, '__all__').to_either( f'module `{mod.__name__}` does not define `__all__`') yield (Lists.wrap(all).flat_map(L(Maybe.getattr)( mod, _)).find(pred).to_either(f'no {desc} in `{mod.__name__}.__all__`'))
def case_list( cls: Type[Case[C, B]], variants: List[Type[C]], alg: Type[C], has_default: bool, ) -> Map[Type[C], Callable[[Case[C, B]], B]]: @do(Maybe[Tuple[Type[C], Callable[[Case[C, B]], B]]]) def is_handler(name: str, f: Callable) -> Do: effective = getattr(f, '__do_original', f) spec = yield Try(inspect.getfullargspec, effective).to_maybe param_name = yield Lists.wrap(spec.args).lift(1) param_type = yield Map(spec.annotations).lift(param_name) yield (Just((normalize_type(param_type), f)) if issubclass(param_type, alg) else Nothing) handlers = Lists.wrap(inspect.getmembers( cls, inspect.isfunction)).flat_map2(is_handler) def find_handler(variant: Type[C]) -> Callable[[Case[C, B]], B]: def not_found() -> None: if not has_default: raise Exception( f'no case defined for {variant} on {cls.__name__}') def match_handler(tpe: type, f: Callable) -> Maybe[Callable[[Case[C, B]], B]]: return Just(f) if issubclass(tpe, variant) else Nothing return handlers.find_map2(match_handler).get_or_else(not_found) return variants.map(find_handler)
def define_handlers(active_rplugin: ActiveRplugin) -> Do: channel = active_rplugin.channel cname = camelcaseify(active_rplugin.name) rpc_handlers_fun = f'{cname}RpcHandlers' result = yield N.call_once_defined(rpc_handlers_fun, timeout=3) handlers = (Lists.wrap(result).flat_map(RpcHandlerSpec.decode).map( lambda spec: ActiveRpcTrigger(spec=spec, channel=channel))) yield N.pure(handlers)
def _parse_row(self, el): sub = lambda a: Lists.wrap(el.xpath(a)) name = sub('descendant::a[@class="detLink"]').head / _.text anchors = sub('descendant::a[@href]') magnet = (anchors / __.get('href')).find(__.startswith('magnet:')) seeders = sub('td').lift(2) / _.text // try_convert_int desc = sub('descendant::font[@class="detDesc"]').head / _.text return name.product3(magnet, seeders, desc).map4(self._extract_info)
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 init_fields(spec: inspect.FullArgSpec) -> List[Field]: args = Lists.wrap(spec.args).tail | Nil types = Map(spec.annotations) def field(name: str) -> Field: tpe = types.lift(name) | Val(Any) return Field(name, tpe) return args / field
def sub(self) -> List[AlgebraMeta]: if self._sub is None: def intermediate(tpe: type) -> bool: return tpe.__name__ == self.__name__ return Lists.wrap( self.__subclasses__()).filter_not(intermediate) return self._sub
def decode(self, tpe: Type[Maybe], data: Json) -> Either[JsonError, Maybe[A]]: inner = Lists.wrap(tpe.__args__).head return (Right(Nothing) if data.absent else maybe_from_object( data, inner) if data.object else decode.match(data) / Just if data.array else Right(Nothing) if data.null else inner.cata( lambda a: decode_json_type_json(data, a) / Just, lambda: data.scalar.e(f'invalid type for `Maybe`: {data}', Maybe.check(data.data))))
def to_json(a: Any) -> Json: return ( JsonArray(Lists.wrap(a) / to_json) if isinstance(a, (list, tuple)) else JsonObject(Map(a).valmap(to_json)) if isinstance(a, dict) else JsonNull(None) if a is None else JsonScalar(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)
def init_fields(init: FunctionType, globalns: dict) -> List[Field]: spec = inspect.getfullargspec(init) args = Lists.wrap(spec.args).tail | Nil types = Map(get_type_hints(init)) def field(name: str) -> Field: tpe = types.lift(name) | Val(Any) return Field(name, tpe) return args / field
def truncated_trace_lines(self) -> List[str]: try: tb = Lists.wrap(traceback.walk_tb(self.cause.__traceback__)) / _[0] error_loc = (tb.filter( L(non_internal_frame)(_, self._internal_packages_arg)).flat_map( frame_traceback_entry)) return self.trace_lines_with((error_loc) + format_exception_error(self.cause)) except Exception as e: return self.trace_error()
def is_handler(name: str, f: Callable) -> Do: effective = getattr(f, '__do_original', f) hints = yield Try(get_type_hints, effective).to_maybe spec = yield Try(inspect.getfullargspec, effective).to_maybe param_name = yield Lists.wrap(spec.args).lift(1) param_type = yield Map(hints).lift(param_name) yield (Just( (normalize_type(param_type), f)) if isinstance(param_type, type) and issubclass(param_type, alg) else Just( (normalize_type(param_type), f)) if isinstance(param_type, _GenericAlias) and issubclass(param_type.__origin__, alg) else Nothing)
def __new__( cls, name: str, bases: typing.List[type], namespace: SimpleNamespace, algebra_base: bool = False, **kw: Any, ) -> None: inst = super().__new__(cls, name, bases, namespace, **kw) if inst.__args__ is None: if algebra_base: inst.__algebra_base__ = None else: setup_algebraic_type(name, inst, Lists.wrap(bases)) return inst
def format_stack(self) -> List[str]: rev = self.stack.reversed def remove_recursion(i): pre = rev[:i + 1] post = rev[i:].drop_while(__.filename.endswith('/amino/io.py')) return pre + post def remove_internal(): start = rev.index_where(_.function == 'unsafe_perform_sync') return start / remove_recursion | rev frames = (self.location.to_list if IO.stack_only_location else remove_internal()) data = frames / (lambda a: a[1:-2] + tuple(a[-2])) return sanitize_tb(Lists.wrap(traceback.format_list(list(data))))
def to_json(a: 'Any') -> 'Json': # line 8 _coconut_match_to = a # line 9 _coconut_match_check = False # line 9 if _coconut.isinstance(_coconut_match_to, (list, tuple)): # line 9 a = _coconut_match_to # line 9 _coconut_match_check = True # line 9 if _coconut_match_check: # line 9 result = JsonArray(Lists.wrap(a) / to_json) # line 11 if not _coconut_match_check: # line 12 if _coconut.isinstance(_coconut_match_to, dict): # line 12 a = _coconut_match_to # line 12 _coconut_match_check = True # line 12 if _coconut_match_check: # line 12 result = JsonObject(Map(a).valmap(to_json)) # line 13 if not _coconut_match_check: # line 14 a = _coconut_match_to # line 14 _coconut_match_check = True # line 14 if _coconut_match_check: # line 14 result = JsonScalar(a) # line 15 return result # line 16
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 list_from_iter(self, iterable: Iterable[A]) -> List[A]: return Lists.wrap(iterable)
def dec() -> Either[JsonError, List[A]]: return Lists.wrap(data.data).traverse(decode.match, Either)
def set(self, value): super().set(value) glob = lambda a: Lists.wrap(a.parent.glob(a.name)) self.value = List.wrap(self.value) / _.value // glob
def process_output(output: list) -> List[str]: s, result = Lists.wrap(output).map(line).traverse(recover, State).run(Map()).value return result.flat_map(_.to_list)
def encode(self, data: Tuple) -> Do: array = yield encode_json(Lists.wrap(data)) return json_object_with_type(Map(data=array), tuple)
def read(cmd: str, *args: str) -> 'TmuxIO[A]': return TmuxRead(TmuxCmd(cmd, Lists.wrap(args)))
def write(cmd: str, *args: str) -> 'TmuxIO[A]': return TmuxWrite(TmuxCmd(cmd, Lists.wrap(args)))
def objects_from_module(mod: ModuleType, pred: Callable[[Any], bool]) -> Do: all = yield Maybe.getattr(mod, '__all__').to_either( f'module `{mod.__name__}` does not define `__all__`') return (Lists.wrap(all).flat_map(L(Maybe.getattr)(mod, _)).filter(pred))
def from_cons(cons: Callable[..., A]) -> 'TmuxCmdData[A]': f = getattr(cons, '__do_original', cons) spec = inspect.getfullargspec(f) return TmuxCmdData(Lists.wrap(spec.args), cons)
def s() -> str: try: return format_funcall(f, Lists.wrap(a), kw) except Exception as e: return str(f) log.error(str(e))
def encode(self, a: Collection) -> Either[JsonError, Json]: return Lists.wrap(a).traverse(encode_json, Either) / JsonArray
def venv_site(venv: Venv) -> Do: lib_dir = venv.meta.dir / 'lib' libs = yield IO.delay(lib_dir.glob, 'python3.?') lib = Lists.wrap(libs).head.to_either(f'no python dirs in {lib_dir}') return lib.map(lambda a: a / 'site-packages')