1
0
mirror of https://github.com/IHaskell/IHaskell.git synced 2025-04-26 06:46:06 +00:00

Support installing profile

Now, EasyKernel supports installing a .tar file containing it's ipython
profile, which includes information about how to launch the executable.
This commit is contained in:
David Raymond Christiansen 2015-01-12 17:39:29 -08:00
parent 120efd0f8e
commit b4f54c190b
4 changed files with 81 additions and 16 deletions
ipython-kernel
example-data
examples
ipython-kernel.cabal
src/IHaskell/IPython

Binary file not shown.

@ -15,13 +15,16 @@ import Data.Monoid ((<>))
import qualified Data.Text as T import qualified Data.Text as T
import IHaskell.IPython.Kernel import IHaskell.IPython.Kernel
import IHaskell.IPython.EasyKernel (easyKernel, KernelConfig(..)) import IHaskell.IPython.EasyKernel (installProfile, easyKernel, KernelConfig(..))
import System.Environment (getArgs) import System.Environment (getArgs)
import System.FilePath ((</>))
import Text.Parsec (Parsec, ParseError, alphaNum, char, letter, oneOf, optionMaybe, runParser, (<?>)) import Text.Parsec (Parsec, ParseError, alphaNum, char, letter, oneOf, optionMaybe, runParser, (<?>))
import qualified Text.Parsec.Token as P import qualified Text.Parsec.Token as P
import qualified Paths_ipython_kernel as Paths
--------------------------------------------------------- ---------------------------------------------------------
-- Hutton's Razor, plus time delays, plus a global state -- Hutton's Razor, plus time delays, plus a global state
--------------------------------------------------------- ---------------------------------------------------------
@ -203,14 +206,15 @@ execRazor val Count clear send = do
mkConfig :: MVar Integer -- ^ The internal state of the execution mkConfig :: MVar Integer -- ^ The internal state of the execution
-> KernelConfig IO [IntermediateEvalRes] (Either ParseError Integer) -> KernelConfig IO [IntermediateEvalRes] (Either ParseError Integer)
mkConfig var = KernelConfig mkConfig var = KernelConfig
{ languageName = "Hutton's Razor + extra" { languageName = "expanded_huttons_razor"
, languageVersion = [0,1,0] , languageVersion = [0,1,0]
, displayResult = displayRes , profileSource = Just . (</> "calc_profile.tar") <$> Paths.getDataDir
, displayOutput = displayOut , displayResult = displayRes
, completion = langCompletion , displayOutput = displayOut
, objectInfo = langInfo , completion = langCompletion
, run = parseAndRun , objectInfo = langInfo
, debug = False , run = parseAndRun
, debug = False
} }
where where
displayRes (Left err) = displayRes (Left err) =
@ -231,6 +235,15 @@ mkConfig var = KernelConfig
return (Right res, Ok, T.unpack pager) return (Right res, Ok, T.unpack pager)
main :: IO () main :: IO ()
main = do ["kernel", profileFile] <- getArgs main = do args <- getArgs
val <- newMVar 1 val <- newMVar 1
easyKernel profileFile (mkConfig val) case args of
["kernel", profileFile] ->
easyKernel profileFile (mkConfig val)
["setup"] -> do
putStrLn "Installing profile..."
installProfile (mkConfig val)
_ -> do
putStrLn "Usage:"
putStrLn "simple-calc-example setup -- set up the profile"
putStrLn "simple-calc-example kernel FILE -- run a kernel with FILE for communication with the frontend"

@ -14,10 +14,15 @@ build-type: Simple
cabal-version: >=1.16 cabal-version: >=1.16
data-dir: example-data
data-files: calc_profile.tar
flag examples flag examples
description: Build example programs description: Build example programs
default: False default: False
library library
exposed-modules: IHaskell.IPython.Kernel exposed-modules: IHaskell.IPython.Kernel
IHaskell.IPython.Types IHaskell.IPython.Types
@ -36,22 +41,27 @@ library
bytestring >=0.10, bytestring >=0.10,
cereal >=0.3, cereal >=0.3,
containers >=0.5, containers >=0.5,
directory >=1.1,
filepath >=1.2,
mtl >=2.1, mtl >=2.1,
tar >=0.4.0.1,
text >=0.11, text >=0.11,
transformers >=0.3, transformers >=0.3,
unix >=2.6, unix >=2.6,
uuid >=1.3, uuid >=1.3,
zeromq4-haskell >=0.1 zeromq4-haskell >=0.1
-- Example program -- Example program
executable simple-calc-example executable simple-calc-example
hs-source-dirs: examples hs-source-dirs: examples
main-is: Calc.hs main-is: Calc.hs
build-depends: ipython-kernel, build-depends: ipython-kernel,
base >=4.6 && < 4.8, base >=4.6 && <4.8,
filepath >=1.2,
mtl >=2.1, mtl >=2.1,
parsec >=3.1, parsec >=3.1,
text >= 0.11, text >=0.11,
transformers >=0.3 transformers >=0.3
if !flag(examples) if !flag(examples)

