Big refactoring, way simpler management of transformations. Early branch for upcoming version 0.2.

This commit is contained in:
Romain Dorgueil
2017-01-17 22:45:10 +01:00
parent b6e84c66e3
commit 8532520aae
41 changed files with 627 additions and 433 deletions

View File

@ -0,0 +1,55 @@
from operator import attrgetter
from bonobo import contextual, ContextProcessor
from bonobo.context.processors import get_context_processors
@contextual
class CP1:
@ContextProcessor
def c(self):
pass
@ContextProcessor
def a(self):
pass
@ContextProcessor
def b(self):
pass
@contextual
class CP2(CP1):
@ContextProcessor
def f(self):
pass
@ContextProcessor
def e(self):
pass
@ContextProcessor
def d(self):
pass
@contextual
class CP3(CP2):
@ContextProcessor
def c(self):
pass
@ContextProcessor
def b(self):
pass
def get_all_processors_names(cls):
return list(map(attrgetter('__name__'), get_context_processors(cls)))
def test_inheritance_and_ordering():
assert get_all_processors_names(CP1) == ['c', 'a', 'b']
assert get_all_processors_names(CP2) == ['c', 'a', 'b', 'f', 'e', 'd']
assert get_all_processors_names(CP3) == ['c', 'a', 'b', 'f', 'e', 'd', 'c', 'b']

View File

@ -1,6 +1,5 @@
from bonobo import Graph, NaiveStrategy, Bag
from bonobo.core.contexts import ExecutionContext
from bonobo.util.lifecycle import with_context
from bonobo import Graph, NaiveStrategy, Bag, contextual
from bonobo.context.execution import GraphExecutionContext
from bonobo.util.tokens import BEGIN, END
@ -12,11 +11,16 @@ def square(i: int) -> int:
return i**2
@with_context
def push_result(ctx, i: int):
if not hasattr(ctx.parent, 'results'):
ctx.parent.results = []
ctx.parent.results.append(i)
@contextual
def push_result(results, i: int):
results.append(i)
@push_result.__processors__.append
def results(f, context):
results = []
yield results
context.parent.results = results
chain = (generate_integers, square, push_result)
@ -25,8 +29,8 @@ chain = (generate_integers, square, push_result)
def test_empty_execution_context():
graph = Graph()
ctx = ExecutionContext(graph)
assert not len(ctx.components)
ctx = GraphExecutionContext(graph)
assert not len(ctx.nodes)
assert not len(ctx.plugins)
assert not ctx.alive
@ -46,15 +50,19 @@ def test_simple_execution_context():
graph = Graph()
graph.add_chain(*chain)
ctx = ExecutionContext(graph)
assert len(ctx.components) == len(chain)
ctx = GraphExecutionContext(graph)
assert len(ctx.nodes) == len(chain)
assert not len(ctx.plugins)
for i, component in enumerate(chain):
assert ctx[i].component is component
for i, node in enumerate(chain):
assert ctx[i].wrapped is node
assert not ctx.alive
ctx.recv(BEGIN, Bag(), END)
assert not ctx.alive
ctx.start()
assert ctx.alive

View File

@ -24,20 +24,20 @@ def test_graph_outputs_of():
def test_graph_add_component():
g = Graph()
assert len(g.components) == 0
assert len(g.nodes) == 0
g.add_component(identity)
assert len(g.components) == 1
g.add_node(identity)
assert len(g.nodes) == 1
g.add_component(identity)
assert len(g.components) == 2
g.add_node(identity)
assert len(g.nodes) == 2
def test_graph_add_chain():
g = Graph()
assert len(g.components) == 0
assert len(g.nodes) == 0
g.add_chain(identity, identity, identity)
assert len(g.components) == 3
assert len(g.nodes) == 3
assert len(g.outputs_of(BEGIN)) == 1

View File

