ipython-kernel 0.6.0.0 → 0.6.1.0
raw patch · 7 files changed
+58/−177 lines, 7 filesdep −unix
Dependencies removed: unix
Files
- ipython-kernel.cabal +2/−6
- src/IHaskell/IPython/EasyKernel.hs +7/−21
- src/IHaskell/IPython/Message/Parser.hs +6/−5
- src/IHaskell/IPython/Message/Writer.hs +19/−15
- src/IHaskell/IPython/Stdin.hs +0/−113
- src/IHaskell/IPython/Types.hs +19/−16
- src/IHaskell/IPython/ZeroMQ.hs +5/−1
ipython-kernel.cabal view
@@ -1,5 +1,5 @@ name: ipython-kernel-version: 0.6.0.0+version: 0.6.1.0 synopsis: A library for creating kernels for IPython frontends description: ipython-kernel is a library for communicating with frontends for the interactive IPython framework. It is used extensively in IHaskell, the interactive Haskell environment.@@ -27,12 +27,10 @@ exposed-modules: IHaskell.IPython.Kernel IHaskell.IPython.Types IHaskell.IPython.ZeroMQ- IHaskell.IPython.Stdin IHaskell.IPython.Message.Writer IHaskell.IPython.Message.Parser IHaskell.IPython.Message.UUID IHaskell.IPython.EasyKernel- -- other-modules: other-extensions: OverloadedStrings hs-source-dirs: src default-language: Haskell2010@@ -47,12 +45,10 @@ tar >=0.4.0.1, text >=0.11, transformers >=0.3,- unix >=2.6, uuid >=1.3, zeromq4-haskell >=0.1, SHA >=1.6 - -- Example program executable simple-calc-example hs-source-dirs: examples@@ -64,6 +60,6 @@ parsec >=3.1, text >=0.11, transformers >=0.3- + if !flag(examples) buildable: False
src/IHaskell/IPython/EasyKernel.hs view
@@ -56,6 +56,7 @@ import IHaskell.IPython.Kernel import IHaskell.IPython.Message.UUID as UUID+import IHaskell.IPython.Types import System.Directory (createDirectoryIfMissing, doesDirectoryExist, doesFileExist, getHomeDirectory)@@ -89,7 +90,7 @@ , completion :: T.Text -> T.Text -> Int -> Maybe ([T.Text], T.Text, T.Text) -- | Return the information or documentation for its argument. The returned tuple consists of the -- name, the documentation, and the type, respectively.- , objectInfo :: T.Text -> Maybe (T.Text, T.Text, T.Text)+ , inspectInfo :: T.Text -> Maybe (T.Text, T.Text, T.Text) -- | Execute a cell. The arguments are the contents of the cell, an IO action that will clear the -- current intermediate output, and an IO action that will add a new item to the intermediate -- output. The result consists of the actual result, the status to be sent to IPython, and the@@ -155,7 +156,7 @@ -- | Execute an IPython kernel for a config. Your 'main' action should call this as the last thing -- it does.-easyKernel :: (MonadIO m)+easyKernel :: MonadIO m => FilePath -- ^ The connection file provided by the IPython frontend -> KernelConfig m output result -- ^ The kernel configuration specifying how to react to -- messages@@ -220,32 +221,17 @@ return ExecuteReply { header = replyHeader- , pagerOutput = pagerOut+ , pagerOutput = [DisplayData PlainText $ T.pack pagerOut] , executionCounter = fromIntegral counter , status = replyStatus } replyTo config _ _ req@CompleteRequest{} replyHeader = -- TODO: FIX- error "Unimplemented in IPython 3.0"+ error "Completion: Unimplemented for IPython 3.0" -replyTo config _ _ ObjectInfoRequest { objectName = obj } replyHeader =- return $- case objectInfo config obj of- Just (name, docs, ty) -> ObjectInfoReply- { header = replyHeader- , objectName = obj- , objectFound = True- , objectTypeString = ty- , objectDocString = docs- }- Nothing -> ObjectInfoReply- { header = replyHeader- , objectName = obj- , objectFound = False- , objectTypeString = ""- , objectDocString = ""- }+replyTo _ _ _ InspectRequest{} _ = do+ error $ "Inspection: Unimplemented for IPython 3.0" replyTo _ _ _ msg _ = do liftIO $ putStrLn "Unknown message: "
src/IHaskell/IPython/Message/Parser.hs view
@@ -74,7 +74,7 @@ parser KernelInfoRequestMessage = kernelInfoRequestParser parser ExecuteRequestMessage = executeRequestParser parser CompleteRequestMessage = completeRequestParser-parser ObjectInfoRequestMessage = objectInfoRequestParser+parser InspectRequestMessage = inspectRequestParser parser ShutdownRequestMessage = shutdownRequestParser parser InputReplyMessage = inputReplyParser parser CommOpenMessage = commOpenParser@@ -139,11 +139,12 @@ pos <- obj .: "cursor_pos" return $ CompleteRequest noHeader code pos -objectInfoRequestParser :: LByteString -> Message-objectInfoRequestParser = requestParser $ \obj -> do- oname <- obj .: "oname"+inspectRequestParser :: LByteString -> Message+inspectRequestParser = requestParser $ \obj -> do+ code <- obj .: "code"+ pos <- obj .: "cursor_pos" dlevel <- obj .: "detail_level"- return $ ObjectInfoRequest noHeader oname dlevel+ return $ InspectRequest noHeader code pos dlevel shutdownRequestParser :: LByteString -> Message shutdownRequestParser = requestParser $ \obj -> do
src/IHaskell/IPython/Message/Writer.hs view
@@ -29,25 +29,30 @@ , "payload" .= if null pager then []- else [object ["source" .= string "page", "text" .= pager]]+ else map mkObj pager , "user_variables" .= emptyMap , "user_expressions" .= emptyMap ]+ where+ mkObj o = object+ [ "source" .= string "page"+ , "line" .= Number 0+ , "data" .= object [displayDataToJson o]+ ] toJSON PublishStatus { executionState = executionState } = object ["execution_state" .= executionState] toJSON PublishStream { streamType = streamType, streamContent = content } = object ["data" .= content, "name" .= streamType] toJSON PublishDisplayData { source = src, displayData = datas } = object- ["source" .= src, "metadata" .=- object [], "data" .=- object (map displayDataToJson datas)]+ ["source" .= src, "metadata" .= object [], "data" .= object (map displayDataToJson datas)] toJSON PublishOutput { executionCount = execCount, reprText = reprText } = object- ["data" .=- object ["text/plain" .= reprText], "execution_count" .= execCount, "metadata" .=- object []]+ [ "data" .= object ["text/plain" .= reprText]+ , "execution_count" .= execCount+ , "metadata" .= object []+ ] toJSON PublishInput { executionCount = execCount, inCode = code } = object ["execution_count" .= execCount, "code" .= code] toJSON (CompleteReply _ matches start end metadata status) =@@ -60,15 +65,14 @@ then string "ok" else "error" ]- toJSON o@ObjectInfoReply{} =+ toJSON i@InspectReply{} = object- [ "oname" .=- objectName o- , "found" .= objectFound o- , "ismagic" .= False- , "isalias" .= False- , "type_name" .= objectTypeString o- , "docstring" .= objectDocString o+ [ "status" .= if inspectStatus i+ then string "ok"+ else "error"+ , "data" .= object (map displayDataToJson . inspectData $ i)+ , "metadata" .= object []+ , "found" .= inspectStatus i ] toJSON ShutdownReply { restartPending = restart } =
− src/IHaskell/IPython/Stdin.hs
@@ -1,113 +0,0 @@-{-# LANGUAGE OverloadedStrings, DoAndIfThenElse #-}---- | This module provides a way in which the Haskell standard input may be forwarded to the IPython--- frontend and thus allows the notebook to use the standard input.------ This relies on the implementation of file handles in GHC, and is generally unsafe and terrible.--- However, it is difficult to find another way to do it, as file handles are generally meant to--- point to streams and files, and not networked communication protocols.------ In order to use this module, it must first be initialized with two things. First of all, in order--- to know how to communicate with the IPython frontend, it must know the kernel profile used for--- communication. For this, use @recordKernelProfile@ once the profile is known. Both this and--- @recordParentHeader@ take a directory name where they can store this data.------ Finally, the module must know what @execute_request@ message is currently being replied to (which--- will request the input). Thus, every time the language kernel receives an @execute_request@--- message, it should inform this module via @recordParentHeader@, so that the module may generate--- messages with an appropriate parent header set. If this is not done, the IPython frontends will--- not recognize the target of the communication.------ Finally, in order to activate this module, @fixStdin@ must be called once. It must be passed the--- same directory name as @recordParentHeader@ and @recordKernelProfile@. Note that if this is being--- used from within the GHC API, @fixStdin@ /must/ be called from within the GHC session not from--- the host code.-module IHaskell.IPython.Stdin (fixStdin, recordParentHeader, recordKernelProfile) where--import Control.Concurrent-import Control.Applicative ((<$>))-import Control.Concurrent.Chan-import Control.Monad-import GHC.IO.Handle-import GHC.IO.Handle.Types-import System.IO-import System.Posix.IO-import System.IO.Unsafe-import qualified Data.Map as Map--import IHaskell.IPython.Types-import IHaskell.IPython.ZeroMQ-import IHaskell.IPython.Message.UUID as UUID--stdinInterface :: MVar ZeroMQStdin-{-# NOINLINE stdinInterface #-}-stdinInterface = unsafePerformIO newEmptyMVar---- | Manipulate standard input so that it is sourced from the IPython frontend. This function is--- build on layers of deep magical hackery, so be careful modifying it.-fixStdin :: String -> IO ()-fixStdin dir = do- -- Initialize the stdin interface.- profile <- read <$> readFile (dir ++ "/.kernel-profile")- interface <- serveStdin profile- putMVar stdinInterface interface- void $ forkIO $ stdinOnce dir--stdinOnce :: String -> IO ()-stdinOnce dir = do- -- Create a pipe using and turn it into handles.- (readEnd, writeEnd) <- createPipe- newStdin <- fdToHandle readEnd- stdinInput <- fdToHandle writeEnd- hSetBuffering newStdin NoBuffering- hSetBuffering stdinInput NoBuffering-- -- Store old stdin and swap in new stdin.- oldStdin <- hDuplicate stdin- hDuplicateTo newStdin stdin-- loop stdinInput oldStdin newStdin-- where- loop stdinInput oldStdin newStdin = do- let FileHandle _ mvar = stdin- threadDelay $ 150 * 1000- empty <- isEmptyMVar mvar- if not empty- then loop stdinInput oldStdin newStdin- else do- line <- getInputLine dir- hPutStr stdinInput $ line ++ "\n"- loop stdinInput oldStdin newStdin---- | Get a line of input from the IPython frontend.-getInputLine :: String -> IO String-getInputLine dir = do- StdinChannel req rep <- readMVar stdinInterface-- -- Send a request for input.- uuid <- UUID.random- parentHeader <- read <$> readFile (dir ++ "/.last-req-header")- let header = MessageHeader- { username = username parentHeader- , identifiers = identifiers parentHeader- , parentHeader = Just parentHeader- , messageId = uuid- , sessionId = sessionId parentHeader- , metadata = Map.fromList []- , msgType = InputRequestMessage- }- let msg = RequestInput header ""- writeChan req msg-- -- Get the reply.- InputReply _ value <- readChan rep- return value--recordParentHeader :: String -> MessageHeader -> IO ()-recordParentHeader dir header =- writeFile (dir ++ "/.last-req-header") $ show header--recordKernelProfile :: String -> Profile -> IO ()-recordKernelProfile dir profile =- writeFile (dir ++ "/.kernel-profile") $ show profile
src/IHaskell/IPython/Types.hs view
@@ -38,6 +38,7 @@ import qualified Data.Text as Text import qualified Data.Text.Encoding as Text import Data.Text (Text)+import qualified Data.String as S import Data.Serialize import IHaskell.IPython.Message.UUID import GHC.Generics (Generic)@@ -175,8 +176,8 @@ | InputMessage | CompleteRequestMessage | CompleteReplyMessage- | ObjectInfoRequestMessage- | ObjectInfoReplyMessage+ | InspectRequestMessage+ | InspectReplyMessage | ShutdownRequestMessage | ShutdownReplyMessage | ClearOutputMessage@@ -201,8 +202,8 @@ showMessageType InputMessage = "pyin" showMessageType CompleteRequestMessage = "complete_request" showMessageType CompleteReplyMessage = "complete_reply"-showMessageType ObjectInfoRequestMessage = "object_info_request"-showMessageType ObjectInfoReplyMessage = "object_info_reply"+showMessageType InspectRequestMessage = "inspect_request"+showMessageType InspectReplyMessage = "inspect_reply" showMessageType ShutdownRequestMessage = "shutdown_request" showMessageType ShutdownReplyMessage = "shutdown_reply" showMessageType ClearOutputMessage = "clear_output"@@ -228,8 +229,8 @@ "pyin" -> return InputMessage "complete_request" -> return CompleteRequestMessage "complete_reply" -> return CompleteReplyMessage- "object_info_request" -> return ObjectInfoRequestMessage- "object_info_reply" -> return ObjectInfoReplyMessage+ "inspect_request" -> return InspectRequestMessage+ "inspect_reply" -> return InspectReplyMessage "shutdown_request" -> return ShutdownRequestMessage "shutdown_reply" -> return ShutdownReplyMessage "clear_output" -> return ClearOutputMessage@@ -272,7 +273,7 @@ ExecuteReply { header :: MessageHeader , status :: ExecuteReplyStatus -- ^ The status of the output.- , pagerOutput :: String -- ^ The help string to show in the pager.+ , pagerOutput :: [DisplayData] -- ^ The mimebundles to display in the pager. , executionCounter :: Int -- ^ The execution count, i.e. which output this is. } |@@ -325,20 +326,22 @@ , completionStatus :: Bool } |- ObjectInfoRequest+ InspectRequest { header :: MessageHeader- -- | Name of object being searched for.- , objectName :: Text+ -- | The code context in which introspection is requested+ , inspectCode :: Text+ -- | Position of the cursor in unicode characters. json field @cursor_pos@+ , inspectCursorPos :: Int -- | Level of detail desired (defaults to 0). 0 is equivalent to foo?, 1 is equivalent to foo??. , detailLevel :: Int } |- ObjectInfoReply+ InspectReply { header :: MessageHeader- , objectName :: Text -- ^ Name of object which was searched for.- , objectFound :: Bool -- ^ Whether the object was found.- , objectTypeString :: Text -- ^ Object type.- , objectDocString :: Text+ -- | whether the request succeeded or failed+ , inspectStatus :: Bool+ -- | @inspectData@ can be empty if nothing is found+ , inspectData :: [DisplayData] } | ShutdownRequest@@ -421,7 +424,7 @@ replyType KernelInfoRequestMessage = Just KernelInfoReplyMessage replyType ExecuteRequestMessage = Just ExecuteReplyMessage replyType CompleteRequestMessage = Just CompleteReplyMessage-replyType ObjectInfoRequestMessage = Just ObjectInfoReplyMessage+replyType InspectRequestMessage = Just InspectReplyMessage replyType ShutdownRequestMessage = Just ShutdownReplyMessage replyType HistoryRequestMessage = Just HistoryReplyMessage replyType _ = Nothing
src/IHaskell/IPython/ZeroMQ.hs view
@@ -194,7 +194,11 @@ sendMessage :: Sender a => Bool -> ByteString -> Socket a -> Message -> IO () sendMessage _ _ _ SendNothing = return () sendMessage debug hmacKey socket message = do- when debug $ print message+ when debug $ do+ putStr "Message: "+ print message+ putStr "Sent: "+ print content -- Send all pieces of the message. mapM_ sendPiece idents