File: Utils.hs

package info (click to toggle)
missingpy 0.10.0.2
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 464 kB
  • ctags: 42
  • sloc: haskell: 1,433; makefile: 129; ansic: 107
file content (147 lines) | stat: -rw-r--r-- 4,932 bytes parent folder | download | duplicates (2)
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)