[cli] Adds a --filter option to "convert" command, allowing to use arbitrary filters to a command line conversion. Also adds --print and "-" output to pretty print to terminal instead of file output.
This commit is contained in:
@ -3,6 +3,9 @@ import os
|
|||||||
|
|
||||||
import bonobo
|
import bonobo
|
||||||
from bonobo.commands.util.arguments import parse_variable_argument
|
from bonobo.commands.util.arguments import parse_variable_argument
|
||||||
|
from bonobo.util import require
|
||||||
|
from bonobo.util.iterators import tuplize
|
||||||
|
from bonobo.util.python import WorkingDirectoryModulesRegistry
|
||||||
|
|
||||||
SHORTCUTS = {
|
SHORTCUTS = {
|
||||||
'csv': 'text/csv',
|
'csv': 'text/csv',
|
||||||
@ -51,7 +54,7 @@ def resolve_factory(name, filename, factory_type, options=None):
|
|||||||
if not name in REGISTRY:
|
if not name in REGISTRY:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
'Could not resolve {factory_type} factory for {filename} ({name}). Try providing it explicitely using -{opt} <format>.'.
|
'Could not resolve {factory_type} factory for {filename} ({name}). Try providing it explicitely using -{opt} <format>.'.
|
||||||
format(name=name, filename=filename, factory_type=factory_type, opt=factory_type[0])
|
format(name=name, filename=filename, factory_type=factory_type, opt=factory_type[0])
|
||||||
)
|
)
|
||||||
|
|
||||||
if factory_type == READER:
|
if factory_type == READER:
|
||||||
@ -62,14 +65,42 @@ def resolve_factory(name, filename, factory_type, options=None):
|
|||||||
raise ValueError('Invalid factory type.')
|
raise ValueError('Invalid factory type.')
|
||||||
|
|
||||||
|
|
||||||
def execute(input, output, reader=None, reader_options=None, writer=None, writer_options=None, options=None):
|
@tuplize
|
||||||
reader_factory, reader_options = resolve_factory(reader, input, READER, (options or []) + (reader_options or []))
|
def resolve_filters(filters):
|
||||||
writer_factory, writer_options = resolve_factory(writer, output, WRITER, (options or []) + (writer_options or []))
|
registry = WorkingDirectoryModulesRegistry()
|
||||||
|
for f in filters:
|
||||||
|
try:
|
||||||
|
mod, attr = f.split(':', 1)
|
||||||
|
yield getattr(registry.require(mod), attr)
|
||||||
|
except ValueError:
|
||||||
|
yield getattr(bonobo, f)
|
||||||
|
|
||||||
|
|
||||||
|
def execute(
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
reader=None,
|
||||||
|
reader_option=None,
|
||||||
|
writer=None,
|
||||||
|
writer_option=None,
|
||||||
|
option=None,
|
||||||
|
filter=None,
|
||||||
|
do_print=False
|
||||||
|
):
|
||||||
|
reader_factory, reader_option = resolve_factory(reader, input, READER, (option or []) + (reader_option or []))
|
||||||
|
|
||||||
|
if output == '-':
|
||||||
|
writer_factory, writer_option = bonobo.PrettyPrinter, {}
|
||||||
|
else:
|
||||||
|
writer_factory, writer_option = resolve_factory(writer, output, WRITER, (option or []) + (writer_option or []))
|
||||||
|
|
||||||
|
filters = resolve_filters(filter)
|
||||||
|
|
||||||
graph = bonobo.Graph()
|
graph = bonobo.Graph()
|
||||||
graph.add_chain(
|
graph.add_chain(
|
||||||
reader_factory(input, **reader_options),
|
reader_factory(input, **reader_option),
|
||||||
writer_factory(output, **writer_options),
|
*filters,
|
||||||
|
writer_factory(output, **writer_option),
|
||||||
)
|
)
|
||||||
|
|
||||||
return bonobo.run(
|
return bonobo.run(
|
||||||
@ -92,25 +123,39 @@ def register(parser):
|
|||||||
'-w',
|
'-w',
|
||||||
help='Choose the writer factory if it cannot be detected from extension, or if detection is wrong.'
|
help='Choose the writer factory if it cannot be detected from extension, or if detection is wrong.'
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--filter',
|
||||||
|
'-f',
|
||||||
|
dest='filter',
|
||||||
|
action='append',
|
||||||
|
help='Add a filter between input and output',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--print',
|
||||||
|
'-p',
|
||||||
|
dest='do_print',
|
||||||
|
action='store_true',
|
||||||
|
help='Replace the output by a pretty printer.',
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--option',
|
'--option',
|
||||||
'-O',
|
'-O',
|
||||||
dest='options',
|
dest='option',
|
||||||
action='append',
|
action='append',
|
||||||
help='Add a named option to both reader and writer factories (i.e. foo="bar").'
|
help='Add a named option to both reader and writer factories (i.e. foo="bar").',
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--' + READER + '-option',
|
'--' + READER + '-option',
|
||||||
'-' + READER[0].upper(),
|
'-' + READER[0].upper(),
|
||||||
dest=READER + '_options',
|
dest=READER + '_option',
|
||||||
action='append',
|
action='append',
|
||||||
help='Add a named option to the reader factory.'
|
help='Add a named option to the reader factory.',
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--' + WRITER + '-option',
|
'--' + WRITER + '-option',
|
||||||
'-' + WRITER[0].upper(),
|
'-' + WRITER[0].upper(),
|
||||||
dest=WRITER + '_options',
|
dest=WRITER + '_option',
|
||||||
action='append',
|
action='append',
|
||||||
help='Add a named option to the writer factory.'
|
help='Add a named option to the writer factory.',
|
||||||
)
|
)
|
||||||
return execute
|
return execute
|
||||||
|
|||||||
@ -9,14 +9,23 @@ class _RequiredModule:
|
|||||||
|
|
||||||
|
|
||||||
class _RequiredModulesRegistry(dict):
|
class _RequiredModulesRegistry(dict):
|
||||||
|
@property
|
||||||
|
def pathname(self):
|
||||||
|
return os.path.join(os.getcwd(), os.path.dirname(inspect.getfile(inspect.stack()[1][0])))
|
||||||
|
|
||||||
def require(self, name):
|
def require(self, name):
|
||||||
if name not in self:
|
if name not in self:
|
||||||
bits = name.split('.')
|
bits = name.split('.')
|
||||||
pathname = os.path.join(os.getcwd(), os.path.dirname(inspect.getfile(inspect.stack()[1][0])))
|
filename = os.path.join(self.pathname, *bits[:-1], bits[-1] + '.py')
|
||||||
filename = os.path.join(pathname, *bits[:-1], bits[-1] + '.py')
|
|
||||||
self[name] = _RequiredModule(runpy.run_path(filename, run_name=name))
|
self[name] = _RequiredModule(runpy.run_path(filename, run_name=name))
|
||||||
return self[name]
|
return self[name]
|
||||||
|
|
||||||
|
|
||||||
|
class WorkingDirectoryModulesRegistry(_RequiredModulesRegistry):
|
||||||
|
@property
|
||||||
|
def pathname(self):
|
||||||
|
return os.getcwd()
|
||||||
|
|
||||||
|
|
||||||
registry = _RequiredModulesRegistry()
|
registry = _RequiredModulesRegistry()
|
||||||
require = registry.require
|
require = registry.require
|
||||||
|
|||||||
Reference in New Issue
Block a user