class Bobby(Configurable): handler = Method() handler2 = Method() foo = Option(positional=True) bar = Option(required=False) @ContextProcessor def think(self, context): yield 'different' def __call__(self, think, *args, **kwargs): self.handler('1', *args, **kwargs) self.handler2('2', *args, **kwargs)
class MethodBasedConfigurable(Configurable): handler = Method() foo = Option(positional=True) bar = Option() def __call__(self, *args, **kwargs): self.handler(*args, **kwargs)
class Reduce(Configurable): function = Method() initializer = Option(required=False) @ContextProcessor def buffer(self, context): values = yield ValueHolder(self.initializer() if callable(self.initializer) else self.initializer) context.send(values.get()) @use_raw_input def __call__(self, values, bag): values.set(self.function(values.get(), bag))
class Factory(Configurable): initialize = Method(required=False) def __init__(self, *args, **kwargs): warnings.warn( __file__ + ' is experimental, API may change in the future, use it as a preview only and knowing the risks.', FutureWarning) super(Factory, self).__init__(*args, **kwargs) self.default_cursor_type = 'default' self.operations = [] if self.initialize is not None: self.initialize(self) @factory_operation def move(self, _from, _to, *args, **kwargs): if _from == _to: return args, kwargs if _isarg(_from): value = args[_from] args = args[:_from] + args[_from + 1:] elif _iskwarg(_from): value = kwargs[_from] kwargs = {k: v for k, v in kwargs if k != _from} else: raise RuntimeError('Houston, we have a problem...') if _isarg(_to): return (*args[:_to], value, *args[_to + 1:]), kwargs elif _iskwarg(_to): return args, {**kwargs, _to: value} else: raise RuntimeError('Houston, we have a problem...') def __call__(self, *args, **kwargs): print('factory call on', args, kwargs) for operation in self.operations: args, kwargs = operation.apply(*args, **kwargs) print(' ... after', operation, 'got', args, kwargs) return Bag(*args, **kwargs) def __getitem__(self, item): return CURSOR_TYPES[self.default_cursor_type](self, item)
class RateLimited(Configurable): handler = Method() initial = Option(int, positional=True, default=1) period = Option(int, positional=True, default=1) amount = Option(int, positional=True, default=1) @ContextProcessor def bucket(self, context): bucket = RateLimitBucket(self.initial, self.amount, self.period) bucket.start() yield bucket bucket.stop() bucket.join() def __call__(self, bucket, *args, **kwargs): bucket.wait() return self.handler(*args, **kwargs)
class Filter(Configurable): """Filter out hashes from the stream depending on the :attr:`filter` callable return value, when called with the current hash as parameter. Can be used as a decorator on a filter callable. .. attribute:: filter A callable used to filter lines. If the callable returns a true-ish value, the input will be passed unmodified to the next items. Otherwise, it'll be burnt. """ filter = Method() def __call__(self, *args, **kwargs): if self.filter(*args, **kwargs): return NOT_MODIFIED
class TwoMethods(Configurable): h1 = Method(required=True) h2 = Method(required=True)
class TwoMethods(Configurable): h1 = Method() h2 = Method()
class PrettyPrinter(Configurable): max_width = Option( int, default=term.get_size()[0], required=False, __doc__=""" If set, truncates the output values longer than this to this width. """, ) filter = Method( default=(lambda self, index, key, value: (value is not None) and (not isinstance(key, str) or not key.startswith("_"))), __doc__=""" A filter that determine what to print. Default is to ignore any key starting with an underscore and none values. """, ) @ContextProcessor def context(self, context): context.setdefault("_jupyter_html", None) yield context if context._jupyter_html is not None: from IPython.display import display, HTML display( HTML("\n".join(["<table>"] + context._jupyter_html + ["</table>"]))) def __call__(self, context, *args, **kwargs): if not settings.QUIET: if term.isjupyter: self.print_jupyter(context, *args, **kwargs) return NOT_MODIFIED if term.istty: self.print_console(context, *args, **kwargs) return NOT_MODIFIED self.print_quiet(context, *args, **kwargs) return NOT_MODIFIED def print_quiet(self, context, *args, **kwargs): for index, (key, value) in enumerate( itertools.chain(enumerate(args), kwargs.items())): if self.filter(index, key, value): print( self.format_quiet(index, key, value, fields=context.get_input_fields())) def format_quiet(self, index, key, value, *, fields=None): # XXX should we implement argnames here ? return " ".join( ((" " if index else "-"), str(key), ":", str(value).strip())) def print_console(self, context, *args, **kwargs): print("\u250c") for index, (key, value) in enumerate( itertools.chain(enumerate(args), kwargs.items())): if self.filter(index, key, value): print( self.format_console(index, key, value, fields=context.get_input_fields())) print("\u2514") def format_console(self, index, key, value, *, fields=None): fields = fields or [] if not isinstance(key, str): if len(fields) > key and str(key) != str(fields[key]): key = "{}{}".format(fields[key], term.lightblack("[{}]".format(key))) else: key = str(index) prefix = "\u2502 {} = ".format(key) prefix_length = len(prefix) def indent(text, prefix): for i, line in enumerate(text.splitlines()): yield (prefix if i else "") + line + CLEAR_EOL + "\n" repr_of_value = "".join( indent(pprint.pformat(value, width=self.max_width - prefix_length), "\u2502" + " " * (len(prefix) - 1))).strip() return "{}{}{}".format(prefix, repr_of_value.replace("\n", CLEAR_EOL + "\n"), CLEAR_EOL) def print_jupyter(self, context, *args): if not context._jupyter_html: context._jupyter_html = [ "<thead><tr>", *map( "<th>{}</th>".format, map( html.escape, map(str, context.get_input_fields() or range(len(args))))), "</tr></thead>", ] context._jupyter_html += [ "<tr>", *map("<td>{}</td>".format, map(html.escape, map(repr, args))), "</tr>" ]