Merge pull request #250 from hartym/249_fix_quoting_as_int
Fix #249: Quoting format is integer, not string.
This commit is contained in:
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
|||||||
# Generated by Medikit 0.4.3 on 2018-01-16.
|
# Generated by Medikit 0.4.7 on 2018-02-03.
|
||||||
# All changes will be overriden.
|
# All changes will be overriden.
|
||||||
|
|
||||||
PACKAGE ?= bonobo
|
PACKAGE ?= bonobo
|
||||||
|
|||||||
10
Projectfile
10
Projectfile
@ -70,11 +70,17 @@ python.add_requirements(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@listen(make.on_generate)
|
@listen(make.on_generate)
|
||||||
def on_make_generate(event):
|
def on_make_generate(event):
|
||||||
event.makefile['SPHINX_AUTOBUILD'] = '$(PYTHON_DIRNAME)/sphinx-autobuild'
|
event.makefile['SPHINX_AUTOBUILD'] = '$(PYTHON_DIRNAME)/sphinx-autobuild'
|
||||||
event.makefile.add_target('watch-$(SPHINX_SOURCEDIR)', '''
|
event.makefile.add_target(
|
||||||
|
'watch-$(SPHINX_SOURCEDIR)',
|
||||||
|
'''
|
||||||
$(SPHINX_AUTOBUILD) $(SPHINX_SOURCEDIR) $(shell mktemp -d)
|
$(SPHINX_AUTOBUILD) $(SPHINX_SOURCEDIR) $(shell mktemp -d)
|
||||||
''', phony=True)
|
''',
|
||||||
|
phony=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# vim: ft=python:
|
# vim: ft=python:
|
||||||
|
|||||||
@ -40,13 +40,14 @@ modules = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def underlined_filter(txt, chr):
|
def underlined_filter(txt, chr):
|
||||||
return txt + '\n' + chr * len(txt)
|
return txt + '\n' + chr * len(txt)
|
||||||
|
|
||||||
|
|
||||||
env = Environment(loader=DictLoader({
|
env = Environment(
|
||||||
'module': '''
|
loader=DictLoader({
|
||||||
|
'module':
|
||||||
|
'''
|
||||||
{{ (':mod:`'~title~' <'~name~'>`') | underlined('=') }}
|
{{ (':mod:`'~title~' <'~name~'>`') | underlined('=') }}
|
||||||
|
|
||||||
.. currentmodule:: {{ name }}
|
.. currentmodule:: {{ name }}
|
||||||
@ -55,7 +56,9 @@ env = Environment(loader=DictLoader({
|
|||||||
|
|
||||||
.. automodule:: {{ name }}
|
.. automodule:: {{ name }}
|
||||||
{% for opt in automodule_options %} :{{ opt }}:{{ "\n" }}{% endfor %}
|
{% for opt in automodule_options %} :{{ opt }}:{{ "\n" }}{% endfor %}
|
||||||
'''[1:-1] + '\n'}))
|
''' [1:-1] + '\n'
|
||||||
|
})
|
||||||
|
)
|
||||||
env.filters['underlined'] = underlined_filter
|
env.filters['underlined'] = underlined_filter
|
||||||
|
|
||||||
for module in modules:
|
for module in modules:
|
||||||
|
|||||||
@ -47,15 +47,7 @@ class ConfigurableMeta(type):
|
|||||||
prefix = ':param {}: '.format(_param)
|
prefix = ':param {}: '.format(_param)
|
||||||
for lineno, line in enumerate((_value.__doc__ or '').split('\n')):
|
for lineno, line in enumerate((_value.__doc__ or '').split('\n')):
|
||||||
_options_doc.append((' ' * len(prefix) if lineno else prefix) + line)
|
_options_doc.append((' ' * len(prefix) if lineno else prefix) + line)
|
||||||
cls.__doc__ = '\n\n'.join(
|
cls.__doc__ = '\n\n'.join(map(str.strip, filter(None, (cls.__doc__, '\n'.join(_options_doc)))))
|
||||||
map(
|
|
||||||
str.strip,
|
|
||||||
filter(None, (
|
|
||||||
cls.__doc__,
|
|
||||||
'\n'.join(_options_doc)
|
|
||||||
))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def __options__(cls):
|
def __options__(cls):
|
||||||
|
|||||||
@ -56,7 +56,7 @@ class ETLCommand(BaseCommand):
|
|||||||
graph_coll = self.get_graph(*args, **options)
|
graph_coll = self.get_graph(*args, **options)
|
||||||
|
|
||||||
if not isinstance(graph_coll, GeneratorType):
|
if not isinstance(graph_coll, GeneratorType):
|
||||||
graph_coll = (graph_coll,)
|
graph_coll = (graph_coll, )
|
||||||
|
|
||||||
for i, graph in enumerate(graph_coll):
|
for i, graph in enumerate(graph_coll):
|
||||||
assert isinstance(graph, bonobo.Graph), 'Invalid graph provided.'
|
assert isinstance(graph, bonobo.Graph), 'Invalid graph provided.'
|
||||||
|
|||||||
@ -12,9 +12,11 @@ class FileHandler(Configurable):
|
|||||||
encoding (str): which encoding to use when opening the file.
|
encoding (str): which encoding to use when opening the file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
path = Option(str, required=True, positional=True, __doc__='''
|
path = Option(
|
||||||
|
str, required=True, positional=True, __doc__='''
|
||||||
Path to use within the provided filesystem.
|
Path to use within the provided filesystem.
|
||||||
''') # type: str
|
'''
|
||||||
|
) # type: str
|
||||||
eol = Option(str, default='\n', __doc__='''
|
eol = Option(str, default='\n', __doc__='''
|
||||||
Character to use as line separator.
|
Character to use as line separator.
|
||||||
''') # type: str
|
''') # type: str
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class CsvHandler(FileHandler):
|
|||||||
doublequote = Option(str, default=csv.excel.doublequote, required=False)
|
doublequote = Option(str, default=csv.excel.doublequote, required=False)
|
||||||
skipinitialspace = Option(str, default=csv.excel.skipinitialspace, required=False)
|
skipinitialspace = Option(str, default=csv.excel.skipinitialspace, required=False)
|
||||||
lineterminator = Option(str, default=csv.excel.lineterminator, required=False)
|
lineterminator = Option(str, default=csv.excel.lineterminator, required=False)
|
||||||
quoting = Option(str, default=csv.excel.quoting, required=False)
|
quoting = Option(int, default=csv.excel.quoting, required=False)
|
||||||
|
|
||||||
# Fields (renamed from headers)
|
# Fields (renamed from headers)
|
||||||
headers = RenamedOption('fields')
|
headers = RenamedOption('fields')
|
||||||
@ -57,9 +57,13 @@ class CsvReader(FileReader, CsvHandler):
|
|||||||
Reads a CSV and yield the values as dicts.
|
Reads a CSV and yield the values as dicts.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
skip = Option(int, default=0, __doc__='''
|
skip = Option(
|
||||||
|
int,
|
||||||
|
default=0,
|
||||||
|
__doc__='''
|
||||||
If set and greater than zero, the reader will skip this amount of lines.
|
If set and greater than zero, the reader will skip this amount of lines.
|
||||||
''')
|
'''
|
||||||
|
)
|
||||||
|
|
||||||
@Method(
|
@Method(
|
||||||
positional=False,
|
positional=False,
|
||||||
|
|||||||
@ -151,7 +151,10 @@ class Graph:
|
|||||||
return '<strong>{}</strong>: {}'.format(type(exc).__name__, str(exc))
|
return '<strong>{}</strong>: {}'.format(type(exc).__name__, str(exc))
|
||||||
|
|
||||||
def _resolve_index(self, mixed):
|
def _resolve_index(self, mixed):
|
||||||
""" Find the index based on various strategies for a node, probably an input or output of chain. Supported inputs are indexes, node values or names.
|
"""
|
||||||
|
Find the index based on various strategies for a node, probably an input or output of chain. Supported
|
||||||
|
inputs are indexes, node values or names.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if mixed is None:
|
if mixed is None:
|
||||||
return None
|
return None
|
||||||
|
|||||||
@ -14,8 +14,8 @@ class ApiHelper:
|
|||||||
from inspect import signature
|
from inspect import signature
|
||||||
parameters = list(signature(x).parameters)
|
parameters = list(signature(x).parameters)
|
||||||
required_parameters = {'plugins', 'services', 'strategy'}
|
required_parameters = {'plugins', 'services', 'strategy'}
|
||||||
assert len(parameters) > 0 and parameters[
|
assert len(parameters
|
||||||
0] == 'graph', 'First parameter of a graph api function must be "graph".'
|
) > 0 and parameters[0] == 'graph', 'First parameter of a graph api function must be "graph".'
|
||||||
assert required_parameters.intersection(
|
assert required_parameters.intersection(
|
||||||
parameters
|
parameters
|
||||||
) == required_parameters, 'Graph api functions must define the following parameters: ' + ', '.join(
|
) == required_parameters, 'Graph api functions must define the following parameters: ' + ', '.join(
|
||||||
|
|||||||
@ -26,7 +26,7 @@ def ensure_tuple(tuple_or_mixed, *, cls=tuple):
|
|||||||
if isinstance(tuple_or_mixed, tuple):
|
if isinstance(tuple_or_mixed, tuple):
|
||||||
return tuple.__new__(cls, tuple_or_mixed)
|
return tuple.__new__(cls, tuple_or_mixed)
|
||||||
|
|
||||||
return tuple.__new__(cls, (tuple_or_mixed,))
|
return tuple.__new__(cls, (tuple_or_mixed, ))
|
||||||
|
|
||||||
|
|
||||||
def cast(type_):
|
def cast(type_):
|
||||||
|
|||||||
@ -61,10 +61,13 @@ language = None
|
|||||||
# This patterns also effect to html_static_path and html_extra_path
|
# This patterns also effect to html_static_path and html_extra_path
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
|
||||||
autoclass_content = 'both'
|
autoclass_content = 'both'
|
||||||
autodoc_member_order = 'groupwise'
|
autodoc_member_order = 'groupwise'
|
||||||
autodoc_default_flags =['members', 'undoc-members', 'show-inheritance', ]
|
autodoc_default_flags = [
|
||||||
|
'members',
|
||||||
|
'undoc-members',
|
||||||
|
'show-inheritance',
|
||||||
|
]
|
||||||
|
|
||||||
add_module_names = False
|
add_module_names = False
|
||||||
pygments_style = 'sphinx'
|
pygments_style = 'sphinx'
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
-e .[dev]
|
-e .[dev]
|
||||||
alabaster==0.7.10
|
alabaster==0.7.10
|
||||||
arrow==0.12.0
|
arrow==0.12.1
|
||||||
attrs==17.4.0
|
attrs==17.4.0
|
||||||
babel==2.5.3
|
babel==2.5.3
|
||||||
binaryornot==0.4.4
|
binaryornot==0.4.4
|
||||||
certifi==2017.11.5
|
certifi==2018.1.18
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
click==6.7
|
click==6.7
|
||||||
cookiecutter==1.5.1
|
cookiecutter==1.5.1
|
||||||
@ -23,7 +23,7 @@ pygments==2.2.0
|
|||||||
pytest-cov==2.5.1
|
pytest-cov==2.5.1
|
||||||
pytest-sugar==0.8.0
|
pytest-sugar==0.8.0
|
||||||
pytest-timeout==1.2.1
|
pytest-timeout==1.2.1
|
||||||
pytest==3.3.2
|
pytest==3.4.0
|
||||||
python-dateutil==2.6.1
|
python-dateutil==2.6.1
|
||||||
pytz==2017.3
|
pytz==2017.3
|
||||||
requests==2.18.4
|
requests==2.18.4
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
-e .[docker]
|
-e .[docker]
|
||||||
appdirs==1.4.3
|
appdirs==1.4.3
|
||||||
bonobo-docker==0.6.0
|
bonobo-docker==0.6.0
|
||||||
certifi==2017.11.5
|
certifi==2018.1.18
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
colorama==0.3.9
|
colorama==0.3.9
|
||||||
docker-pycreds==0.2.1
|
docker-pycreds==0.2.1
|
||||||
docker==2.7.0
|
docker==2.7.0
|
||||||
fs==2.0.17
|
fs==2.0.18
|
||||||
graphviz==0.8.2
|
graphviz==0.8.2
|
||||||
idna==2.6
|
idna==2.6
|
||||||
jinja2==2.10
|
jinja2==2.10
|
||||||
|
|||||||
@ -4,14 +4,14 @@ bleach==2.1.2
|
|||||||
decorator==4.2.1
|
decorator==4.2.1
|
||||||
entrypoints==0.2.3
|
entrypoints==0.2.3
|
||||||
html5lib==1.0.1
|
html5lib==1.0.1
|
||||||
ipykernel==4.7.0
|
ipykernel==4.8.0
|
||||||
ipython-genutils==0.2.0
|
ipython-genutils==0.2.0
|
||||||
ipython==6.2.1
|
ipython==6.2.1
|
||||||
ipywidgets==6.0.1
|
ipywidgets==6.0.1
|
||||||
jedi==0.11.1
|
jedi==0.11.1
|
||||||
jinja2==2.10
|
jinja2==2.10
|
||||||
jsonschema==2.6.0
|
jsonschema==2.6.0
|
||||||
jupyter-client==5.2.1
|
jupyter-client==5.2.2
|
||||||
jupyter-console==5.2.0
|
jupyter-console==5.2.0
|
||||||
jupyter-core==4.4.0
|
jupyter-core==4.4.0
|
||||||
jupyter==1.0.0
|
jupyter==1.0.0
|
||||||
@ -19,7 +19,7 @@ markupsafe==1.0
|
|||||||
mistune==0.8.3
|
mistune==0.8.3
|
||||||
nbconvert==5.3.1
|
nbconvert==5.3.1
|
||||||
nbformat==4.4.0
|
nbformat==4.4.0
|
||||||
notebook==5.2.2
|
notebook==5.4.0
|
||||||
pandocfilters==1.4.2
|
pandocfilters==1.4.2
|
||||||
parso==0.1.1
|
parso==0.1.1
|
||||||
pexpect==4.3.1
|
pexpect==4.3.1
|
||||||
@ -28,8 +28,9 @@ prompt-toolkit==1.0.15
|
|||||||
ptyprocess==0.5.2
|
ptyprocess==0.5.2
|
||||||
pygments==2.2.0
|
pygments==2.2.0
|
||||||
python-dateutil==2.6.1
|
python-dateutil==2.6.1
|
||||||
pyzmq==16.0.3
|
pyzmq==16.0.4
|
||||||
qtconsole==4.3.1
|
qtconsole==4.3.1
|
||||||
|
send2trash==1.4.2
|
||||||
simplegeneric==0.8.1
|
simplegeneric==0.8.1
|
||||||
six==1.11.0
|
six==1.11.0
|
||||||
terminado==0.8.1
|
terminado==0.8.1
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
-e .[sqlalchemy]
|
-e .[sqlalchemy]
|
||||||
appdirs==1.4.3
|
appdirs==1.4.3
|
||||||
bonobo-sqlalchemy==0.6.0
|
bonobo-sqlalchemy==0.6.0
|
||||||
certifi==2017.11.5
|
certifi==2018.1.18
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
colorama==0.3.9
|
colorama==0.3.9
|
||||||
fs==2.0.17
|
fs==2.0.18
|
||||||
graphviz==0.8.2
|
graphviz==0.8.2
|
||||||
idna==2.6
|
idna==2.6
|
||||||
jinja2==2.10
|
jinja2==2.10
|
||||||
@ -18,7 +18,7 @@ python-slugify==1.2.4
|
|||||||
pytz==2017.3
|
pytz==2017.3
|
||||||
requests==2.18.4
|
requests==2.18.4
|
||||||
six==1.11.0
|
six==1.11.0
|
||||||
sqlalchemy==1.2.1
|
sqlalchemy==1.2.2
|
||||||
stevedore==1.28.0
|
stevedore==1.28.0
|
||||||
unidecode==1.0.22
|
unidecode==1.0.22
|
||||||
urllib3==1.22
|
urllib3==1.22
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
-e .
|
-e .
|
||||||
appdirs==1.4.3
|
appdirs==1.4.3
|
||||||
certifi==2017.11.5
|
certifi==2018.1.18
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
colorama==0.3.9
|
colorama==0.3.9
|
||||||
fs==2.0.17
|
fs==2.0.18
|
||||||
graphviz==0.8.2
|
graphviz==0.8.2
|
||||||
idna==2.6
|
idna==2.6
|
||||||
jinja2==2.10
|
jinja2==2.10
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import pprint
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from bonobo.config.configurables import Configurable
|
from bonobo.config.configurables import Configurable
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
from csv import QUOTE_ALL
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from bonobo import CsvReader, CsvWriter
|
from bonobo import CsvReader, CsvWriter
|
||||||
from bonobo.constants import EMPTY
|
from bonobo.constants import EMPTY
|
||||||
from bonobo.util.testing import FilesystemTester, BufferingNodeExecutionContext, WriterTest, ConfigurableNodeTest, ReaderTest
|
from bonobo.util.testing import FilesystemTester, BufferingNodeExecutionContext, WriterTest, ConfigurableNodeTest, \
|
||||||
|
ReaderTest
|
||||||
|
|
||||||
csv_tester = FilesystemTester('csv')
|
csv_tester = FilesystemTester('csv')
|
||||||
csv_tester.input_data = 'a,b,c\na foo,b foo,c foo\na bar,b bar,c bar'
|
csv_tester.input_data = 'a,b,c\na foo,b foo,c foo\na bar,b bar,c bar'
|
||||||
@ -90,6 +92,13 @@ class CsvReaderTest(Csv, ReaderTest, TestCase):
|
|||||||
self.check_output(context)
|
self.check_output(context)
|
||||||
assert context.get_output_fields() == ('x', 'y')
|
assert context.get_output_fields() == ('x', 'y')
|
||||||
|
|
||||||
|
@incontext(quoting=QUOTE_ALL)
|
||||||
|
def test_quoting(self, context):
|
||||||
|
context.write_sync(EMPTY)
|
||||||
|
context.stop()
|
||||||
|
self.check_output(context)
|
||||||
|
assert context.get_output_fields() == ('id', 'name')
|
||||||
|
|
||||||
|
|
||||||
class CsvWriterTest(Csv, WriterTest, TestCase):
|
class CsvWriterTest(Csv, WriterTest, TestCase):
|
||||||
@incontext()
|
@incontext()
|
||||||
|
|||||||
@ -14,8 +14,8 @@ def test_sortedlist():
|
|||||||
|
|
||||||
|
|
||||||
def test_ensure_tuple():
|
def test_ensure_tuple():
|
||||||
assert ensure_tuple('a') == ('a',)
|
assert ensure_tuple('a') == ('a', )
|
||||||
assert ensure_tuple(('a',)) == ('a',)
|
assert ensure_tuple(('a', )) == ('a', )
|
||||||
assert ensure_tuple(()) is ()
|
assert ensure_tuple(()) is ()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user