@ -45,12 +45,14 @@
-- source code for further configuration of the frontend, including -- source code for further configuration of the frontend, including
-- syntax highlighting, logos, help text, and so forth. -- syntax highlighting, logos, help text, and so forth.
module IHaskell.IPython.EasyKernel (easyKernel, KernelConfig(..)) where module IHaskell.IPython.EasyKernel (easyKernel, installProfile, KernelConfig(..)) where
import Data.Aeson (decode) import Data.Aeson (decode)
import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy as BL
import qualified Codec.Archive.Tar as Tar
import Control.Concurrent (MVar, readChan, writeChan, newMVar, readMVar, modifyMVar_) import Control.Concurrent (MVar, readChan, writeChan, newMVar, readMVar, modifyMVar_)
import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad (forever, when) import Control.Monad (forever, when)
@ -62,7 +64,8 @@ import qualified Data.Text as T
import IHaskell.IPython.Kernel import IHaskell.IPython.Kernel
import IHaskell.IPython.Message.UUID as UUID import IHaskell.IPython.Message.UUID as UUID
import System.Directory (createDirectoryIfMissing, doesDirectoryExist, doesFileExist, getHomeDirectory)
import System.FilePath ((</>))
import System.Exit (exitSuccess) import System.Exit (exitSuccess)
import System.IO (openFile, IOMode(ReadMode)) import System.IO (openFile, IOMode(ReadMode))
@ -71,8 +74,18 @@ import System.IO (openFile, IOMode(ReadMode))
-- your kernel will run, the type of intermediate outputs from running -- your kernel will run, the type of intermediate outputs from running
-- cells, and the type of final results of cells, respectively. -- cells, and the type of final results of cells, respectively.
data KernelConfig m output result = KernelConfig data KernelConfig m output result = KernelConfig
{ languageName :: String -- ^ The name of the language { languageName :: String
-- ^ The name of the language. This field is used to calculate
-- the name of the profile, so it should contain characters that
-- are reasonable to have in file names.
, languageVersion :: [Int] -- ^ The version of the language , languageVersion :: [Int] -- ^ The version of the language
, profileSource :: IO (Maybe FilePath)
-- ^ Determine the source of a profile to install using
-- 'installProfile'. The source should be a tarball whose contents
-- will be unpacked directly into the profile directory. For
-- example, the file whose name is @ipython_config.py@ in the
-- tar file for a language named @lang@ will end up in
-- @~/.ipython/profile_lang/ipython_config.py@.
, displayOutput :: output -> [DisplayData] -- ^ How to render intermediate output , displayOutput :: output -> [DisplayData] -- ^ How to render intermediate output
, displayResult :: result -> [DisplayData] -- ^ How to render final cell results , displayResult :: result -> [DisplayData] -- ^ How to render final cell results
, completion :: T.Text -> T.Text -> Int -> Maybe ([T.Text], T.Text, T.Text) , completion :: T.Text -> T.Text -> Int -> Maybe ([T.Text], T.Text, T.Text)
@ -97,6 +110,35 @@ data KernelConfig m output result = KernelConfig
-- the console -- the console
} }
-- | Attempt to install the IPython profile from the .tar file
-- indicated by the 'profileSource' field of the configuration, if it
-- is not already installed.
installProfile :: MonadIO m => KernelConfig m output result -> m ()
installProfile config = do
installed <- isInstalled
when (not installed) $ do
profSrc <- liftIO $ profileSource config
case profSrc of
Nothing -> liftIO (putStrLn "No IPython profile is installed or specified")
Just tar -> do
profExists <- liftIO $ doesFileExist tar
profTgt <- profDir
if profExists
then do liftIO $ createDirectoryIfMissing True profTgt
liftIO $ Tar.extract profTgt tar
else liftIO . putStrLn $
"The supplied profile source '" ++ tar ++ "' does not exist"
where
profDir = do
home <- liftIO getHomeDirectory
return $ home </> ".ipython" </> ("profile_" ++ languageName config)
isInstalled = do
prof <- profDir
dirThere <- liftIO $ doesDirectoryExist prof
isProf <- liftIO . doesFileExist $ prof </> "ipython_config.py"
return $ dirThere && isProf
getProfile :: FilePath -> IO Profile getProfile :: FilePath -> IO Profile
getProfile fn = do getProfile fn = do
profData <- openFile fn ReadMode >>= BL.hGetContents profData <- openFile fn ReadMode >>= BL.hGetContents