Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with Attributes on provided Python Objects #2

Open
abhillman opened this issue Nov 11, 2023 · 5 comments
Open

Issues with Attributes on provided Python Objects #2

abhillman opened this issue Nov 11, 2023 · 5 comments

Comments

@abhillman
Copy link

Observed behavior:
If a python object is exported, there isn't a way to access its attributes.

Expected behavior:
I'm not sure. Ideally attributes could be accessed. Short of that, some documentation about best-practice for being able to access the attribute of a python object from a different module.

Repro:

Store this in py-point.rkt:

#lang racket

(require pyffi)

;; initialize the python interpreter
(initialize)
(post-initialize)

;; define `Point` via `collections.namedtuple`
(import collections)
(run* "Point = collections.namedtuple('Point', 'x y')")

;; create a `Point` object and bind it 
(define py-point (run "Point(1, 2)"))

(provide py-point)

Store this in main.rkt:

#lang racket

(require "py-point.rkt")

;; Print out the point; this works.
(print py-point)

;; Attempt to access an attr on `py-point`; this fails.
(print py-point.x)

Run main.rkt:

$ racket main.rkt
main.rkt:9:7: py-point.x: unbound identifier
  in: py-point.x
  location...:
   main.rkt:9:7

Other stuff

Note that within py-point.rkt, attributes can be accessed:

$ cat py-point.rkt
#lang racket

(require pyffi)

;; initialize the python interpreter
(initialize)
(post-initialize)

;; define `Point` via `collections.namedtuple`
(import collections)
(run* "Point = collections.namedtuple('Point', 'x y')")

;; create a `Point` object and bind it
(define py-point (run "Point(1, 2)"))

(provide py-point)

(print py-point.x)

$ racket py-point.rkt
1
@abhillman abhillman changed the title Issues with Attributes on Python Objects Issues with Attributes on provided Python Objects Nov 11, 2023
@abhillman
Copy link
Author

abhillman commented Nov 11, 2023

Workaround appears to be to add a (require pyffi) statement in a module that wishes to access attributes on a given object. Ideally there's something better (I'm guessing there is, but I have not discovered it yet) that might be something like:

(require (prefix-in pyffi/ pyffi))
(require "py-point.rkt")

;; this doesn't exist, but I'm guessing something like it might
(pyffi/read-attr py-point 'x)

Related: #3

@abhillman
Copy link
Author

abhillman commented Nov 11, 2023

Oh cool! These seem to work as workarounds:

(require (prefix-in pyffi/ pyffi))
(require "py-point.rkt")

;; allows for attribute fetching with `pyffi` via `prefix-in`
(pyffi/getattr py-point "x")
(require pyffi)
(require "py-point.rkt")

;; allows for attribute fetching with `pyffi` via `prefix-in`
(getattr py-point "x")

@soegaard
Copy link
Owner

In this examle:

#lang racket
(require "py-point.rkt")
(print py-point.x)

The (require "py-point.rkt") imports the identifier py-point.
In #lang racket the syntax py-point.x is read as a the name of a single
identifier py-point.x with no relation to py-point, therefore
you get an "unbound identifier" error.

Now in #lang racket a reference to an unbound identifier py-point.x
expands into (#%top . py-point.x). The standard binding of #%top
simply generates the "unbound identifier" error.
However, we can use our own #%top to turn py-point.x into
something that references the attribute x of py-point.

One fix:

#lang racket
(require "py-point.rkt" (only-in pyffi #%top))
(print py-point.x)

which will display

(obj "Point" : Point(x=1, y=2))

Another way:

#lang racket
(require "py-point.rkt" pyffi)
(print py-point.x)

@abhillman
Copy link
Author

Wow! Very nice explanation and thank you!

@soegaard
Copy link
Owner

Note that you can do this:

#lang racket
(require "py-point.rkt" 
               (only-in pyffi #%top)
               (prefix-in pyffi/ pyffi))
(print py-point.x)

If you prefer to have the pyffi/ prefix and still want dot notation to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants