From 3e961776e3b8a7b0b4c0fe1c9be27c1cfb24efbf Mon Sep 17 00:00:00 2001 From: Romain Dorgueil Date: Sun, 16 Jul 2017 18:45:49 +0200 Subject: [PATCH] [cli] First draft implementation of "convert" command, which builds a simple graph of reader+writer and executes it. --- Makefile | 2 +- Projectfile | 1 + bonobo/commands/convert.py | 61 ++++++++++++++++++++++++++++++++++++++ setup.py | 4 +-- 4 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 bonobo/commands/convert.py diff --git a/Makefile b/Makefile index 10094af..fcdc7e2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # This file has been auto-generated. # All changes will be lost, see Projectfile. # -# Updated at 2017-07-04 10:50:55.775681 +# Updated at 2017-07-16 18:44:56.169119 PACKAGE ?= bonobo PYTHON ?= $(shell which python) diff --git a/Projectfile b/Projectfile index 6fe6c2b..117dd76 100644 --- a/Projectfile +++ b/Projectfile @@ -29,6 +29,7 @@ python.setup( 'bonobo = bonobo.commands:entrypoint', ], 'bonobo.commands': [ + 'convert = bonobo.commands.convert:register', 'init = bonobo.commands.init:register', 'run = bonobo.commands.run:register', 'version = bonobo.commands.version:register', diff --git a/bonobo/commands/convert.py b/bonobo/commands/convert.py new file mode 100644 index 0000000..c29f31c --- /dev/null +++ b/bonobo/commands/convert.py @@ -0,0 +1,61 @@ +import mimetypes + +import bonobo + +SHORTCUTS = { + 'plain': 'text/plain', + 'txt': 'text/plain', + 'text': 'text/plain', + 'csv': 'text/csv', + 'json': 'application/json', +} + +REGISTRY = { + 'text/plain': (bonobo.FileReader, bonobo.FileWriter), + 'text/csv': (bonobo.CsvReader, bonobo.CsvWriter), + 'application/json': (bonobo.JsonReader, bonobo.JsonWriter), +} + + +def resolve_factory(name, filename, factory_type): + """ + Try to resolve which transformation factory to use for this filename. User eventually provided a name, which has + priority, otherwise we try to detect it using the mimetype detection on filename. + + """ + if name is None: + name = mimetypes.guess_type(filename)[0] + + if name in SHORTCUTS: + name = SHORTCUTS[name] + + if not name in REGISTRY: + raise RuntimeError('Could not resolve {factory_type} factory for {filename} ({name}). Try providing it explicitely using -{opt} .'.format(name=name, filename=filename, factory_type=factory_type, opt=factory_type[0])) + + if factory_type == 'reader': + return REGISTRY[name][0] + elif factory_type == 'writer': + return REGISTRY[name][1] + else: + raise ValueError('Invalid factory type.') + +def execute(input, output, reader=None, reader_options=None, writer=None, writer_options=None, options=None): + reader = resolve_factory(reader, input, 'reader')(input) + writer = resolve_factory(writer, output, 'writer')(output) + + graph = bonobo.Graph() + graph.add_chain(reader, writer) + + return bonobo.run(graph, services={ + 'fs': bonobo.open_fs(), + }) + +def register(parser): + parser.add_argument('input') + parser.add_argument('output') + parser.add_argument('--reader', '-r') + parser.add_argument('--writer', '-w') + parser.add_argument('--reader-option', '-ro', dest='reader_options') + parser.add_argument('--writer-option', '-wo', dest='writer_options') + parser.add_argument('--option', '-o', dest='options') + return execute diff --git a/setup.py b/setup.py index 89c9ccd..a925811 100644 --- a/setup.py +++ b/setup.py @@ -67,8 +67,8 @@ setup( }, entry_points={ 'bonobo.commands': [ - 'init = bonobo.commands.init:register', 'run = bonobo.commands.run:register', - 'version = bonobo.commands.version:register' + 'convert = bonobo.commands.convert:register', 'init = bonobo.commands.init:register', + 'run = bonobo.commands.run:register', 'version = bonobo.commands.version:register' ], 'console_scripts': ['bonobo = bonobo.commands:entrypoint'] },