From 4154d7e3d839456c047fe9b8ce109cfbc6663715 Mon Sep 17 00:00:00 2001 From: Romain Dorgueil Date: Mon, 1 May 2017 18:27:27 +0200 Subject: [PATCH] Starting to work on #47 a.k.a the context processor mess. This is a first implementation removing all the uggly function calls, but further work must work on less things called "context", as it is bad for readability. Concerns better separated now. --- bonobo/basics.py | 5 +- bonobo/config/configurables.py | 21 +++-- bonobo/config/processors.py | 79 ++++++++++++++++--- bonobo/execution/base.py | 55 +++++-------- bonobo/execution/node.py | 2 +- bonobo/ext/opendatasoft.py | 1 - bonobo/io/csv.py | 2 - bonobo/io/file.py | 2 - bonobo/io/json.py | 1 - tests/test_basics.py | 27 +++++++ ...rocessors.py => test_config_processors.py} | 27 ++++--- tests/test_execution.py | 5 +- 12 files changed, 152 insertions(+), 75 deletions(-) create mode 100644 tests/test_basics.py rename tests/{context/test_processors.py => test_config_processors.py} (62%) diff --git a/bonobo/basics.py b/bonobo/basics.py index 97282ab..03a1232 100644 --- a/bonobo/basics.py +++ b/bonobo/basics.py @@ -3,7 +3,7 @@ from pprint import pprint as _pprint from colorama import Fore, Style -from bonobo.config.processors import contextual +from bonobo.config.processors import ContextProcessor from bonobo.structs.bags import Bag from bonobo.util.objects import ValueHolder from bonobo.util.term import CLEAR_EOL @@ -49,12 +49,11 @@ def Tee(f): return wrapped -@contextual def count(counter, *args, **kwargs): counter += 1 -@count.add_context_processor +@ContextProcessor.decorate(count) def _count_counter(self, context): counter = ValueHolder(0) yield counter diff --git a/bonobo/config/configurables.py b/bonobo/config/configurables.py index 6be2b29..c1486ee 100644 --- a/bonobo/config/configurables.py +++ b/bonobo/config/configurables.py @@ -1,3 +1,4 @@ +from bonobo.config.processors import ContextProcessor from bonobo.config.options import Option __all__ = [ @@ -15,16 +16,24 @@ class ConfigurableMeta(type): super().__init__(what, bases, dict) cls.__options__ = {} cls.__positional_options__ = [] + cls.__processors__ = [] for typ in cls.__mro__: for name, value in typ.__dict__.items(): if isinstance(value, Option): - if not value.name: - value.name = name - if not name in cls.__options__: - cls.__options__[name] = value - if value.positional: - cls.__positional_options__.append(name) + if isinstance(value, ContextProcessor): + cls.__processors__.append(value) + else: + if not value.name: + value.name = name + if not name in cls.__options__: + cls.__options__[name] = value + if value.positional: + cls.__positional_options__.append(name) + + # This can be done before, more efficiently. Not so bad neither as this is only done at type() creation time + # (aka class Xxx(...) time) and there should not be hundreds of processors. Still not very elegant. + cls.__processors__ = sorted(cls.__processors__, key=lambda v: v._creation_counter) class Configurable(metaclass=ConfigurableMeta): diff --git a/bonobo/config/processors.py b/bonobo/config/processors.py index 9dac6d0..2d3de8f 100644 --- a/bonobo/config/processors.py +++ b/bonobo/config/processors.py @@ -2,24 +2,23 @@ import functools import types -from bonobo.util.compat import deprecated_alias +from bonobo.util.compat import deprecated_alias, deprecated + +from bonobo.config.options import Option +from bonobo.util.iterators import ensure_tuple _CONTEXT_PROCESSORS_ATTR = '__processors__' -class ContextProcessor: - _creation_counter = 0 - +class ContextProcessor(Option): @property def __name__(self): return self.func.__name__ def __init__(self, func): self.func = func - - # This hack is necessary for python3.5 - self._creation_counter = ContextProcessor._creation_counter - ContextProcessor._creation_counter += 1 + super(ContextProcessor, self).__init__(required=False, default=self.__name__) + self.name = self.__name__ def __repr__(self): return repr(self.func).replace(' int: return i**2 -@contextual def push_result(results, i: int): results.append(i) -@push_result.__processors__.append +@ContextProcessor.decorate(push_result) def results(f, context): results = [] yield results