module Python.Objects (
PyObject,
ToPyObject(..),
FromPyObject(..),
typeOf,
strOf,
reprOf,
showPyObject,
dirPyObject,
getattr,
hasattr,
setattr,
pyList_AsTuple,
pyObject_Call,
pyObject_CallHs,
pyObject_RunHs,
callMethodHs,
runMethodHs,
noParms,
noKwParms
)
where
import Python.Types
import Python.Utils
import Foreign.C.Types (
CLong
, CInt
, CDouble
)
import Foreign.C.String (
withCString
, peekCStringLen
, CStringLen
)
import Foreign.Ptr (nullPtr)
import Foreign.Storable (peek)
import Foreign.Marshal.Alloc (alloca)
import Python.ForeignImports (
cpyList_AsTuple
, cpyObject_Call
, pyDict_New
, pyFloat_AsDouble
, pyFloat_FromDouble
, pyInt_AsLong
, pyInt_FromLong
, pyList_Append
, pyList_Check
, pyList_GetItem
, pyList_New
, pyList_Size
, pyLong_FromString
, pyMapping_Items
, pyObject_Dir
, pyObject_GetAttrString
, pyObject_HasAttrString
, pyObject_Repr
, pyObject_SetAttrString
, pyObject_SetItem
, pyObject_Str
, pyObject_Type
, pyString_AsStringAndSize
, pyString_FromStringAndSize
, pyTuple_Check
, pyTuple_GetItem
, pyTuple_Size
)
class ToPyObject a where
toPyObject :: a -> IO PyObject
class FromPyObject a where
fromPyObject :: PyObject -> IO a
typeOf :: PyObject -> IO PyObject
typeOf x = withPyObject x (\pyo -> pyObject_Type pyo >>= fromCPyObject)
strOf :: PyObject -> IO String
strOf x = withPyObject x
(\pyo -> pyObject_Str pyo >>= fromCPyObject >>= fromPyObject)
reprOf :: PyObject -> IO String
reprOf x = withPyObject x
(\pyo -> pyObject_Repr pyo >>= fromCPyObject >>= fromPyObject)
showPyObject :: PyObject -> IO String
showPyObject x = do typestr <- typeOf x >>= strOf
contentstr <- strOf x
return $ typestr ++ ": " ++ contentstr
dirPyObject :: PyObject -> IO [String]
dirPyObject x = withPyObject x (\cpyo ->
do dr <- pyObject_Dir cpyo >>= fromCPyObject
fromPyObject dr
)
pyObject_CallHs :: (ToPyObject a, ToPyObject b, FromPyObject c) =>
PyObject
-> [a]
-> [(String, b)]
-> IO c
pyObject_CallHs callobj simpleargs kwargs =
pyObject_Hs callobj simpleargs kwargs >>= fromPyObject
pyObject_Hs :: (ToPyObject a, ToPyObject b) =>
PyObject
-> [a]
-> [(String, b)]
-> IO PyObject
pyObject_Hs callobj simpleargs kwargs =
let conv (k, v) = do v1 <- toPyObject v
return (k, v1)
in
do s <- mapM toPyObject simpleargs
k <- mapM conv kwargs
pyObject_Call callobj s k
pyObject_RunHs :: (ToPyObject a, ToPyObject b) =>
PyObject
-> [a]
-> [(String, b)]
-> IO ()
pyObject_RunHs callobj simpleargs kwargs =
pyObject_Hs callobj simpleargs kwargs >> return ()
callMethodHs_internal :: (ToPyObject a, ToPyObject b) =>
PyObject
-> String
-> [a]
-> [(String, b)]
-> IO PyObject
callMethodHs_internal pyo method args kwargs =
do mobj <- getattr pyo method
pyObject_Hs mobj args kwargs
callMethodHs :: (ToPyObject a, ToPyObject b, FromPyObject c) =>
PyObject
-> String
-> [a]
-> [(String, b)]
-> IO c
callMethodHs pyo method args kwargs =
callMethodHs_internal pyo method args kwargs >>= fromPyObject
runMethodHs :: (ToPyObject a, ToPyObject b) =>
PyObject
-> String
-> [a]
-> [(String, b)]
-> IO ()
runMethodHs pyo method args kwargs =
callMethodHs_internal pyo method args kwargs >> return ()
noParms :: [String]
noParms = []
noKwParms :: [(String, String)]
noKwParms = []
pyObject_Call :: PyObject
-> [PyObject]
-> [(String, PyObject)]
-> IO PyObject
pyObject_Call callobj simpleparams kwparams =
do pyosimple <- toPyObject simpleparams >>= pyList_AsTuple
pyokw <- toPyObject kwparams
cval <- withPyObject callobj (\ccallobj ->
withPyObject pyosimple (\cpyosimple ->
withPyObject pyokw (\cpyokw ->
cpyObject_Call ccallobj cpyosimple cpyokw)))
fromCPyObject cval
pyList_AsTuple :: PyObject -> IO PyObject
pyList_AsTuple x =
withPyObject x (\cpo -> cpyList_AsTuple cpo >>= fromCPyObject)
getattr :: PyObject -> String -> IO PyObject
getattr pyo s =
withPyObject pyo (\cpo ->
withCString s (\cstr ->
pyObject_GetAttrString cpo cstr >>= fromCPyObject))
hasattr :: PyObject -> String -> IO Bool
hasattr pyo s =
withPyObject pyo (\cpo ->
withCString s (\cstr ->
do r <- pyObject_HasAttrString cpo cstr >>= checkCInt
if r == 0
then return False
else return True
)
)
setattr :: PyObject
-> String
-> PyObject
-> IO ()
setattr pyo s setpyo =
withPyObject pyo (\cpo ->
withPyObject setpyo (\csetpyo ->
withCString s (\cstr ->
pyObject_SetAttrString cpo cstr csetpyo >>= checkCInt >> return ()
)))
instance ToPyObject [PyObject] where
toPyObject mainlist =
do l <- pyList_New 0
mapM_ (\pyo -> withPyObject pyo (\x -> pyList_Append l x >>= checkCInt)) mainlist
fromCPyObject l
instance FromPyObject [PyObject] where
fromPyObject x =
let worker cpyo =
do islist <- pyList_Check cpyo >>= checkCInt
istuple <- pyTuple_Check cpyo >>= checkCInt
if islist /= 0
then fromx pyList_Size pyList_GetItem cpyo
else if istuple /= 0
then fromx pyTuple_Size pyTuple_GetItem cpyo
else fail "Error fromPyObject to [PyObject]: Passed object not a list or tuple."
fromx sizefunc itemfunc cpyo = do size <- sizefunc cpyo
fromx_worker 0 size itemfunc cpyo
fromx_worker counter size itemfunc cpyo =
if counter >= size
then return []
else do thisitem <- itemfunc cpyo counter
py_incref thisitem
thisobj <- fromCPyObject thisitem
next <- fromx_worker (succ counter) size itemfunc cpyo
return $ thisobj : next
in
withPyObject x worker
instance ToPyObject [(PyObject, PyObject)] where
toPyObject mainlist =
do d <- pyDict_New
mapM_ (setitem d) mainlist
fromCPyObject d
where setitem l (key, value) =
withPyObject key (\keyo ->
withPyObject value (\valueo ->
pyObject_SetItem l keyo valueo >>= checkCInt))
instance FromPyObject [(PyObject, PyObject)] where
fromPyObject pydict = withPyObject pydict (\cpydict ->
do
items <- (pyMapping_Items cpydict >>= fromCPyObject):: IO PyObject
itemlist <- (fromPyObject items)::IO [[PyObject]]
return $ map list2tup itemlist
)
where list2tup x = case x of
x1:x2:[] -> (x1, x2)
_ -> error "Expected 2-tuples in fromPyObject dict"
instance ToPyObject a => ToPyObject [(a, PyObject)] where
toPyObject mainlist =
let conv (k, v) = do k1 <- toPyObject k
return (k1, v)
in mapM conv mainlist >>= toPyObject
instance FromPyObject a => FromPyObject [(a, PyObject)] where
fromPyObject pyo =
let conv (k, v) = do k1 <- fromPyObject k
return (k1, v)
in do list <- (fromPyObject pyo)::IO [(PyObject, PyObject)]
mapM conv list
instance (ToPyObject a, ToPyObject b) => ToPyObject [(a, b)] where
toPyObject mainlist =
let convone (i1, i2) = do oi1 <- toPyObject i1
oi2 <- toPyObject i2
return (oi1, oi2)
in do newl <- mapM convone mainlist
toPyObject newl
instance (FromPyObject a, FromPyObject b) => FromPyObject [(a, b)] where
fromPyObject pydict =
let conv (x, y) = do x1 <- fromPyObject x
y1 <- fromPyObject y
return (x1, y1)
in do pyodict <- ((fromPyObject pydict)::IO [(PyObject, PyObject)])
mapM conv pyodict
instance ToPyObject CStringLen where
toPyObject (x, len) =
pyString_FromStringAndSize x (fromIntegral len) >>= fromCPyObject
instance ToPyObject String where
toPyObject x = withCString x (\cstr -> toPyObject (cstr, length x))
instance FromPyObject String where
fromPyObject x = withPyObject x (\po ->
alloca (\lenptr ->
alloca (\strptr ->
do pyString_AsStringAndSize po strptr lenptr
len <- peek lenptr
cstr <- peek strptr
peekCStringLen (cstr, (fromIntegral) len)
)
)
)
instance ToPyObject CLong where
toPyObject x = pyInt_FromLong x >>= fromCPyObject
instance FromPyObject CLong where
fromPyObject x = withPyObject x pyInt_AsLong
instance ToPyObject CInt where
toPyObject x = toPyObject ((fromIntegral x)::CLong)
instance FromPyObject CInt where
fromPyObject x = do y <- (fromPyObject x)::IO CLong
return $ fromIntegral y
instance ToPyObject Integer where
toPyObject i =
let repr = show i
in withCString repr (\cstr ->
pyLong_FromString cstr nullPtr 10 >>= fromCPyObject)
instance FromPyObject Integer where
fromPyObject pyo =
do longstr <- strOf pyo
return $ read longstr
instance ToPyObject CDouble where
toPyObject x = pyFloat_FromDouble x >>= fromCPyObject
instance FromPyObject CDouble where
fromPyObject x = withPyObject x pyFloat_AsDouble
instance ToPyObject a => ToPyObject [a] where
toPyObject mainlist =
do newlist <- mapM toPyObject mainlist
toPyObject newlist
instance FromPyObject a => FromPyObject [a] where
fromPyObject pylistobj =
do pylist <- fromPyObject pylistobj
mapM fromPyObject pylist