From 78cfc08b75776c4a5d130e928c074437de15bcfe Mon Sep 17 00:00:00 2001 From: jay groven Date: Mon, 3 Dec 2012 12:03:56 -0600 Subject: [PATCH 1/3] an attempt at making MissingPy work in GHC 7.6, but exceptions are not correct --- MissingPy.cabal | 2 +- Python/Exceptions.hs | 10 +++++----- Python/Types.hs | 2 ++ Python/Utils.hs | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/MissingPy.cabal b/MissingPy.cabal index 2a307c9..065984d 100644 --- a/MissingPy.cabal +++ b/MissingPy.cabal @@ -1,5 +1,5 @@ Name: MissingPy -Version: 0.10.6 +Version: 0.10.7 License: MIT Maintainer: Matt Brown Author: John Goerzen diff --git a/Python/Exceptions.hs b/Python/Exceptions.hs index 50719ab..e51f77d 100644 --- a/Python/Exceptions.hs +++ b/Python/Exceptions.hs @@ -58,14 +58,14 @@ import Python.Types ( ) import Data.Dynamic (fromDynamic) import Python.ForeignImports (pyErr_GivenExceptionMatches) -import Control.OldException (throwDyn, catchDyn, dynExceptions, Exception) +import Control.Exception (throw, catch, fromException, SomeException) {- | Execute the given IO action. If it raises a 'PyException', then execute the supplied handler and return its return value. Otherwise, process as normal. -} catchPy :: IO a -> (PyException -> IO a) -> IO a -catchPy = catchDyn +catchPy = catch {- | Like 'catchPy', with the order of arguments reversed. -} handlePy :: (PyException -> IO a) -> IO a -> IO a @@ -78,14 +78,14 @@ catchSpecificPy pyo action handlerfunc = let handler e = do d <- doesExceptionMatch e pyo if d then handlerfunc e - else throwDyn e + else throw e in catchPy action handler {- | Useful as the first argument to catchJust, tryJust, or handleJust. Return Nothing if the given exception is not a 'PyException', or the exception otherwise. -} -pyExceptions :: Exception -> Maybe PyException -pyExceptions exc = dynExceptions exc >>= fromDynamic +pyExceptions :: SomeException -> Maybe PyException +pyExceptions = fromException {- | When an exception is thrown, it is not immediately formatted. diff --git a/Python/Types.hs b/Python/Types.hs index 56d7ff6..3aabd0f 100644 --- a/Python/Types.hs +++ b/Python/Types.hs @@ -48,6 +48,7 @@ module Python.Types ( ) where +import Control.Exception ( Exception ) import Foreign (ForeignPtr) import Data.Typeable ( TyCon @@ -76,6 +77,7 @@ data PyException = PyException {excType :: PyObject, -- ^ Exception type } instance Show PyException where show x = excFormatted x +instance Exception PyException pyExceptionTc :: TyCon pyExceptionTc = mkTyCon "MissingPy.Python.Types.PyException" diff --git a/Python/Utils.hs b/Python/Utils.hs index 84e0e77..368ed12 100644 --- a/Python/Utils.hs +++ b/Python/Utils.hs @@ -68,7 +68,7 @@ import Python.ForeignImports ( import Foreign.C.Types (CInt) import Foreign.C (withCString) import Foreign (peek, Ptr, newForeignPtr, nullPtr, alloca, withForeignPtr) -import Control.OldException (throwDyn) +import Control.Exception (throw) {- | Convert a Ptr 'CPyObject' to a 'PyObject'. -} fromCPyObject :: Ptr CPyObject -> IO PyObject @@ -110,7 +110,7 @@ raisePyException = excTraceBack = otb, excFormatted = ""} pyErr_Clear - throwDyn exc + throw exc ))) {- do cpy <- getexc From 55f607f8122a1a542b0e28de49767985685c2131 Mon Sep 17 00:00:00 2001 From: jay groven Date: Mon, 3 Dec 2012 18:12:21 -0600 Subject: [PATCH 2/3] add instances for Bool and Maybe --- Python/Exceptions.hs | 1 + Python/ForeignImports.hsc | 10 ++++++++++ Python/Objects.hs | 22 ++++++++++++++++++++++ glue/glue.c | 10 ++++++++++ glue/glue.h | 2 ++ 5 files changed, 45 insertions(+) diff --git a/Python/Exceptions.hs b/Python/Exceptions.hs index e51f77d..9c8e9ad 100644 --- a/Python/Exceptions.hs +++ b/Python/Exceptions.hs @@ -59,6 +59,7 @@ import Python.Types ( import Data.Dynamic (fromDynamic) import Python.ForeignImports (pyErr_GivenExceptionMatches) import Control.Exception (throw, catch, fromException, SomeException) +import Prelude hiding ( catch ) {- | Execute the given IO action. diff --git a/Python/ForeignImports.hsc b/Python/ForeignImports.hsc index 31431a6..c62b739 100644 --- a/Python/ForeignImports.hsc +++ b/Python/ForeignImports.hsc @@ -201,6 +201,16 @@ foreign import ccall unsafe "glue.h PyImport_AddModule" foreign import ccall unsafe "glue.h hspy_none" cNone :: IO (Ptr CPyObject) +foreign import ccall unsafe "glue.h hspy_true" + cTrue :: IO (Ptr CPyObject) + +foreign import ccall unsafe "glue.h hspy_false" + cFalse :: IO (Ptr CPyObject) + +{- +foreign import ccall unsafe "glue.h PyBool_FromLong" + pyBool_FromLong :: CLong -> IO (Ptr CPyObject) +-} foreign import ccall unsafe "glue.h PyEval_InitThreads" cpy_InitThreads :: IO () diff --git a/Python/Objects.hs b/Python/Objects.hs index a493f37..7f69214 100644 --- a/Python/Objects.hs +++ b/Python/Objects.hs @@ -79,6 +79,7 @@ import Foreign.C.String ( import Foreign.Ptr (nullPtr) import Foreign.Storable (peek) import Foreign.Marshal.Alloc (alloca) +import Foreign (newForeignPtr_) import Python.ForeignImports ( cpyList_AsTuple , cpyObject_Call @@ -107,6 +108,10 @@ import Python.ForeignImports ( , pyTuple_Check , pyTuple_GetItem , pyTuple_Size + , py_decref + , cNone + , cTrue + , cFalse ) @@ -390,6 +395,10 @@ instance (FromPyObject a, FromPyObject b) => FromPyObject [(a, b)] where in do pyodict <- ((fromPyObject pydict)::IO [(PyObject, PyObject)]) mapM conv pyodict +instance ToPyObject a => ToPyObject (Maybe a) where + toPyObject Nothing = PyObject `fmap` (cNone >>= newForeignPtr_) + toPyObject (Just x) = toPyObject x + -------------------------------------------------- -- Strings @@ -451,6 +460,19 @@ instance FromPyObject Integer where return $ read longstr -------------------------------------------------- +-- Numbers, Python Bools + +instance ToPyObject Bool where + toPyObject True = cTrue >>= fromCPyObject + toPyObject False = cFalse>>= fromCPyObject + +instance FromPyObject Bool where + fromPyObject x = do + l <- fromPyObject x :: IO CLong + if l == 0 + then return False + else return True +-------------------------------------------------- -- Numbers, anything else. {- For these, we attempt to guess whether to handle it as an int or a long. -} diff --git a/glue/glue.c b/glue/glue.c index 5aa9210..3965dd7 100644 --- a/glue/glue.c +++ b/glue/glue.c @@ -54,6 +54,16 @@ PyObject *hspy_none(void) { return Py_None; } +PyObject *hspy_true(void) { + Py_INCREF(Py_True); + return Py_True; +} + +PyObject *hspy_false(void) { + Py_INCREF(Py_False); + return Py_False; +} + PyObject *glue_PyMapping_Keys(PyObject *o) { return PyMapping_Keys(o); } diff --git a/glue/glue.h b/glue/glue.h index 88bfe06..1876ccd 100644 --- a/glue/glue.h +++ b/glue/glue.h @@ -23,6 +23,8 @@ extern PyObject ** hspy_getexc(); extern int hspy_list_check(PyObject *o); extern int hspy_tuple_check(PyObject *o); extern PyObject *hspy_none(void); +extern PyObject *hspy_true(void); +extern PyObject *hspy_false(void); /* These are now macros */ extern PyObject *glue_PyMapping_Keys(PyObject *o); From e0e4d368f7030adfa078cd1cf0552a6e647f49ed Mon Sep 17 00:00:00 2001 From: jay groven Date: Wed, 19 Dec 2012 13:06:37 -0600 Subject: [PATCH 3/3] ByteString instances --- MissingPy.cabal | 2 +- Python/Objects.hs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/MissingPy.cabal b/MissingPy.cabal index 065984d..73b5ac2 100644 --- a/MissingPy.cabal +++ b/MissingPy.cabal @@ -44,7 +44,7 @@ Library MissingPy.FileArchive.BZip2, MissingPy.AnyDBM Other-Modules: Python.ForeignImports - Build-Depends: base == 4.*, MissingH>=1.0.1, anydbm>=1.0.5 + Build-Depends: base == 4.*, MissingH>=1.0.1, anydbm>=1.0.5, bytestring C-Sources: glue/glue.c glue/excglue.c Extensions: ForeignFunctionInterface, TypeSynonymInstances, FlexibleInstances diff --git a/Python/Objects.hs b/Python/Objects.hs index 7f69214..0eb9317 100644 --- a/Python/Objects.hs +++ b/Python/Objects.hs @@ -80,6 +80,7 @@ import Foreign.Ptr (nullPtr) import Foreign.Storable (peek) import Foreign.Marshal.Alloc (alloca) import Foreign (newForeignPtr_) +import Data.ByteString (ByteString, useAsCStringLen, packCStringLen) import Python.ForeignImports ( cpyList_AsTuple , cpyObject_Call @@ -424,6 +425,21 @@ instance FromPyObject String where ) ) +-- ByteString to PyObject +instance ToPyObject ByteString where + toPyObject bs = useAsCStringLen bs toPyObject + +instance FromPyObject ByteString where + fromPyObject x = withPyObject x (\po -> + alloca (\lenptr -> + alloca (\strptr -> + do pyString_AsStringAndSize po strptr lenptr + len <- peek lenptr + cstr <- peek strptr + packCStringLen (cstr, fromIntegral len) + ) ) ) + + -------------------------------------------------- -- Numbers, Python Ints