1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
{- arch-tag: Python low-level utilities
Copyright (C) 2005 John Goerzen <jgoerzen@complete.org>
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 2 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{- |
Module : Python.Utils
Copyright : Copyright (C) 2005 John Goerzen
License : GNU GPL, version 2 or above
Maintainer : John Goerzen,
Maintainer : jgoerzen\@complete.org
Stability : provisional
Portability: portable
Python low-level utilities
Written by John Goerzen, jgoerzen\@complete.org
Please use sparingly and with caution. The documentation for their behavior
should be considered to be the source code.
-}
module Python.Utils (-- * Objects
fromCPyObject,
withPyObject,
maybeWithPyObject,
-- * Exceptions
raisePyException,
checkCInt,
-- * Environment
getDefaultGlobals,
pyImport_AddModule,
pyModule_GetDict,
py_incref
)
where
import Python.Types
import Python.ForeignImports
import Foreign.C.Types
import Foreign.C
import Foreign
import Foreign.Ptr
import Foreign.Marshal.Array
import Foreign.Marshal.Alloc
import Control.Exception
{- | Convert a Ptr 'CPyObject' to a 'PyObject'. -}
fromCPyObject :: Ptr CPyObject -> IO PyObject
fromCPyObject po =
if po == nullPtr
then raisePyException
else do fp <- newForeignPtr py_decref po
return $ PyObject fp
{- | Called to make sure the passed CInt isn't -1. Raise an exception if
it is. -}
checkCInt :: CInt -> IO CInt
checkCInt x =
if x == (-1)
then raisePyException
else return x
{- | Called when a Python exception has been detected. It will raise
the exception in Haskell. -}
raisePyException :: IO a
raisePyException =
let noneorptr cval = if cval == nullPtr
then do p <- cNone
fromCPyObject p
else fromCPyObject cval
in alloca (\typeptr -> alloca (\valptr -> alloca (\tbptr ->
do pyErr_Fetch typeptr valptr tbptr
pyErr_NormalizeException typeptr valptr tbptr
ctype <- peek typeptr
cval <- peek valptr
ctb <- peek tbptr
otype <- noneorptr ctype
oval <- noneorptr cval
otb <- noneorptr ctb
--seq otype $ return ()
--seq oval $ return ()
--seq otb $ return ()
let exc = PyException {excType = otype, excValue = oval,
excTraceBack = otb,
excFormatted = ""}
pyErr_Clear
throwDyn exc
)))
{-
do cpy <- getexc
let (exc, val, tb) = cpy
--pyErr_Print
fail "Python Error!"
where getexc = do cexc <- hspy_getexc
exc <- peekArray 3 cexc
exc2 <- mapM fromCPyObject exc
case exc2 of
[x, y, z] -> return (x, y, z)
_ -> fail "Got unexpected number of elements"
-}
{- | Uses a 'PyObject' in a function that needs Ptr 'CPyObject'. -}
withPyObject :: PyObject -> (Ptr CPyObject -> IO b) -> IO b
withPyObject (PyObject x) = withForeignPtr x
{- | Same as 'withPyObject', but uses nullPtr if the input is Nothing. -}
maybeWithPyObject :: Maybe PyObject -> (Ptr CPyObject -> IO b) -> IO b
maybeWithPyObject Nothing func = func nullPtr
maybeWithPyObject (Just x) y = withPyObject x y
{- | Returns the default globals environment. -}
getDefaultGlobals :: IO PyObject
getDefaultGlobals =
do m <- pyImport_AddModule "__main__"
pyModule_GetDict m
{- | Wrapper around C PyImport_AddModule, which looks up an existing module -}
pyImport_AddModule :: String -> IO PyObject
pyImport_AddModule x =
withCString x (\cstr ->
do r <- cpyImport_AddModule cstr
py_incref r
fromCPyObject r
)
{- | Gets the dict associated with a module. -}
pyModule_GetDict :: PyObject -> IO PyObject
pyModule_GetDict x =
withPyObject x (\cpyo ->
do r <- cpyModule_GetDict cpyo
py_incref r
fromCPyObject r)
|