caketop / python-starlark-go

๐Ÿ Python bindings for starlark-go ๐Ÿ
https://python-starlark-go.readthedocs.io/
Apache License 2.0
20 stars 7 forks source link

Can't tell what starlark Builtin cannot be converted to Python #143

Closed colindean closed 1 year ago

colindean commented 1 year ago

I can't tell which property of the final output of my Starlark script is not convertible.

$ python3 test.py test.star
Traceback (most recent call last):
  File "/Users/Z003XC4/Source/Target/TargetOSS/python-poetry/test.py", line 12, in <module>
    print(s.eval("main([])"))
starlark_go.errors.ConversionError: Don't know how to convert *starlark.Builtin to Python value

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/Z003XC4/Source/Target/TargetOSS/python-poetry/test.py", line 14, in <module>
    print(e.backtrace)
AttributeError: 'ConversionError' object has no attribute 'backtrace'

Test code:

import sys

from starlark_go import Starlark
from starlark_go.errors import EvalError, ConversionError

s = Starlark()

with open(sys.argv[1], 'r') as input_file:
    s.exec(input_file.read())

try:
    print(s.eval("main([])"))
except (EvalError, ConversionError) as e:
    print(e.backtrace)

The test code is working with simple dictionaries so it might be something else fancier I'm (unknowingly) doing that's not resolving to something convertible.

jordemort commented 1 year ago

Can you share the Starlark that triggers this as well?

jordemort commented 1 year ago

It looks like you're trying to return a reference to a function somehow? A Builtin is a Go function that is callable from Starlark. I'd like for this module to support returning Callables back to Python but it doesn't at this time.

colindean commented 1 year ago

I introduce a print() of the final output and tracked it down to basically this:

"slack": {"needs": <built-in method keys of dict value>, 

and this is the minimum reproduction:

def stage_slack_notify(stage_names):
    return {"name": "slack", "needs": stage_names}

def main(ctx):
    build_stages = {"something": [], "something_else": []}

    stages = [build_stages] + [stage_slack_notify(build_stages.keys)]
    final = {
        'version': '1',
        'stages': stages,
    }

    print(final)

    return final

Can you spot the error?

Dict.keys() is a function and I forgot (). ๐Ÿ™ƒ PEBKAC.

But I still feel like there's a better way to communicate the error, perhaps by telling exactly what wasn't able to be converted, with some path to it if possible.

jordemort commented 1 year ago

Keeping track of the path to the value would be doable but maybe kinda ugly. I think we'd have to add a path parameter to every function in starlark_to_python.go and have starlark[Dict|Tuple|Set|List]ToPython append keys to it before passing it along to the next function.