Skip to content

Commit

Permalink
added support for keyword arguments in define-pymethod;
Browse files Browse the repository at this point in the history
bug fix in dictionary object conversion;
added example of using h5py
  • Loading branch information
iraikov committed Jun 11, 2016
1 parent 98435d4 commit 83029d5
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 77 deletions.
54 changes: 50 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ a pointer to a Python value. The arguments must be either Scheme
values of types listed in the type conversion table above, or pointers
to Python values.

`(py-object-type value)`

Returns the type string of the given Python object.

`(py-object-to value)`

Returns the Python representation of the given Scheme object.

`(py-object-from)`

Returns the Scheme representation of the given Python object, or the corresponding pointer.


## Macros

Expand Down Expand Up @@ -94,12 +106,13 @@ a modifier for that slot.



`(define-pymethod NAME [SCHEME-NAME])`
`(define-pymethod NAME [SCHEME-NAME: NAME] [KW: ARGS])`

Defines an accessor for the Python method `NAME`. The optional
Defines an accessor for the Python method `NAME`. The optional keyword
argument `SCHEME-NAME` is an alternate name for the Scheme
procedure. The accessor is a procedure of the form `LAMBDA OBJ ARG1 ...`
that takes in a Python object `OBJ` and invokes the method
procedure. The optional keyword argument `KW` is a list of keyword
argument names. The accessor is a procedure of the form `LAMBDA OBJ
ARG1 ...` that takes in a Python object `OBJ` and invokes the method
`NAME` contained in that object, with the supplied arguments, which
must be either Scheme values of types listed in the type conversion
table above, or pointers to Python values. If the object has no such
Expand All @@ -109,6 +122,39 @@ method, #f is returned.

## Examples

### h5py

```scheme
(import chicken)
(require-extension pyffi)
(py-start)
(py-import "h5py")
(py-import "numpy")
(define-pyfun "h5py.File" name mode)
(define-pymethod "close") ;; File
(define-pymethod "create_dataset" kw: (dtype)) ;; File
(define-pyslot "shape")
(define-pyslot "dtype")
(define-pyslot "name")
(define f (h5py.File "mytestfile.hdf5" "w"))
(define dset (create_dataset f "mydataset" (vector 100) dtype: "i"))
(print (py-object-from (name dset)))
(print (py-object-from (shape dset)))
(print (py-object-type (dtype dset)))
(close f)
```

### Python-UNO

