brython-dev / brython

Brython (Browser Python) is an implementation of Python 3 running in the browser
BSD 3-Clause "New" or "Revised" License
6.4k stars 512 forks source link

Error setting a jsObject field from brython #2440

Closed benjie-git closed 6 months ago

benjie-git commented 6 months ago

I can set an object's field by index, but setting by dot notation is broken.

Running the following brython code:

from browser import window

window.jsObj = {}   # When I set up the jsObj here from a dict, it does not work
# window.jsObj = window.Object.new()    # When I set up the jsObj like this, it does work
window.jsObj["a"] = "hello"
window.jsObj.b = "there"   # This line only works if the jsObj was not originally created as a brython dict
window.console.log(window.jsObj)

When the jsObject is set up from javascript, or as window.Object.new(), I get {a: 'hello', b: 'there'} as expected, but when I set it up from brython as {}, I get {a: 'hello', Symbol(PYOBJ): {…}} with the value for the key 'b' missing. Both ways to set an object value from brython worked up through the previous release.

benjie-git commented 6 months ago

Expanding the minimal test case slightly, I use the following JS and brython code:

window.jsTest = function () {
    window.jsObj["c"] = "BEEP"
    window.jsObj.d = "BOOP"
}
from browser import window

window.jsObj = window.Object.new()    # When I set up the jsObj like this, it does work
# window.jsObj = {}   # When I set up the jsObj here from a dict, it does not work

window.jsObj["a"] = "hello"
window.jsObj.b = "there"   # This line only works if the jsObj was not originally created as a brython dict
window.jsTest()
window.console.log(window.jsObj)

print(window.jsObj.to_dict())
# print(window.jsObj)    # Uncomment this line, and comment the previous, when switching the jsObj setup line above

Running the above, I get:

{a: 'hello', b: 'there', c: 'BEEP', d: 'BOOP'}
{'a': 'hello', 'b': 'there', 'c': 'BEEP', 'd': 'BOOP'}

when switched to set up using a dict value, and printing without .to_dict(), I see just:

{a: 'hello', c: 'BEEP', d: 'BOOP', Symbol(PYOBJ): {…}}
{'a': 'hello'}

I'm not sure whether the right fix is to:

PierreQuentel commented 6 months ago

With the commit above, setting an attribute to a dictionary now raises the same error as CPython (in the current 3.13 version)

Brython 3.12.3 on Netscape 5.0 (Windows)
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {}
>>> d.b = 0
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'b' and no __dict__ for setting new attributes
>>> 

This is standard Python behaviour, it's the absence of error in previous Brython versions that was a bug.

benjie-git commented 6 months ago

Great! This feels right. Thank you!