def filter_by_metadata(self, series=None, season=None, episode=None): filters = List( Maybe(series) / (lambda a: Release.name == a), Maybe(season) / str / (lambda a: Release.season == a), Maybe(episode) / str / (lambda a: Release.episode == a), ) return self.filter_release(*filters.join)
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 flat_map(self) -> None: a = 'start' b = 'end' Maybe.optional(a).flat_map( lambda v: Maybe.optional(v + b)).should.contain(a + b) f = lambda a: Maybe.optional(a).flat_map(lambda c: Monad.fatal(Maybe). pure(c + b)) f(a).should.contain(a + b)
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 venv_package_status_site(venv: Venv, site: Path, req_spec: str) -> Do: ws = yield IO.delay(pkg_resources.WorkingSet, [site]) req = yield IO.delay(pkg_resources.Requirement, req_spec) return Maybe.check(ws.by_key.get(req.key)).cata_strict( lambda a: VenvPackageExistent(venv, a), VenvPackageAbsent(venv), )
def cons( ident: IdentSpec, id: int = None, ) -> 'Pane': return Pane( ensure_ident_or_generate(ident), Maybe.check(id), )
def cons( ident: IdentSpec, id: int = None, ) -> 'Window': return Window( ensure_ident_or_generate(ident), Maybe.check(id), )
def cons( ident: IdentSpec, id: int = None, ) -> 'Session': return Session( ensure_ident_or_generate(ident), Maybe.check(id), )
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 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 text(element: etree.Element, expr: str) -> Maybe[str]: return sub(element, expr) // (lambda a: Maybe.optional(a.text)) return dict( title='', size=1, size_str='1', seeders=5, magnet_link='', )
def cons( rplugins: List[Rplugin] = Nil, chromatin_rplugin: Rplugin = None, chromatin_venv: str = None, venvs: List[str] = Nil, ready: List[str] = Nil, active: List[ActiveRpluginMeta] = Nil, uninitialized: List[ActiveRpluginMeta] = Nil, triggers: Map[str, List[ActiveRpcTrigger]] = Map(), errors: List[str] = Nil, ) -> 'Env': return Env( rplugins, Maybe.optional(chromatin_rplugin), Maybe.optional(chromatin_venv), venvs, ready, active, uninitialized, triggers, errors, )
def add_season(self, id, num): def handle_show(show): season = List.wrap(self.tvdb.season(show.etvdb_id, num)) if season: now = datetime.now().strftime('%F') aired = (season.filter(_['date'] < now).map(_['episode']).max) aired % L(self._releases.add_season)( show.canonical_name, num, _, search_name=show.search_name) return 'Done' else: return 'No such season: {} s{}'.format(show, num) return (Maybe(self._shows.find_by_id(id)) / handle_show | self._no_show(id))
def cons( ident: IdentSpec = None, state: ViewState = None, geometry: ViewGeometry = None, open: bool = False, cwd: Path = None, pin: bool = False, ) -> 'SimplePane': return SimplePane( ensure_ident_or_generate(ident), state or ViewState.cons(), geometry or ViewGeometry.cons(), Boolean(open), Maybe.optional(cwd), Boolean(pin), )
def parse_row(row: etree.Element) -> Generator: texts = cell_texts(row) title = yield texts.head size_str, seeders_str = yield texts.lift_all(-3, -2) link = yield sub(row, 'div[@class="tt-name"]/a').head url = yield Maybe.optional(link.get('href')) hash_match = yield url_re.search(url).to_maybe hash = yield hash_match.group('hash').to_maybe size = yield parse_size(size_str) seeders = yield Try(int, seeders_str.replace(',', '')).to_maybe yield Just( dict( title=title, size=size, size_str=size_str, seeders=seeders, magnet_link=magnet(hash), ))
def from_json(self, json: Map) -> Maybe[Project]: ''' Try to instantiate a Project from the given json object. Convert the **type** key to **tpe** and its value to Maybe. Make sure **root** is a directory, fall back to resolution by **tpe/name**. Reinsert the root dir into the json dict, filter out all keys that aren't contained in Project's fields. Try to instantiate. ''' root = json.get('root')\ .map(mkpath)\ .or_else( json.get_all('type', 'name') .flat_smap(self.resolver.type_name)) valid_fields = root\ .map(lambda a: json ** Map(root=a, tpe=json.get('type')))\ .map(lambda a: a.at(*Project._pclass_fields)) return Maybe.from_call(lambda: valid_fields.ssmap(Project)) | Empty()
def cons( min_size: Number = None, max_size: Number = None, fixed_size: Number = None, minimized_size: Number = None, weight: Number = None, position: Number = None, ) -> 'ViewGeometry': return ViewGeometry( Maybe.check(min_size), Maybe.check(max_size), Maybe.check(fixed_size), Maybe.check(minimized_size), Maybe.check(weight), Maybe.check(position), )
def cons( name: str = None, pythonpath: List[str] = None, debug: bool = None, interpreter: str = None, extensions: List[str] = None, track: bool = True, ) -> 'AddPluginOptions': return AddPluginOptions( Maybe.optional(name), Maybe.optional(pythonpath), Maybe.optional(debug), Maybe.optional(interpreter), Maybe.optional(extensions), Maybe.optional(track), )
def find(self, fa: List[A], f: Callable[[A], bool]): return Maybe(_find(fa, f))
def m(self, params, skip=1): return Maybe(self(params, skip))
def http_link_by_id(self, id): return Maybe(self._db.query(Link).filter_by(id=id).first())
def _current(self): return Maybe(Job(self._candidates))
def torrent_by_id(self, id): return Maybe(self._db.query(Torrent).filter_by(id=id).first())
def cons(socket: str = None) -> 'Tmux': return NativeTmux(Maybe.optional(socket))
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 latest_episode_m(self): return Maybe(self.latest_episode)
def sub_path(base: Path, path: Path): check = lambda: path.relative_to(str(base)) return Maybe.from_call(check, exc=ValueError)\ .map(_.parts)\ .map(List.wrap)
def latest_for_season(self, name, season): q = (self._db.query(func.max(Release.episode)).filter_by( name=name, season=season).join(ReleaseMonitor)) return Maybe(*q.first())
def main_dir(self) -> Maybe[Path]: return Maybe.from_call(Path.cwd, exc=IOError)
def _dat__values(self) -> List[Any]: return (self._dat__fields.traverse( lambda a: Maybe.getattr(self, a.name), Maybe).get_or_fail(lambda: f'corrupt `Dat`: {type(self)}'))
def optional_ident(spec: IdentSpec) -> Either[str, Maybe[Ident]]: return Maybe.optional(spec).cata(ensure_ident, Right(Nothing))
def ref(self, name): return Maybe.from_call(lambda: self.repo.refs[name.encode()], exc=KeyError)
def search(self, data: str, *a: Any, **kw: Any) -> Either[str, 'Match']: return (Maybe(self.rex.search(data, *a, **kw)).to_either( '`{}` does not contain `{}`'.format(data, self.spec)) / L(Match)(self, _, data))
def format_cause(exc: Exception, **kw) -> List[str]: from amino import Maybe return Maybe(exc.__cause__) / (lambda a: format_exception(a, **kw)) / (lambda a: a.cons('Cause:')) | List()
def setup(self): self.cwd = Maybe.from_call(Path.cwd, exc=IOError) super().setup()