Allow callable references in sqlite-utils convert, closes #686

This allows users to pass just a callable reference like `r.parsedate`
instead of `r.parsedate(value)` to the convert command. The code now
detects when the input evaluates to a callable and uses it directly.

Examples that now work:
- sqlite-utils convert my.db table col r.parsedate
- sqlite-utils convert my.db table col json.loads --import json
This commit is contained in:
Claude 2025-11-29 20:33:27 +00:00
commit 29b07222f5
No known key found for this signature in database
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"]