```scheme
;;
;; Python-UNO example from pyffi.lisp by Dmitri Hrapof.
Expand Down
58 changes: 0 additions & 58 deletions example.scm

This file was deleted.

44 changes: 44 additions & 0 deletions examples/h5py.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
;;
;; Example from Python h5py documentation.
;;
;;
;; This program is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; A full copy of the GPL license can be found at
;; <http://www.gnu.org/licenses/>.
;;

(import chicken)
(require-extension pyffi)

(py-start)

(py-import "h5py")
(py-import "numpy")


(define-pyfun "h5py.File" name mode)
(define-pymethod "close") ;; File
(define-pymethod "create_dataset" kw: (dtype)) ;; File

(define-pyslot "shape")
(define-pyslot "dtype")
(define-pyslot "name")

(define f (h5py.File "mytestfile.hdf5" "w"))

(define dset (create_dataset f "mydataset" (vector 100) dtype: "i"))

(print (py-object-from (name dset)))
(print (py-object-from (shape dset)))
(print (py-object-type (dtype dset)))

(close f)
File renamed without changes.
66 changes: 53 additions & 13 deletions pyffi.scm
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@

(module pyffi

(py-start py-stop py-import py-eval py-apply
raise-python-exception
(py-start py-stop py-import py-eval py-apply py-object-type py-object-to py-object-from
raise-python-exception python-exception-string
*py-functions*
(define-pyfun PyCallable_Check Py_DecRef )
(define-pyslot PyObject_GetAttrString PyObject_SetAttrString )
(define-pymethod PyObject_GetAttrString PyObject_CallObject ))
(define-pymethod PyObject_GetAttrString PyObject_CallObject PyObject_Call ))


(import scheme chicken lolevel srfi-1 srfi-4 srfi-69 data-structures foreign)
Expand Down Expand Up @@ -101,6 +101,9 @@
(Py_IncRef value)
value)))))

(define (py-object-type value)
(PyObject_Type_asString value))

;; Embed, but do not parse
#>

Expand Down Expand Up @@ -231,6 +234,7 @@ int PyList_SetItem (PyObject *, int, pyobject);

pyobject PyModule_GetDict (PyObject *);
pyobject PyObject_CallObject (PyObject *, pyobject);
pyobject PyObject_Call (PyObject *, pyobject, pyobject);

PyObject *PyObject_GetAttrString (PyObject *, const char *);
int PyObject_SetAttrString (PyObject *, const char *, pyobject);
Expand Down Expand Up @@ -309,6 +313,10 @@ EOF
(print-error-message desc)
(signal (pyerror-exn desc))))

(define (python-exception-string)
(let* ((desc (PyErr_Occurred_asString)))
desc))

(define-pytype py-int PyInt_FromLong PyInt_AsLong)

(define-pytype py-tuple
Expand Down Expand Up @@ -365,7 +373,8 @@ EOF
(define (utf8-string->py-unicode value)
;; Given a Scheme UTF8 string, converts it into Python Unicode string
(let ((str (list->s32vector (map char->integer (utf8-string->list value)))))
(pyffi_PyUnicode_FromUnicode str (s32vector-length str))))
(let ((res (pyffi_PyUnicode_FromUnicode str (s32vector-length str))))
res)))

(define (py-unicode->utf8-string value)
;; Given a Python Unicode string, converts it into Scheme UTF8 string
Expand All @@ -390,7 +399,9 @@ EOF
(if (not (zero? (PyDict_SetItem dct k v)))
(raise-python-exception)))
(else (pyffi:error 'py-dict "invalid alist pair " kv))))
value)))
value)
dct
))
;; Given a Python dictionary, converts it into a Scheme alist
(lambda (value)
(let ((its (PyDict_Items value)))
Expand Down Expand Up @@ -524,19 +535,48 @@ EOF
(lambda (x r c)
(let ((name (cadr x))
(rest (cddr x)))
(let-optionals rest ((scheme-name #f))
(let ((scheme-name (member 'scheme-name: rest))
(kw (member 'kw: rest)))
(let ((%define (r 'define))
(or (r 'or))
(%quote (r 'quote))
(%cons (r 'cons))
(%list (r 'list))
(%filter (r 'filter))
(%take-while (r 'take-while))
(%lambda (r 'lambda))
(%symbol? (r 'symbol?))
(%null? (r 'null?))
(%and (r 'and))
(%not (r 'not))
(%if (r 'if))
(list->vector (r 'list->vector))
(PyObject_GetAttrString (r 'PyObject_GetAttrString))
(PyObject_CallObject (r 'PyObject_CallObject))
(name (string->symbol (or scheme-name name)))
(PyObject_Call (r 'PyObject_Call))
(name (string->symbol (or (and scheme-name (cadr scheme-name)) name)))
(obj (r 'obj))
(rest (r 'rest)))
`(,%define (,name ,obj . ,rest)
(,PyObject_CallObject
(,PyObject_GetAttrString ,obj ,(->string name) )
(,list->vector ,rest))))))))
(rest (r 'rest))
)
(if (not kw)
`(,%define (,name ,obj #!rest ,rest)
(,PyObject_CallObject
(,PyObject_GetAttrString ,obj ,(->string name) )
(,list->vector ,rest)))
(let ((kwargs (cadr kw)))
`(,%define (,name ,obj #!rest ,rest #!key ,@(map (lambda (x) (list x #f)) kwargs))
(let ((kwargs (,%filter identity
(,%list
,@(map (lambda (k x) `(,%and ,x (,%list (->string (quote ,k)) ,x))) kwargs kwargs)))))
(,PyObject_Call
(,PyObject_GetAttrString ,obj ,(->string name) )
(,list->vector (,%take-while (,%lambda (x) (,%not (,%symbol? x))) ,rest))
(,%if (,%null? kwargs) #f kwargs))
))
))
))
))
)



)
4 changes: 2 additions & 2 deletions pyffi.setup
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@
(define (dynld-name fn)
(make-pathname #f fn ##sys#load-dynamic-extension))

(compile -O2 -d0 -I. -s pyffi.scm -j pyffi
(compile -O -d2 -I. -s pyffi.scm -j pyffi
-L "\"" ,ld-options "\"" -C "\"" ,c-options "\"" )
(compile -O2 -d0 -s pyffi.import.scm)

(install-extension
'pyffi
`(,(dynld-name "pyffi") ,(dynld-name "pyffi.import") )
`((version 3.1)))
`((version 3.3)))

0 comments on commit 83029d5

Please sign in to comment.