Skip to content

JS’s classes cannot be used correctly in python #170

Closed

Description

@zanxueyan

Issue type

Bug

How did you install PythonMonkey?

Installed from pip

OS platform and distribution

Windows 11

Python version (python --version)

3.10

PythonMonkey version (pip show pythonmonkey)

0.2.1

Bug Description

When python calls js, it is not possible to modify the properties of a class through its methods.

consult:How to instantiate JS's classes in python?

Standalone code to reproduce the issue

//JS code
class Runoob {
  constructor(name, url) {
    this.name = name;
    this.url = url;
  }
  setname(name)
  {
      this.name = name;
      console.log("box");
      return this.name;
  }
}
//first Type:transmit the class
module.exports = Runoob

//secend Type: Create an instance pass an instance
pepole = new Runoob("ddd","www.baidu.com")

************
#python code


import pythonmonkey as pm

pep =pm.require("./pyreadjs")
#first Type Error:TypeError: class constructors must be invoked with 'new'

pep("ddd","www.baidu.com")
# but can't code like this:
#test = new pep("ddd","www.baidu.com")

print(pep.setname("test")) #can return OK
print(pep.name)     #NOT CHANGE

Relevant log output or backtrace

pythonmonkey.SpiderMonkeyError: TypeError: class constructors must be invoked with 'new'

Additional info if applicable

No response

What branch of PythonMonkey were you developing on? (If applicable)

No response

Activity

  1. wiwichips commented on Sep 14, 2023

    @wiwichips
    Collaborator

    Hi @zanxueyan , thank you so much for taking the time to play with PythonMonkey and submit this issue!

    Since Python lacks a new keyword for instantiating objects, we had to add a new(class) function to the PythonMonkey API. Here's a small example:

    import pythonmonkey as pm
    jsDateClass = pm.Date
    myDate = pm.new(jsDateClass)(0) # in js this would be: let myDate = new Date(0);

    Here's the change you would need to make to get your code working

    //JS code
    class Runoob {
      constructor(name, url) {
        this.name = name;
        this.url = url;
      }
      setname(name)
      {
          this.name = name;
          console.log("box");
          return this.name;
      }
    }
    //first Type:transmit the class
    module.exports = Runoob
    
    //secend Type: Create an instance pass an instance
    pepole = new Runoob("ddd","www.baidu.com")
    #python code
    
    
    import pythonmonkey as pm
    
    Runoob =pm.require("./pyreadjs")
    #first Type Error:TypeError: class constructors must be invoked with 'new'
    
    pep = pm.new(Runoob)("ddd","www.baidu.com")
    # but can't code like this:
    #test = new pep("ddd","www.baidu.com")
    
    print(pep.setname("test")) #can return OK
    print(pep.name)     #NOT CHANGE

    Running the python program results in the following output:

    box
    test
    ddd
    

    I changed a couple things in your python code here:

    1. Runoob = pm.require("./pyreadjs")
    • Get the JS class from pyreadjs.js
    1. pep = pm.new(Runoob)("ddd","www.baidu.com")
    • Instantiate a new Runoob and set a variable pep equal to it. I'm using the pm.new(Class)(args...) function to instantiate a new object

    I'm sorry you had this experience, we'll try to improve the error message or improve the documentation so more people don't run into this in the future. Thank you!!!

  2. zanxueyan commented on Sep 19, 2023

    @zanxueyan
    Author

    Thanks a lot!

  3. zanxueyan commented on Sep 27, 2023

    @zanxueyan
    Author

    `import pythonmonkey as pm

    Runoob = pm.require("./pyreadjs") # Get the JS class from pyreadjs.js

    pep = pm.new(Runoob)("ddd", "www.baidu.com") # Instantiated object
    print(pep.add(2, 3))
    pep.setname("test")
    print(pep.name) # You cannot get the value of the property directly in this way
    ##Whether you can support getting its value from an attribute???

    print(pep.getname()) # You need to use the built-in function to get the value`

  4. wiwichips commented on Sep 28, 2023

    @wiwichips
    Collaborator

    Hi @zanxueyan Good catch!!! - you're right, something is wrong here...

    import pythonmonkey as pm
    
    Runoob = pm.require("./pyreadjs") # Get the JS class from pyreadjs.js
    
    pep = pm.new(Runoob)("Will Pringle", "www.google.com") # Instantiated object
    pep.setname("Joseph")
    
    print(pep['name'])   # prints Will Pringle BUT SHOULD PRINT Joseph
    print(pep.name)      # prints Will Pringle BUT SHOULD PRINT Joseph
    print(pep.getname()) # prints Joseph

    I'll file a bug report - thank you so much for finding and reporting this error!

  5. wiwichips commented on Sep 28, 2023

    @wiwichips
    Collaborator

    @zanxueyan check this out: #172 (comment)

    seems to be another side effect of this bug - I'll notify you when we have it patched


    import pythonmonkey as pm
    
    pm.eval("""
    class Human {
      constructor(name)
      {
        this.name = name;
      }
    
      setName(name)
      {
        this.name = name;
      }
    
      getName()
      {
        return this.name;
      }
    }
    
    """)
    
    Human = pm.eval('Human')
    
    person = pm.new(Human)('Will')
    
    # setting it using setName
    person.setName('Joe')
    
    print(person.getName()) # prints "Joe"
    print(person.name) # prints "Will" but should print "Joe"!!!
    print(person['name']) # prints "Will" but should print "Joe"!!!
    
    # now try setting it directly 
    person.name = "Liang"
    
    print(person.getName()) # prints "Joe"
    print(person.name) # prints "Liang"!!!
    print(person['name']) # prints "Liang"!!!

    prints

    Joe
    Will
    Will
    Joe
    Liang
    Liang
    
    
  6. zanxueyan commented on Nov 6, 2023

    @zanxueyan
    Author

    @wiwichips Thank you very much! Are there any further optimization results at present? Looking forward to...

  7. wiwichips commented on Jan 31, 2024

    @wiwichips
    Collaborator

    This should be solved in the next release of PythonMonkey - not sure when that is - but I'll make sure to notify you @ zanxueyan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions