镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

object prototype chaining does not work correctly on proxied python objects #399

Open

Description

@zollqir

Describe your feature request here.

Proxied python objects currently do not have a proper prototype chain, and we are instead mimicking prototype chain behaviour by special-casing [[GetOwnPropertyDescriptor]] when the prop name is equal to a default prop name on the intended prototype.

For example, in:

import pythonmonkey as pm
l = [1, 2, 3]
pm.eval("(l) => l.pop()")(l)

l.pop is accomplished by us intercepting prop lookup on l, seeing that the prop name is "pop", and passing back our own implementation of pop that is special-cased for python lists. This has some interesting consequences:

pm.eval("(l) => Object.getPrototypeOf(l) === Array.prototype")(l) # True
pm.eval("(l) => l.pop === Array.prototype.pop")(l) # False, should be True
pm.eval("(l) => l.pop === l.pop")(l) # False!!, should DEFINITELY be True

I propose that we define our own classes/prototypes for our proxied objects, and have those classes/prototypes inherit from the respective mimicked types, like so:

listObject = []
dictObject = []
bytesObject = b""
iterObject = iter(())

class Class:
  pass
classObject = Class()

pm.eval("""
(listObject, dictObject, bytesObject, iterObject, classObject) => {
  assert(Object.getPrototypeOf(listObject) === PyListProxy.prototype);
  assert(Object.getPrototypeOf(dictObject) === PyDictProxy.prototype);
  assert(Object.getPrototypeOf(bytesObject) === PyBytesProxy.prototype);
  assert(Object.getPrototypeOf(iterObject) === PyIterProxy.prototype);
  assert(Object.getPrototypeOf(classObject) === PyObjectProxy.prototype);  // would be interesting if we could get python class 
  inheritance to be represented in the prototype chain with proxied Classes, though I don't think that's currently in scope, particularly since Python has true multiple inheritance

  assert(Object.getPrototypeOf(PyListProxy.prototype) === Array.prototype);
  assert(Object.getPrototypeOf(PyDictProxy.prototype) === Object.prototype);
  assert(Object.getPrototypeOf(PyBytesProxy.prototype) === Uint8Array.prototype);
  assert(Object.getPrototypeOf(PyIterProxy.prototype) === Object.prototype);
  assert(Object.getPrototypeOf(PyObjectProxy.prototype) === Object.prototype);
}
""")(listObject, dictObject, bytesObject, iterObject, classObject)

Code example

No response

Activity

  1. self-assigned this
    on Jul 30, 2024
  2. added this to the v1.0.0 milestone on Jul 30, 2024
  3. moved this from Backlog to In progress in PythonMonkey Kanban Boardon Jul 30, 2024
  4. wesgarland commented on Sep 4, 2024

    @wesgarland
    Collaborator

    Q: Is this holding up BiFrost 2? If so, how? If not, we should pull this from the 1.0 Milestone

    Some thoughts:

    • it should be possible to write the majority of this in JS and decorate the prototypes from C++ and/or Python as-needed
    • let's avoid adding more symbols to the global namespace, ctor funs can be in python.classes or something
  5. wiwichips commented on Sep 4, 2024

    @wiwichips
    Collaborator

    @wesgarland it is not holding up Bifrost2 - it was moved to the > V1.0.1 release (aka after 1.0 Milestone)

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions