Implements JsonReader (#2)

This commit is contained in:
Romain Dorgueil
2016-12-28 11:29:12 +01:00
parent f3757f38b7
commit 67e25b92e1
7 changed files with 52 additions and 16 deletions

View File

@ -23,7 +23,7 @@ import os
import sys import sys
from .core import * from .core import *
from .io import * from .io import FileReader, FileWriter, JsonReader, JsonWriter
from .util import * from .util import *
PY35 = (sys.version_info >= (3, 5)) PY35 = (sys.version_info >= (3, 5))
@ -36,8 +36,10 @@ with open(os.path.realpath(os.path.join(os.path.dirname(__file__), '../version.t
__all__ = [ __all__ = [
'Bag', 'Bag',
'FileReader',
'FileWriter', 'FileWriter',
'Graph', 'Graph',
'JsonReader',
'JsonWriter', 'JsonWriter',
'NOT_MODIFIED', 'NOT_MODIFIED',
'NaiveStrategy', 'NaiveStrategy',

View File

@ -1,11 +1,11 @@
""" Readers and writers for common file formats. """ """ Readers and writers for common file formats. """
from .file import Handler, FileReader, FileWriter from .file import FileReader, FileWriter
from .json import JsonWriter from .json import JsonReader, JsonWriter
__all__ = [ __all__ = [
'Handler',
'FileReader', 'FileReader',
'FileWriter', 'FileWriter',
'JsonReader',
'JsonWriter', 'JsonWriter',
] ]

View File

@ -1,14 +1,14 @@
from bonobo.util.lifecycle import with_context from bonobo.util.lifecycle import with_context
__all__ = [ __all__ = [
'Handler', 'FileHandler',
'FileReader', 'FileReader',
'FileWriter', 'FileWriter',
] ]
@with_context @with_context
class Handler: class FileHandler:
""" """
Abstract component factory for file-related components. Abstract component factory for file-related components.
@ -44,7 +44,7 @@ class Handler:
del ctx.file del ctx.file
class Reader(Handler): class Reader(FileHandler):
def __call__(self, ctx): def __call__(self, ctx):
yield from self.handle(ctx) yield from self.handle(ctx)
@ -52,7 +52,7 @@ class Reader(Handler):
raise NotImplementedError('Abstract.') raise NotImplementedError('Abstract.')
class Writer(Handler): class Writer(FileHandler):
def __call__(self, ctx, row): def __call__(self, ctx, row):
return self.handle(ctx, row) return self.handle(ctx, row)

View File

@ -1,6 +1,6 @@
import json import json
from .file import FileWriter from .file import FileWriter, FileReader
__all__ = ['JsonWriter', ] __all__ = ['JsonWriter', ]
@ -9,9 +9,14 @@ class JsonHandler:
eol = ',\n' eol = ',\n'
class JsonReader(JsonHandler, FileReader):
def handle(self, ctx):
for line in json.load(ctx.file):
yield line
class JsonWriter(JsonHandler, FileWriter): class JsonWriter(JsonHandler, FileWriter):
def initialize(self, ctx): def initialize(self, ctx):
print('EOL', self.eol)
super().initialize(ctx) super().initialize(ctx)
ctx.file.write('[\n') ctx.file.write('[\n')

9
bonobo/util/testing.py Normal file
View File

@ -0,0 +1,9 @@
from unittest.mock import MagicMock
from bonobo.core.contexts import ComponentExecutionContext
class CapturingComponentExecutionContext(ComponentExecutionContext):
def __init__(self, component, parent):
super().__init__(component, parent)
self.send = MagicMock()

View File

@ -1,15 +1,11 @@
import pytest import pytest
from mock import MagicMock
from bonobo import FileWriter, Bag, FileReader from bonobo import FileWriter, Bag, FileReader
from bonobo.core.contexts import ComponentExecutionContext from bonobo.core.contexts import ComponentExecutionContext
from bonobo.util.testing import CapturingComponentExecutionContext
from bonobo.util.tokens import BEGIN, END from bonobo.util.tokens import BEGIN, END
class CapturingComponentExecutionContext(ComponentExecutionContext):
send = MagicMock()
@pytest.mark.parametrize( @pytest.mark.parametrize(
'lines,output', 'lines,output',
[ [

View File

@ -1,7 +1,8 @@
import pytest import pytest
from bonobo import Bag, JsonWriter from bonobo import Bag, JsonWriter, JsonReader
from bonobo.core.contexts import ComponentExecutionContext from bonobo.core.contexts import ComponentExecutionContext
from bonobo.util.testing import CapturingComponentExecutionContext
from bonobo.util.tokens import BEGIN, END from bonobo.util.tokens import BEGIN, END
@ -33,3 +34,26 @@ def test_write_json_without_initializer_should_not_work(tmpdir):
context = ComponentExecutionContext(json_writer, None) context = ComponentExecutionContext(json_writer, None)
with pytest.raises(AttributeError): with pytest.raises(AttributeError):
json_writer(context, {'foo': 'bar'}) json_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))
context = CapturingComponentExecutionContext(reader, None)
context.initialize()
context.recv(BEGIN, Bag(), END)
context.step()
context.finalize()
assert len(context.send.mock_calls) == 2
args0, kwargs0 = context.send.call_args_list[0]
assert len(args0) == 1 and not len(kwargs0)
args1, kwargs1 = context.send.call_args_list[1]
assert len(args1) == 1 and not len(kwargs1)
assert args0[0].args[0] == {'x': 'foo'}
assert args1[0].args[0] == {'x': 'bar'}