From 7a43af232e4bc00bd227307665163614e225948b Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Fri, 10 Dec 2021 16:11:22 -0800 Subject: [PATCH] Support nested imports, closes #351 --- docs/cli.rst | 6 ++++++ sqlite_utils/cli.py | 2 +- tests/test_cli_convert.py | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/cli.rst b/docs/cli.rst index 1185c1a..6a39c1e 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -1023,6 +1023,12 @@ You can specify Python modules that should be imported and made available to you '"\n".join(textwrap.wrap(value, 100))' \ --import=textwrap +This supports nested imports as well, for example to use `ElementTree `__:: + + $ sqlite-utils convert content.db articles content \ + 'xml.etree.ElementTree.fromstring(value).attrib["title"]' \ + --import=xml.etree.ElementTree + Use a CODE value of `-` to read from standard input: $ cat mycode.py | sqlite-utils convert content.db articles headline - diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index 0345d55..c19339d 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -2137,7 +2137,7 @@ def convert( locals = {} globals = {"r": recipes, "recipes": recipes} for import_ in imports: - globals[import_] = __import__(import_) + globals[import_.split(".")[0]] = __import__(import_) exec(code_o, globals, locals) fn = locals["fn"] if dry_run: diff --git a/tests/test_cli_convert.py b/tests/test_cli_convert.py index 2c77c0c..8755600 100644 --- a/tests/test_cli_convert.py +++ b/tests/test_cli_convert.py @@ -93,6 +93,27 @@ def test_convert_import(test_db_and_path): ] == list(db["example"].rows) +def test_convert_import_nested(fresh_db_and_path): + db, db_path = fresh_db_and_path + db["example"].insert({"xml": ''}) + result = CliRunner().invoke( + cli.cli, + [ + "convert", + db_path, + "example", + "xml", + 'xml.etree.ElementTree.fromstring(value).attrib["name"]', + "--import", + "xml.etree.ElementTree", + ], + ) + assert 0 == result.exit_code, result.output + assert [ + {"xml": "Cleo"}, + ] == list(db["example"].rows) + + def test_convert_dryrun(test_db_and_path): db, db_path = test_db_and_path result = CliRunner().invoke(