json-python 0.3.0.1 → 0.4.0.0
raw patch · 4 files changed
+358/−124 lines, 4 filesdep ~basedep ~template-haskell
Dependency ranges changed: base, template-haskell
Files
- Python.hs +245/−51
- cdefs.c +110/−0
- hello_world.c +0/−70
- json-python.cabal +3/−3
Python.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DeriveDataTypeable #-} module Python( module Str,@@ -20,7 +21,24 @@ defVVO, defVVV, defOOOO,+ defOOOV,+ defOOVO,+ defOOVV,+ defOVOO,+ defOVOV,+ defOVVO,+ defOVVV,+ defVOOO,+ defVOOV,+ defVOVO,+ defVOVV,+ defVVOO,+ defVVOV,+ defVVVO,+ defVVVV, PyObject,+ PythonException,+ exceptionType, ) where @@ -30,12 +48,16 @@ import Foreign (FunPtr, ForeignPtr) import Foreign.Ptr (Ptr, nullPtr) import Foreign.ForeignPtr (newForeignPtr, withForeignPtr)+import Foreign.Marshal.Alloc (free) import Data.Aeson (FromJSON, ToJSON, toJSON, encode, decode) import Data.ByteString.Lazy.Char8 (unpack, pack) import Data.IORef (IORef, newIORef, writeIORef, readIORef) import System.IO.Unsafe (unsafePerformIO) import qualified Data.Map as Map import Data.Maybe (fromJust)+import Data.List (elemIndex)+import Control.Exception (Exception, throw)+import Data.Typeable modules :: IORef (Map.Map String RawPyObject) modules = unsafePerformIO $ newIORef (Map.empty)@@ -43,8 +65,16 @@ data P type RawPyObject = (Ptr P) data PyObject a = PyObject (ForeignPtr P) deriving Show- +data PythonException = PyException { exceptionType :: String, exceptionValue :: String } | DecodeException + deriving (Typeable)++instance Show PythonException where+ show DecodeException = "DecodeException"+ show x = exceptionType x ++ "\n" ++ exceptionValue x++instance Exception PythonException+ foreign import ccall "getObject" c_getObject:: CString -> IO (RawPyObject) foreign import ccall "getObjectInModule" c_getObjectInModule :: CString -> CString -> IO (RawPyObject) foreign import ccall "execInModule" c_execInModule :: CString -> CString -> IO ()@@ -57,9 +87,11 @@ foreign import ccall "Py_BuildValue" py_BuildValueObject :: CString -> RawPyObject -> IO (RawPyObject) foreign import ccall "Py_BuildValue" py_BuildValueObject2 :: CString -> RawPyObject -> RawPyObject -> IO (RawPyObject) foreign import ccall "Py_BuildValue" py_BuildValueObject3 :: CString -> RawPyObject -> RawPyObject -> RawPyObject -> IO (RawPyObject)+foreign import ccall "Py_BuildValue" py_BuildValueObject4 :: CString -> RawPyObject -> RawPyObject -> RawPyObject -> RawPyObject -> IO (RawPyObject) foreign import ccall "PyObject_CallObject" pyObject_CallObject :: RawPyObject -> RawPyObject -> IO (RawPyObject) foreign import ccall "PyString_AsString" pyString_AsString :: RawPyObject -> IO CString foreign import ccall unsafe "gimmeFunc" gimmeFunc :: CInt -> IO (FunPtr (RawPyObject -> IO ()))+foreign import ccall "checkError" c_checkError :: IO CString exec :: String -> IO () exec s = withCString s pyRun_SimpleString@@ -72,6 +104,22 @@ execInModule moduleName payload = withCString2 payload moduleName c_execInModule +parseException :: String -> PythonException+parseException s = let (t, v) = splitAt (fromJust $ (elemIndex ',' s)) s+ (_, t2) = splitAt (fromJust $ (elemIndex '\'' t)) t+ (t3, _) = splitAt (fromJust $ (elemIndex '\'' (tail t2 ))) (tail t2 )+ in PyException { exceptionType = t3, exceptionValue = tail v }++checkError :: String -> IO ()+checkError funcdef = do+ cs <- c_checkError+ if cs == nullPtr+ then return ()+ else do+ s <- peekCString cs+ free cs+ throw $ parseException $ s ++ "\n----------------------------------------------------------------------\n" ++ funcdef+ initialize :: IO () initialize = do py_initialize@@ -87,30 +135,26 @@ jsonfunc = [str| def jsonfunc(argformats): def wrapper(f):- import simplejson as json+ import json import traceback- def new_f(*args):- new_args = []- for (x, format) in zip(args, argformats):- if format == 'J':- try:- new_x = json.loads(x)- except:- print('error processing %s' % x) - new_args.append(new_x)- else:- new_args.append(x)+ def json_wrapper(*args): try:+ new_args = []+ for (x, format) in zip(args, argformats):+ if format == 'V':+ new_x = json.loads(x)+ new_args.append(new_x)+ else:+ new_args.append(x) result = f(*new_args)- if argformats[-1] == 'J':+ if argformats[-1] == 'V': result = json.dumps(result)+ return result except Exception as ex:- print(traceback.format_exc())- result = None- if argformats[-1] == 'J':- result = json.dumps(result)- return result- return new_f+ assert("," not in str(type(ex)))+ ex.args = (traceback.format_exc(),)+ raise ex+ return json_wrapper return wrapper |] @@ -134,10 +178,12 @@ fromPyObject :: (FromJSON a) => PyObject b -> IO a fromPyObject (PyObject fr) = do r2 <- withForeignPtr fr $ \r -> peekCString =<< pyString_AsString r- return $ fromJust $ mydecode r2+ return $ case mydecode r2 of+ Just x -> x+ Nothing -> throw $ DecodeException -getFunc :: String -> IO RawPyObject-getFunc s = do+getFunc :: String -> String -> IO RawPyObject+getFunc s argTypes = do currentModules <- readIORef $ modules key <- return $ hash s if Map.member "initialized" currentModules then@@ -148,8 +194,11 @@ Nothing -> do execInModule key jsonfunc execInModule key s- execInModule key "export = jsonfunc('JJ')(export)"+ execInModule key $ "export = jsonfunc('" ++ argTypes ++ "')(export)" f' <- getObjectInModule key "export"+ if f' == nullPtr+ then error "NameError: name 'export' is not defined"+ else return () writeIORef modules (Map.insert (hash s) f' currentModules) return f' @@ -158,34 +207,37 @@ finalizer <- gimmeFunc 0 return . PyObject =<< newForeignPtr finalizer r -defO :: String -> IO (PyObject b)-defO s = do- f <- getFunc s+def1 :: String -> String -> IO (PyObject b)+def1 s argTypes = do+ f <- getFunc s argTypes r <- pyObject_CallObject f nullPtr+ checkError s newForeignPyPtr r -defOO :: String -> (PyObject a) -> IO (PyObject b)-defOO s (PyObject fx1) = do- f <- getFunc s+def2 :: String -> String -> (PyObject a) -> IO (PyObject b)+def2 s argTypes (PyObject fx1) = do+ f <- getFunc s argTypes p1 <- withForeignPtr fx1 $ \x1 -> withCString "(O)" (\cs -> py_BuildValueObject cs x1) (PyObject fp) <- newForeignPyPtr p1 r <- withForeignPtr fp $ \p -> pyObject_CallObject f p+ checkError s newForeignPyPtr r -defOOO :: String -> (PyObject a1) -> (PyObject a2) -> IO (PyObject b)-defOOO s (PyObject fx1) (PyObject fx2) = do- f <- getFunc s+def3 :: String -> String -> (PyObject a1) -> (PyObject a2) -> IO (PyObject b)+def3 s argTypes (PyObject fx1) (PyObject fx2) = do+ f <- getFunc s argTypes p1 <- withForeignPtr fx1 $ \x1 -> ( withForeignPtr fx2 $ \x2 -> ( withCString "(OO)" (\cs -> py_BuildValueObject2 cs x1 x2) )) (PyObject fp) <- newForeignPyPtr p1 r <- withForeignPtr fp $ \p -> pyObject_CallObject f p+ checkError s newForeignPyPtr r -defOOOO :: String -> (PyObject a1) -> (PyObject a2) -> (PyObject a3) -> IO (PyObject b)-defOOOO s (PyObject fx1) (PyObject fx2) (PyObject fx3) = do- f <- getFunc s+def4 :: String -> String -> (PyObject a1) -> (PyObject a2) -> (PyObject a3) -> IO (PyObject b)+def4 s argTypes (PyObject fx1) (PyObject fx2) (PyObject fx3) = do+ f <- getFunc s argTypes p1 <- withForeignPtr fx1 $ \x1 -> ( withForeignPtr fx2 $ \x2 -> ( withForeignPtr fx3 $ \x3 -> (@@ -193,62 +245,92 @@ ))) (PyObject fp) <- newForeignPyPtr p1 r <- withForeignPtr fp $ \p -> pyObject_CallObject f p+ checkError s newForeignPyPtr r +def5 :: String -> String -> (PyObject a1) -> (PyObject a2) -> (PyObject a3) -> (PyObject a4) -> IO (PyObject b)+def5 s argTypes (PyObject fx1) (PyObject fx2) (PyObject fx3) (PyObject fx4) = do+ f <- getFunc s argTypes+ p1 <- withForeignPtr fx1 $ \x1 -> (+ withForeignPtr fx2 $ \x2 -> (+ withForeignPtr fx3 $ \x3 -> (+ withForeignPtr fx4 $ \x4 -> (+ withCString "(OOOO)" (\cs -> py_BuildValueObject4 cs x1 x2 x3 x4) + ))))+ (PyObject fp) <- newForeignPyPtr p1+ r <- withForeignPtr fp $ \p -> pyObject_CallObject f p+ checkError s+ newForeignPyPtr r++defO :: String -> IO (PyObject b)+defO s = do+ fr <- def1 s "O" + return fr+ defV :: (FromJSON b) => String -> IO b-defV s = do- r <- defO s- b <- fromPyObject r+defV s = do+ fr <- def1 s "V" + b <- fromPyObject fr return b +defOO :: String -> (PyObject a1) -> IO (PyObject b)+defOO s x1 = do+ fr <- def2 s "OO" x1+ return fr+ defOV :: (FromJSON b) => String -> (PyObject a1) -> IO b defOV s x1 = do- r <- defOO s x1- b <- fromPyObject r+ fr <- def2 s "OV" x1+ b <- fromPyObject fr return b defVO :: (ToJSON a1) => String -> a1 -> IO (PyObject b) defVO s input1 = do x1 <- toPyObject input1- r <- defOO s x1- return r+ fr <- def2 s "VO" x1+ return fr defVV :: (ToJSON a1, FromJSON b) => String -> a1 -> IO b defVV s input1 = do x1 <- toPyObject input1- fr <- defOO s x1+ fr <- def2 s "VV" x1 b <- fromPyObject fr return b +defOOO :: String -> (PyObject a1) -> (PyObject a2) -> IO (PyObject b)+defOOO s x1 x2 = do+ fr <- def3 s "OOO" x1 x2+ return fr+ defOOV :: (FromJSON b) => String -> (PyObject a1) -> (PyObject a2) -> IO b defOOV s x1 x2 = do- fr <- defOOO s x1 x2+ fr <- def3 s "OOV" x1 x2 b <- fromPyObject fr return b defOVO :: (ToJSON a2) => String -> (PyObject a1) -> a2 -> IO (PyObject b) defOVO s x1 input2 = do x2 <- toPyObject input2- fr <- defOOO s x1 x2+ fr <- def3 s "OVO" x1 x2 return fr defOVV :: (ToJSON a2, FromJSON b) => String -> (PyObject a1) -> a2 -> IO b defOVV s x1 input2 = do x2 <- toPyObject input2- fr <- defOOO s x1 x2+ fr <- def3 s "OVV" x1 x2 b <- fromPyObject fr return b defVOO :: (ToJSON a1) => String -> a1 -> (PyObject a2) -> IO (PyObject b) defVOO s input1 x2 = do x1 <- toPyObject input1- fr <- defOOO s x1 x2+ fr <- def3 s "VOO" x1 x2 return fr defVOV :: (ToJSON a1, FromJSON b) => String -> a1 -> (PyObject a2) -> IO b defVOV s input1 x2 = do x1 <- toPyObject input1- fr <- defOOO s x1 x2+ fr <- def3 s "VOV" x1 x2 b <- fromPyObject fr return b @@ -256,13 +338,125 @@ defVVO s input1 input2 = do x1 <- toPyObject input1 x2 <- toPyObject input2- fr <- defOOO s x1 x2+ fr <- def3 s "VVO" x1 x2 return fr defVVV :: (ToJSON a1, ToJSON a2, FromJSON b) => String -> a1 -> a2 -> IO b defVVV s input1 input2 = do x1 <- toPyObject input1 x2 <- toPyObject input2- fr <- defOOO s x1 x2+ fr <- def3 s "VVV" x1 x2+ b <- fromPyObject fr+ return b++defOOOO :: String -> (PyObject a1) -> (PyObject a2) -> (PyObject a3) -> IO (PyObject b)+defOOOO s x1 x2 x3 = do+ fr <- def4 s "OOOO" x1 x2 x3+ return fr++defOOOV :: (FromJSON b) => String -> (PyObject a1) -> (PyObject a2) -> (PyObject a3) -> IO b+defOOOV s x1 x2 x3 = do+ fr <- def4 s "OOOV" x1 x2 x3+ b <- fromPyObject fr+ return b++defOOVO :: (ToJSON a3) => String -> (PyObject a1) -> (PyObject a2) -> a3 -> IO (PyObject b)+defOOVO s x1 x2 input3 = do+ x3 <- toPyObject input3+ fr <- def4 s "OOVO" x1 x2 x3+ return fr++defOOVV :: (ToJSON a3, FromJSON b) => String -> (PyObject a1) -> (PyObject a2) -> a3 -> IO b+defOOVV s x1 x2 input3 = do+ x3 <- toPyObject input3+ fr <- def4 s "OOVV" x1 x2 x3+ b <- fromPyObject fr+ return b++defOVOO :: (ToJSON a2) => String -> (PyObject a1) -> a2 -> (PyObject a3) -> IO (PyObject b)+defOVOO s x1 input2 x3 = do+ x2 <- toPyObject input2+ fr <- def4 s "OVOO" x1 x2 x3+ return fr++defOVOV :: (ToJSON a2, FromJSON b) => String -> (PyObject a1) -> a2 -> (PyObject a3) -> IO b+defOVOV s x1 input2 x3 = do+ x2 <- toPyObject input2+ fr <- def4 s "OVOV" x1 x2 x3+ b <- fromPyObject fr+ return b++defOVVO :: (ToJSON a2, ToJSON a3) => String -> (PyObject a1) -> a2 -> a3 -> IO (PyObject b)+defOVVO s x1 input2 input3 = do+ x2 <- toPyObject input2+ x3 <- toPyObject input3+ fr <- def4 s "OVVO" x1 x2 x3+ return fr++defOVVV :: (ToJSON a2, ToJSON a3, FromJSON b) => String -> (PyObject a1) -> a2 -> a3 -> IO b+defOVVV s x1 input2 input3 = do+ x2 <- toPyObject input2+ x3 <- toPyObject input3+ fr <- def4 s "OVVV" x1 x2 x3+ b <- fromPyObject fr+ return b++defVOOO :: (ToJSON a1) => String -> a1 -> (PyObject a2) -> (PyObject a3) -> IO (PyObject b)+defVOOO s input1 x2 x3 = do+ x1 <- toPyObject input1+ fr <- def4 s "VOOO" x1 x2 x3+ return fr++defVOOV :: (ToJSON a1, FromJSON b) => String -> a1 -> (PyObject a2) -> (PyObject a3) -> IO b+defVOOV s input1 x2 x3 = do+ x1 <- toPyObject input1+ fr <- def4 s "VOOV" x1 x2 x3+ b <- fromPyObject fr+ return b++defVOVO :: (ToJSON a1, ToJSON a3) => String -> a1 -> (PyObject a2) -> a3 -> IO (PyObject b)+defVOVO s input1 x2 input3 = do+ x1 <- toPyObject input1+ x3 <- toPyObject input3+ fr <- def4 s "VOVO" x1 x2 x3+ return fr++defVOVV :: (ToJSON a1, ToJSON a3, FromJSON b) => String -> a1 -> (PyObject a2) -> a3 -> IO b+defVOVV s input1 x2 input3 = do+ x1 <- toPyObject input1+ x3 <- toPyObject input3+ fr <- def4 s "VOVV" x1 x2 x3+ b <- fromPyObject fr+ return b++defVVOO :: (ToJSON a1, ToJSON a2) => String -> a1 -> a2 -> (PyObject a3) -> IO (PyObject b)+defVVOO s input1 input2 x3 = do+ x1 <- toPyObject input1+ x2 <- toPyObject input2+ fr <- def4 s "VVOO" x1 x2 x3+ return fr++defVVOV :: (ToJSON a1, ToJSON a2, FromJSON b) => String -> a1 -> a2 -> (PyObject a3) -> IO b+defVVOV s input1 input2 x3 = do+ x1 <- toPyObject input1+ x2 <- toPyObject input2+ fr <- def4 s "VVOV" x1 x2 x3+ b <- fromPyObject fr+ return b++defVVVO :: (ToJSON a1, ToJSON a2, ToJSON a3) => String -> a1 -> a2 -> a3 -> IO (PyObject b)+defVVVO s input1 input2 input3 = do+ x1 <- toPyObject input1+ x2 <- toPyObject input2+ x3 <- toPyObject input3+ fr <- def4 s "VVVO" x1 x2 x3+ return fr++defVVVV :: (ToJSON a1, ToJSON a2, ToJSON a3, FromJSON b) => String -> a1 -> a2 -> a3 -> IO b+defVVVV s input1 input2 input3 = do+ x1 <- toPyObject input1+ x2 <- toPyObject input2+ x3 <- toPyObject input3+ fr <- def4 s "VVVV" x1 x2 x3 b <- fromPyObject fr return b
+ cdefs.c view
@@ -0,0 +1,110 @@+#include <stdio.h>+#include <Python.h>+#include <string.h>++void print_object(PyObject* object)+{+ PyObject_Print(object, stdout, 0);+}++PyObject* getObject(const char* string_name)+{+ PyObject *evalModule;+ PyObject *evalDict;+ PyObject *evalVal;+ evalModule = PyImport_AddModule( (char*)"__main__" );+ evalDict = PyModule_GetDict( evalModule );+ evalVal = PyDict_GetItemString( evalDict, string_name);+ if ( PyErr_Occurred() ) {+ PyErr_Print();PyErr_Clear(); return NULL;+ }+ else {+ return evalVal;+ }+}++PyObject* getObjectInModule(const char* objectName, const char* moduleName)+{+ PyObject *evalModule;+ PyObject *evalDict;+ PyObject *evalVal;+ evalModule = PyImport_AddModule( moduleName );+ evalDict = PyModule_GetDict( evalModule );+ evalVal = PyDict_GetItemString( evalDict, objectName );+ if ( PyErr_Occurred() ) {+ PyErr_Print();PyErr_Clear(); return evalVal;+ }+ else {+ return evalVal;+ }+}++char* checkError() {+ if ( PyErr_Occurred() ) {+ //PyErr_Print();//PyErr_Clear();+ /* PyRun_SimpleString("traceback.format_exc()"); */+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;+ PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);+ /* print_object(exc_val); */+ /* printf("\n"); */+ /* print_object(exc_tb); */+ PyObject *exc_typ_string = PyObject_Str(exc_typ);+ PyObject *exc_val_string = PyObject_Str(exc_val);+ char *exc_typ_tmp = PyString_AsString(exc_typ_string);+ char *exc_val_tmp = PyString_AsString(exc_val_string);+ char *exc = malloc(strlen(exc_val_tmp) + strlen(exc_typ_tmp) + 1);+ strcpy(exc, exc_typ_tmp);+ strcat(exc, ",");+ strcat(exc, exc_val_tmp);+ Py_DECREF(exc_val_string);+ Py_DECREF(exc_typ_string);+ Py_XDECREF(exc_val);+ Py_XDECREF(exc_typ);+ Py_XDECREF(exc_tb);+ return exc;+ }+ else {+ return NULL;+ }+}++void execInModule(const char* payload, const char* moduleName) {+ PyObject *evalModule;+ PyObject *evalDict;+ PyObject *evalVal;+ evalModule = PyImport_AddModule(moduleName);+ PyObject *globals = PyModule_GetDict(evalModule);+ PyDict_SetItemString(globals, "__builtins__", PyEval_GetBuiltins());+ PyObject *locals = Py_BuildValue("{}");+ PyObject *result = PyRun_StringFlags(payload,+ Py_file_input,+ globals,+ globals,+ NULL);+ + if ( PyErr_Occurred() ) {PyErr_Print();PyErr_Clear();}+ /* if ( PyErr_Occurred() ) {PyErr_Clear();} */+ return;+}++void finalizer(PyObject* p) {+ Py_DecRef(p);+}++typedef void funcType(PyObject*);+typedef funcType * pFuncType;++pFuncType gimmeFunc(int dummy) {+ return &finalizer;+}+++/*int main() {*/+ /*Py_Initialize();*/+ /*[> PyRun_SimpleString("x = 3"); <]*/+ /*execInModule("def x(y):\n print(y)\n import traceback\n return 0", "foo");*/+ /*PyObject *x = getObjectInModule("x", "foo");*/+ /*PyObject *result = PyObject_CallObject(x, Py_BuildValue("(i)", 5));*/+ /*print_object(result);*/+ /*printf("\n");*/+/*}*/
− hello_world.c
@@ -1,70 +0,0 @@-#include <stdio.h>-#include <Python.h>-#include <string.h>--PyObject* getObject(const char* string_name)-{- PyObject *evalModule;- PyObject *evalDict;- PyObject *evalVal;- evalModule = PyImport_AddModule( (char*)"__main__" );- evalDict = PyModule_GetDict( evalModule );- evalVal = PyDict_GetItemString( evalDict, string_name);- return evalVal;-}--PyObject* getObjectInModule(const char* objectName, const char* moduleName)-{- PyObject *evalModule;- PyObject *evalDict;- PyObject *evalVal;- evalModule = PyImport_AddModule( moduleName );- evalDict = PyModule_GetDict( evalModule );- evalVal = PyDict_GetItemString( evalDict, objectName );- return evalVal;-}--void execInModule(const char* payload, const char* moduleName) {- PyObject *evalModule;- PyObject *evalDict;- PyObject *evalVal;- evalModule = PyImport_AddModule(moduleName);- PyObject *globals = PyModule_GetDict(evalModule);- PyDict_SetItemString(globals, "__builtins__", PyEval_GetBuiltins());- PyObject *locals = Py_BuildValue("{}");- PyObject *result = PyRun_StringFlags(payload,- Py_file_input,- globals,- globals,- NULL);- - if ( PyErr_Occurred() ) {PyErr_Print();PyErr_Clear();}- return;-}--void print_object(PyObject* object)-{- PyObject_Print(object, stdout, 0);-}--void finalizer(PyObject* p) {- Py_DecRef(p);-}--typedef void funcType(PyObject*);-typedef funcType * pFuncType;--pFuncType gimmeFunc(int dummy) {- return &finalizer;-}---/*int main() {*/- /*Py_Initialize();*/- /*[> PyRun_SimpleString("x = 3"); <]*/- /*execInModule("def x(y):\n print(y)\n import traceback\n return 0", "foo");*/- /*PyObject *x = getObjectInModule("x", "foo");*/- /*PyObject *result = PyObject_CallObject(x, Py_BuildValue("(i)", 5));*/- /*print_object(result);*/- /*printf("\n");*/-/*}*/
json-python.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: json-python-version: 0.3.0.1+version: 0.4.0.0 synopsis: Call python inline from haskell description: WARNING: Project in alpha. Call python from haskell with ease. homepage: http://stewart.guru@@ -20,8 +20,8 @@ -- main-is: Main.hs exposed-modules: Python, Str other-extensions: TemplateHaskell, ForeignFunctionInterface, QuasiQuotes, OverloadedStrings- build-depends: base >=4.6 && <4.7, template-haskell >=2.8 && <2.9, aeson >=0.8 && <0.9, bytestring >=0.10 && <0.11, containers >= 0.5, pureMD5 >= 2.0+ build-depends: base >=4.6 && < 4.8, template-haskell >=2.8, aeson >=0.8 && <0.9, bytestring >=0.10 && <0.11, containers >= 0.5, pureMD5 >= 2.0 -- hs-source-dirs: default-language: Haskell2010 PkgConfig-Depends: python- c-sources: hello_world.c+ c-sources: cdefs.c