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

Binary file not shown.

View File

@ -15,13 +15,16 @@ import Data.Monoid ((<>))
import qualified Data.Text as T
import IHaskell.IPython.Kernel
import IHaskell.IPython.EasyKernel (easyKernel, KernelConfig(..))
import IHaskell.IPython.EasyKernel (installProfile, easyKernel, KernelConfig(..))
import System.Environment (getArgs)
import System.FilePath ((</>))
import Text.Parsec (Parsec, ParseError, alphaNum, char, letter, oneOf, optionMaybe, runParser, (<?>))
import qualified Text.Parsec.Token as P
import qualified Paths_ipython_kernel as Paths
---------------------------------------------------------
-- 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
-> KernelConfig IO [IntermediateEvalRes] (Either ParseError Integer)
mkConfig var = KernelConfig
{ languageName = "Hutton's Razor + extra"
, languageVersion = [0,1,0]
, displayResult = displayRes
, displayOutput = displayOut
, completion = langCompletion
, objectInfo = langInfo
, run = parseAndRun
, debug = False
{ languageName = "expanded_huttons_razor"
, languageVersion = [0,1,0]
, profileSource = Just . (</> "calc_profile.tar") <$> Paths.getDataDir
, displayResult = displayRes
, displayOutput = displayOut
, completion = langCompletion
, objectInfo = langInfo
, run = parseAndRun
, debug = False
}
where
displayRes (Left err) =
@ -231,6 +235,15 @@ mkConfig var = KernelConfig
return (Right res, Ok, T.unpack pager)
main :: IO ()
main = do ["kernel", profileFile] <- getArgs
main = do args <- getArgs
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"

View File

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

View File

@ -45,12 +45,14 @@
-- source code for further configuration of the frontend, including
-- 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 qualified Data.ByteString.Lazy as BL
import qualified Codec.Archive.Tar as Tar
import Control.Concurrent (MVar, readChan, writeChan, newMVar, readMVar, modifyMVar_)
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad (forever, when)
@ -62,7 +64,8 @@ import qualified Data.Text as T
import IHaskell.IPython.Kernel
import IHaskell.IPython.Message.UUID as UUID
import System.Directory (createDirectoryIfMissing, doesDirectoryExist, doesFileExist, getHomeDirectory)
import System.FilePath ((</>))
import System.Exit (exitSuccess)
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
-- cells, and the type of final results of cells, respectively.
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
, 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
, displayResult :: result -> [DisplayData] -- ^ How to render final cell results
, 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
}
-- | 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 fn = do
profData <- openFile fn ReadMode >>= BL.hGetContents