brython-dev / brython

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

Issue with Symbol and BigInt from JavaScript #1417

Closed redradist closed 4 years ago

redradist commented 4 years ago

In the following Python code standard JavaScript primitive types (BigInt and Symbol) are missed:

from browser import document, console
import javascript

n = javascript.BigInt(2) # AttributeError: 'module' object has no attribute 'BigInt'
s = javascript.Symbol("abracadabra") # AttributeError: 'module' object has no attribute 'Symbol'

Below the Stacktraces for both this lines

Missed BigInt:

Traceback (most recent call last):
  File http://localhost:63344/WebPython/index.html?_ijt=g7iau0hssgdgcripk8geh4d91s/__main__ line 17, in <module>
    n = javascript.BigInt(2) # Missed BigInt symbol
AttributeError: 'module' object has no attribute 'BigInt'
brython.js:5389 Uncaught Error
    at Object._b_.AttributeError.$factory (eval at $make_exc (brython.js:7929), <anonymous>:41:354)
    at attr_error (brython.js:6844)
    at Object.$B.$getattr (brython.js:6960)
    at eval (eval at $B.loop (brython.js:5368), <anonymous>:21:41)
    at $B.loop (brython.js:5368)
    at idb_load (brython.js:5288)
    at IDBRequest.req.onsuccess (brython.js:5302)

Missed Symbol:

Traceback (most recent call last):
  File http://localhost:63344/WebPython/index.html?_ijt=g7iau0hssgdgcripk8geh4d91s/__main__ line 17, in <module>
    s = javascript.Symbol("abracadabra") # Missed Symbol symbol
AttributeError: 'module' object has no attribute 'Symbol'
brython.js:5389 Uncaught Error
    at Object._b_.AttributeError.$factory (eval at $make_exc (brython.js:7929), <anonymous>:41:354)
    at attr_error (brython.js:6844)
    at Object.$B.$getattr (brython.js:6960)
    at eval (eval at $B.loop (brython.js:5368), <anonymous>:21:41)
    at $B.loop (brython.js:5368)
    at idb_load (brython.js:5288)
    at IDBRequest.req.onsuccess (brython.js:5302)
PierreQuentel commented 4 years ago

For BigInt there is a problem : it's trivial to create an instance of the Javascript object (without including it in the javascript module, it's in the global Javascript namespace, so available through window):

Brython 3.8.9 on Netscape 5.0 (Windows)
>>> from browser import window
>>> window.BigInt(2)
<BigInt object>
>>> 

but operations on these objects are not supported

>>> b2 = window.BigInt(2)
>>> b3 = window.BigInt(3)
>>> b2 + b3
Traceback (most recent call last):
  File <string>, line 1, in <module>
TypeError: unsupported operand type(s) for +: 'JSObject' and 'JSObject'
>>> 

because these objects don't support all the dunder methods (__add__, __mul__, etc.). Implementing them is going to be less trivial, all the more so as operations between this type and Python numeric types should be supported (integers, floats, booleans...).

The most stairghtforward would be to implement javascript.BigInt to return a Python integer : this way, interaction with Python types would be supported.

redradist commented 4 years ago

@PierreQuentel

For BigInt there is a problem : it's trivial to create an instance of the Javascript object (without including it in the javascript module, it's in the global Javascript namespace, so available through window):

Brython 3.8.9 on Netscape 5.0 (Windows)
>>> from browser import window
>>> window.BigInt(2)
<BigInt object>
>>> 

but operations on these objects are not supported

>>> b2 = window.BigInt(2)
>>> b3 = window.BigInt(3)
>>> b2 + b3
Traceback (most recent call last):
  File <string>, line 1, in <module>
TypeError: unsupported operand type(s) for +: 'JSObject' and 'JSObject'
>>> 

because these objects don't support all the dunder methods (__add__, __mul__, etc.). Implementing them is going to be less trivial, all the more so as operations between this type and Python numeric types should be supported (integers, floats, booleans...).

The most stairghtforward would be to implement javascript.BigInt to return a Python integer : this way, interaction with Python types would be supported.

Yea, seems like it better to return Python integer ... I read documentation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt seems like there is not many special method, it would also nice to provide

And what about Symbol ?

PierreQuentel commented 4 years ago

@redradist The commit referenced above implements operations (addition, multiplication etc.) on instances created with window.BigInt, as shown in the examples in the test file

b1 = window.BigInt('23456')
b2 = window.BigInt('78901')
assert b1 + b2 == window.BigInt(str(23456 + 78901))
assert b1 - b2 == window.BigInt(str(23456 - 78901))
assert b1 * b2 == window.BigInt(str(23456 * 78901))
assert b1 % b2 == window.BigInt(str(23456 % 78901))

b3 = window.BigInt('2')
assert b1 ** b3 == window.BigInt(str(23456 ** 2))

for num in [1, 4.7]:
    try:
        b1 + num
        raise Exception("should have raised TypeError")
    except TypeError:
        pass

I have done nothing special for Symbol, I can't imagine useful use cases for this in a Python script.

redradist commented 4 years ago

@PierreQuentel

@redradist The commit referenced above implements operations (addition, multiplication etc.) on instances created with window.BigInt, as shown in the examples in the test file

b1 = window.BigInt('23456')
b2 = window.BigInt('78901')
assert b1 + b2 == window.BigInt(str(23456 + 78901))
assert b1 - b2 == window.BigInt(str(23456 - 78901))
assert b1 * b2 == window.BigInt(str(23456 * 78901))
assert b1 % b2 == window.BigInt(str(23456 % 78901))

b3 = window.BigInt('2')
assert b1 ** b3 == window.BigInt(str(23456 ** 2))

for num in [1, 4.7]:
    try:
        b1 + num
        raise Exception("should have raised TypeError")
    except TypeError:
        pass

I have done nothing special for Symbol, I can't imagine useful use cases for this in a Python script.

Thanks ;)

What do you meant by Symbol ? It does not work still ?

PierreQuentel commented 4 years ago

Yes, it works:

from browser import window

symbol = window.Symbol("test")
assert symbol.description == "test"
redradist commented 4 years ago

Yes, it works:

from browser import window

symbol = window.Symbol("test")
assert symbol.description == "test"

Cool !! Thanks, @PierreQuentel !!