From a3df483c803ea6e45cf878025aa8a59d2c62f67e Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Fri, 10 Dec 2021 16:01:02 -0800 Subject: [PATCH] sqlite-utils convert db table column -, refs #353 --- docs/cli.rst | 10 ++++++++++ sqlite_utils/cli.py | 5 +++++ tests/test_cli_convert.py | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/docs/cli.rst b/docs/cli.rst index 1e3b330..1185c1a 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -1023,6 +1023,16 @@ You can specify Python modules that should be imported and made available to you '"\n".join(textwrap.wrap(value, 100))' \ --import=textwrap +Use a CODE value of `-` to read from standard input: + + $ cat mycode.py | sqlite-utils convert content.db articles headline - + +Where `mycode.py` contains a fragment of Python code that looks like this: + +```python +return value.upper() +``` + The transformation will be applied to every row in the specified table. You can limit that to just rows that match a ``WHERE`` clause using ``--where``:: $ sqlite-utils convert content.db articles headline 'value.upper()' \ diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index cd0be82..0345d55 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -2038,6 +2038,8 @@ def _generate_convert_help(): "value" is a variable with the column value to be converted. + Use "-" for CODE to read Python code from standard input. + The following common operations are available as recipe functions: """ ).strip() @@ -2120,6 +2122,9 @@ def convert( raise click.ClickException("Cannot use --multi with more than one column") if drop and not (output or multi): raise click.ClickException("--drop can only be used with --output or --multi") + if code == "-": + # Read code from standard input + code = sys.stdin.read() # If single line and no 'return', add the return if "\n" not in code and not code.strip().startswith("return "): code = "return {}".format(code) diff --git a/tests/test_cli_convert.py b/tests/test_cli_convert.py index 8ce5203..2c77c0c 100644 --- a/tests/test_cli_convert.py +++ b/tests/test_cli_convert.py @@ -515,3 +515,36 @@ def test_convert_where_multi(fresh_db_and_path): {"id": 1, "name": "Cleo", "upper": None}, {"id": 2, "name": "Bants", "upper": "BANTS"}, ] + + +def test_convert_code_standard_input(fresh_db_and_path): + db, db_path = fresh_db_and_path + db["names"].insert_all([{"id": 1, "name": "Cleo"}], pk="id") + result = CliRunner().invoke( + cli.cli, + [ + "convert", + db_path, + "names", + "name", + "-", + ], + input="value.upper()", + ) + assert 0 == result.exit_code, result.output + assert list(db["names"].rows) == [ + {"id": 1, "name": "CLEO"}, + ] + + +def test_convert_hyphen_workaround(fresh_db_and_path): + db, db_path = fresh_db_and_path + db["names"].insert_all([{"id": 1, "name": "Cleo"}], pk="id") + result = CliRunner().invoke( + cli.cli, + ["convert", db_path, "names", "name", '"-"'], + ) + assert 0 == result.exit_code, result.output + assert list(db["names"].rows) == [ + {"id": 1, "name": "-"}, + ]