TranscryptOrg / Transcrypt

Python 3.9 to JavaScript compiler - Lean, fast, open!
https://www.transcrypt.org
Apache License 2.0
2.82k stars 215 forks source link

Dictionary unpacking causes a transpiling error #837

Open tomkcook opened 1 year ago

tomkcook commented 1 year ago

Example:

#__pragma__('skip')
def el(name, attrs, *children):
    pass
#__pragma__('noskip')
def App():
    return el("div", {
        **{'class': 'my-class'}
    })

Transcrypt output:

$ python3 -m transcrypt test.py

Transcrypt (TM) Python to JavaScript Small Sane Subset Transpiler Version 3.9.0
Copyright (C) Geatec Engineering. License: Apache 2.0

Saving target code in: /home/tkcook/git/test/__target__/org.transcrypt.__runtime__.js
Saving minified target code in: /home/tkcook/git/test/__target__/org.transcrypt.__runtime__.js

Error while compiling (offending file last):
    File 'test', line 6, namely:

    Error while compiling (offending file last):
    File 'test', line 6, namely:

Aborted

The dictionary unpack is obviously redundant in this case but is useful in more complex cases.

JennaSys commented 1 year ago

There must be an edge case somewhere in the compiler. With a slightly simpler example, this works:

def test(args):
    print(list(args.keys()))

test(dict(**{'class': 'my-class'}))

But this does not:

def test(args):
    print(list(args.keys()))

test({**{'class': 'my-class'}})

Though both versions work in CPython.

mentalisttraceur commented 1 year ago

Those last two examples are actually significantly different at the technical/language level, and the latter is actually a lot newer in CPython.

  1. dict(**a_dictionary) is a splatting a dictionary into arguments of a function call. In Python since 2.2 (over 20 years ago).
  2. {**a_dictionary} is splatting a dictionary into a dictionary literal "display". Added in 3.5 by PEP-448.

If I had to guess, Transcrypt has different code paths for "translating the stuff inside a function call" and "translating the stuff inside a dictionary display", and the former is expecting the possibility of a ** while the latter isn't.