diff --git a/src/Python/Inline/Eval.hs b/src/Python/Inline/Eval.hs index 8141ffb..759fc83 100644 --- a/src/Python/Inline/Eval.hs +++ b/src/Python/Inline/Eval.hs @@ -10,6 +10,7 @@ module Python.Inline.Eval , evalPyFunction -- * Source code , PyQuote(..) + , PyQuoteFun(..) , Code , codeFromText , codeFromString diff --git a/src/Python/Inline/Monad/QQ.hs b/src/Python/Inline/Monad/QQ.hs index 710e411..2d42caa 100644 --- a/src/Python/Inline/Monad/QQ.hs +++ b/src/Python/Inline/Monad/QQ.hs @@ -9,6 +9,7 @@ module Python.Inline.Monad.QQ , pye , pyf , pycode + , pyfun ) where @@ -17,7 +18,7 @@ import Language.Haskell.TH.Quote import Python.Internal.EvalQQ import Python.Internal.Eval import Python.Inline.Monad -import Python.Inline.QQ (pycode) +import Python.Inline.QQ (pycode,pyfun) diff --git a/src/Python/Inline/QQ.hs b/src/Python/Inline/QQ.hs index 11e3dcd..f8dfb69 100644 --- a/src/Python/Inline/QQ.hs +++ b/src/Python/Inline/QQ.hs @@ -43,6 +43,7 @@ module Python.Inline.QQ , pye , pyf , pycode + , pyfun ) where import Language.Haskell.TH.Quote @@ -122,3 +123,17 @@ pycode = QuasiQuoter , quoteType = error "quoteType" , quoteDec = error "quoteDec" } + +-- | Create quote of python code suitable for use with +-- 'Python.Inline.Eval.exec' +-- +-- It creates value of type @PyQuoteFun@ +-- +-- @since 0.3@ +pyfun :: QuasiQuoter +pyfun = QuasiQuoter + { quoteExp = \txt -> expQQ Fun txt + , quotePat = error "quotePat" + , quoteType = error "quoteType" + , quoteDec = error "quoteDec" + } diff --git a/src/Python/Internal/Eval.hs b/src/Python/Internal/Eval.hs index 2254498..f4b8aff 100644 --- a/src/Python/Internal/Eval.hs +++ b/src/Python/Internal/Eval.hs @@ -1104,10 +1104,10 @@ exec globals locals q = runProgram $ do -- @since 0.3 evalPyFunction :: Namespace global - => global -- ^ Global variables - -> PyQuote -- ^ Source code + => global -- ^ Global variables + -> PyQuoteFun -- ^ Source code -> Py PyObject -evalPyFunction globals (PyQuote code binder) = runProgram $ do +evalPyFunction globals (PyQuoteFun code binder) = runProgram $ do p_locals <- takeOwnership =<< progPy basicNewDict p_kwargs <- takeOwnership =<< progPy basicNewDict progPy $ do diff --git a/src/Python/Internal/EvalQQ.hs b/src/Python/Internal/EvalQQ.hs index 59dc22f..8297309 100644 --- a/src/Python/Internal/EvalQQ.hs +++ b/src/Python/Internal/EvalQQ.hs @@ -116,9 +116,10 @@ expQQ mode qq_src = do ] src_eval = prepareForEval mode antis src -- - [| PyQuote ($(TH.lift $ codeFromString src_eval)) - (mconcat $(TH.listE args)) - |] + case mode of + Eval -> [| PyQuote ($(TH.lift $ codeFromString src_eval)) (mconcat $(TH.listE args)) |] + Exec -> [| PyQuote ($(TH.lift $ codeFromString src_eval)) (mconcat $(TH.listE args)) |] + Fun -> [| PyQuoteFun ($(TH.lift $ codeFromString src_eval)) (mconcat $(TH.listE args)) |] antiSuffix :: String diff --git a/src/Python/Internal/Types.hs b/src/Python/Internal/Types.hs index dadafce..91a6730 100644 --- a/src/Python/Internal/Types.hs +++ b/src/Python/Internal/Types.hs @@ -20,6 +20,7 @@ module Python.Internal.Types , pyIO -- ** Python code wrappers , PyQuote(..) + , PyQuoteFun(..) , Code(..) , codeFromText , codeFromString @@ -147,6 +148,18 @@ data PyQuote = PyQuote } +-- | Quasiquoted body of python function which could be used by +-- 'Python.Inline.Eval.evalPyFunction'. Function body must be +-- wrapped in @_inline_python_@ function which quasiquoter +-- 'Python.Inline.QQ.pyfun' does automatically. +-- +-- @since 0.3@ +data PyQuoteFun = PyQuoteFun + { code :: !Code + , binder :: !DictBinder + } + + -- | UTF-8 encoded python source code. -- -- @since 0.2@ diff --git a/test/TST/Run.hs b/test/TST/Run.hs index 34beb5f..6bb10c7 100644 --- a/test/TST/Run.hs +++ b/test/TST/Run.hs @@ -186,6 +186,10 @@ testEvalExec = testGroup "eval/exec" assert m_hs.a == 12 assert m_hs.b == 'asd' |] + , testCase "evalPyFunction" $ runPy $ do + let n = 2 :: Int + x <- fromPy =<< evalPyFunction Temp [pyfun| return 100 * n_hs |] + liftIO $ Just (200::Int) @=? x ] testAsync :: TestTree