sqlite-utils convert can now use callable references, closes #686

This now works:

    echo '{"date": "13th January 2025"}' | sqlite-utils insert dates.db dates -
    sqlite-utils convert dates.db dates date r.parsedate
    sqlite-utils rows dates.db dates

Previously the command would have been:

    sqlite-utils convert dates.db dates date 'r.parsedate(value)'
This commit is contained in:
Simon Willison 2025-11-29 14:43:02 -08:00 committed by GitHub
commit 5a7f522980
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 74 additions and 3 deletions

View file

@ -450,6 +450,10 @@ def progressbar(*args, **kwargs):
def _compile_code(code, imports, variable="value"):
globals = {"r": recipes, "recipes": recipes}
# Handle imports first so they're available for all approaches
for import_ in imports:
globals[import_.split(".")[0]] = __import__(import_)
# If user defined a convert() function, return that
try:
exec(code, globals)
@ -457,6 +461,15 @@ def _compile_code(code, imports, variable="value"):
except (AttributeError, SyntaxError, NameError, KeyError, TypeError):
pass
# Check if code is a direct callable reference
# e.g. "r.parsedate" instead of "r.parsedate(value)"
try:
fn = eval(code, globals)
if callable(fn):
return fn
except Exception:
pass
# Try compiling their code as a function instead
body_variants = [code]
# If single line and no 'return', try adding the return
@ -478,8 +491,6 @@ def _compile_code(code, imports, variable="value"):
if code_o is None:
raise SyntaxError("Could not compile code")
for import_ in imports:
globals[import_.split(".")[0]] = __import__(import_)
exec(code_o, globals)
return globals["fn"]