@ -1,8 +1,8 @@
from bonobo.core.stats import WithStatistics
from bonobo.core.statistics import WithStatistics
class MyThingWithStats(WithStatistics):
def get_stats(self, *args, **kwargs):
def get_statistics(self, *args, **kwargs):
return (
('foo', 42),
('bar', 69),
@ -11,4 +11,4 @@ class MyThingWithStats(WithStatistics):
def test_with_statistics():
o = MyThingWithStats()
assert o.get_stats_as_string() == 'foo=42 bar=69'
assert o.get_statistics_as_string() == 'foo=42 bar=69'

View File

@ -1,21 +1,22 @@
import pytest
from bonobo import Bag, CsvReader, CsvWriter
from bonobo.core.contexts import ComponentExecutionContext
from bonobo.util.testing import CapturingComponentExecutionContext
from bonobo.context.execution import NodeExecutionContext
from bonobo.util.testing import CapturingNodeExecutionContext
from bonobo.util.tokens import BEGIN, END
def test_write_csv_to_file(tmpdir):
file = tmpdir.join('output.json')
writer = CsvWriter(str(file))
context = ComponentExecutionContext(writer, None)
writer = CsvWriter(path=str(file))
context = NodeExecutionContext(writer, None)
context.initialize()
context.recv(BEGIN, Bag({'foo': 'bar'}), Bag({'foo': 'baz', 'ignore': 'this'}), END)
context.start()
context.step()
context.step()
context.finalize()
context.stop()
assert file.read() == 'foo\nbar\nbaz\n'
@ -23,27 +24,18 @@ def test_write_csv_to_file(tmpdir):
getattr(context, 'file')
def test_write_json_without_initializer_should_not_work(tmpdir):
file = tmpdir.join('output.json')
writer = CsvWriter(str(file))
context = ComponentExecutionContext(writer, None)
with pytest.raises(AttributeError):
writer(context, {'foo': 'bar'})
def test_read_csv_from_file(tmpdir):
file = tmpdir.join('input.csv')
file.write('a,b,c\na foo,b foo,c foo\na bar,b bar,c bar')
reader = CsvReader(str(file), delimiter=',')
reader = CsvReader(path=str(file), delimiter=',')
context = CapturingComponentExecutionContext(reader, None)
context = CapturingNodeExecutionContext(reader, None)
context.initialize()
context.start()
context.recv(BEGIN, Bag(), END)
context.step()
context.finalize()
context.stop()
assert len(context.send.mock_calls) == 2

View File

@ -1,8 +1,8 @@
import pytest
from bonobo import FileWriter, Bag, FileReader
from bonobo.core.contexts import ComponentExecutionContext
from bonobo.util.testing import CapturingComponentExecutionContext
from bonobo.context.execution import NodeExecutionContext
from bonobo.util.testing import CapturingNodeExecutionContext
from bonobo.util.tokens import BEGIN, END
@ -16,27 +16,24 @@ from bonobo.util.tokens import BEGIN, END
def test_file_writer_in_context(tmpdir, lines, output):
file = tmpdir.join('output.txt')
writer = FileWriter(str(file))
context = ComponentExecutionContext(writer, None)
writer = FileWriter(path=str(file))
context = NodeExecutionContext(writer, None)
context.initialize()
context.start()
context.recv(BEGIN, *map(Bag, lines), END)
for i in range(len(lines)):
context.step()
context.finalize()
context.stop()
assert file.read() == output
with pytest.raises(AttributeError):
getattr(context, 'file')
def test_file_writer_out_of_context(tmpdir):
file = tmpdir.join('output.txt')
writer = FileWriter(str(file))
fp = writer.open()
fp.write('Yosh!')
writer.close(fp)
writer = FileWriter(path=str(file))
with writer.open() as fp:
fp.write('Yosh!')
assert file.read() == 'Yosh!'
@ -45,13 +42,13 @@ def test_file_reader_in_context(tmpdir):
file = tmpdir.join('input.txt')
file.write('Hello\nWorld\n')
reader = FileReader(str(file))
context = CapturingComponentExecutionContext(reader, None)
reader = FileReader(path=str(file))
context = CapturingNodeExecutionContext(reader, None)
context.initialize()
context.start()
context.recv(BEGIN, Bag(), END)
context.step()
context.finalize()
context.stop()
assert len(context.send.mock_calls) == 2

View File

@ -1,20 +1,21 @@
import pytest
from bonobo import Bag, JsonWriter, JsonReader
from bonobo.core.contexts import ComponentExecutionContext
from bonobo.util.testing import CapturingComponentExecutionContext
from bonobo.context.execution import NodeExecutionContext
from bonobo.util.objects import ValueHolder
from bonobo.util.testing import CapturingNodeExecutionContext
from bonobo.util.tokens import BEGIN, END
def test_write_json_to_file(tmpdir):
file = tmpdir.join('output.json')
writer = JsonWriter(str(file))
context = ComponentExecutionContext(writer, None)
writer = JsonWriter(path=str(file))
context = NodeExecutionContext(writer, None)
context.initialize()
context.start()
context.recv(BEGIN, Bag({'foo': 'bar'}), END)
context.step()
context.finalize()
context.stop()
assert file.read() == '[\n{"foo": "bar"}\n]'
@ -25,26 +26,17 @@ def test_write_json_to_file(tmpdir):
getattr(context, 'first')
def test_write_json_without_initializer_should_not_work(tmpdir):
file = tmpdir.join('output.json')
writer = JsonWriter(str(file))
context = ComponentExecutionContext(writer, None)
with pytest.raises(AttributeError):
writer(context, {'foo': 'bar'})
def test_read_json_from_file(tmpdir):
file = tmpdir.join('input.json')
file.write('[{"x": "foo"},{"x": "bar"}]')
reader = JsonReader(str(file))
reader = JsonReader(path=str(file))
context = CapturingComponentExecutionContext(reader, None)
context = CapturingNodeExecutionContext(reader, None)
context.initialize()
context.start()
context.recv(BEGIN, Bag(), END)
context.step()
context.finalize()
context.stop()
assert len(context.send.mock_calls) == 2