Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
gargantext-ihaskell
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
gargantext-ihaskell
Commits
c53f70d8
Commit
c53f70d8
authored
Mar 21, 2015
by
Andrew Gibiansky
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Formatting ipython-kernel
parent
7ba7c4d1
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
836 additions
and
890 deletions
+836
-890
Calc.hs
ipython-kernel/examples/Calc.hs
+123
-120
EasyKernel.hs
ipython-kernel/src/IHaskell/IPython/EasyKernel.hs
+136
-165
Kernel.hs
ipython-kernel/src/IHaskell/IPython/Kernel.hs
+8
-11
Parser.hs
ipython-kernel/src/IHaskell/IPython/Message/Parser.hs
+46
-49
UUID.hs
ipython-kernel/src/IHaskell/IPython/Message/UUID.hs
+14
-17
Writer.hs
ipython-kernel/src/IHaskell/IPython/Message/Writer.hs
+92
-107
Stdin.hs
ipython-kernel/src/IHaskell/IPython/Stdin.hs
+50
-60
Types.hs
ipython-kernel/src/IHaskell/IPython/Types.hs
+293
-291
ZeroMQ.hs
ipython-kernel/src/IHaskell/IPython/ZeroMQ.hs
+65
-66
verify_formatting.py
verify_formatting.py
+9
-4
No files found.
ipython-kernel/examples/Calc.hs
View file @
c53f70d8
This diff is collapsed.
Click to expand it.
ipython-kernel/src/IHaskell/IPython/EasyKernel.hs
View file @
c53f70d8
This diff is collapsed.
Click to expand it.
ipython-kernel/src/IHaskell/IPython/Kernel.hs
View file @
c53f70d8
-- | This module exports all the types and functions necessary to create an
-- | This module exports all the types and functions necessary to create an IPython language kernel
-- IPython language kernel that supports the @ipython console@ and @ipython
-- that supports the @ipython console@ and @ipython notebook@ frontends.
-- notebook@ frontends.
module
IHaskell.IPython.Kernel
(
module
X
)
where
module
IHaskell.IPython.Kernel
(
module
X
,
)
where
import
IHaskell.IPython.Types
as
X
import
IHaskell.IPython.Types
as
X
import
IHaskell.IPython.Message.Writer
as
X
import
IHaskell.IPython.Message.Writer
as
X
import
IHaskell.IPython.Message.Parser
as
X
import
IHaskell.IPython.Message.Parser
as
X
import
IHaskell.IPython.Message.UUID
as
X
import
IHaskell.IPython.Message.UUID
as
X
import
IHaskell.IPython.ZeroMQ
as
X
import
IHaskell.IPython.ZeroMQ
as
X
ipython-kernel/src/IHaskell/IPython/Message/Parser.hs
View file @
c53f70d8
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedStrings #-}
-- | Description : Parsing messages received from IPython
-- | Description : Parsing messages received from IPython
--
--
-- This module is responsible for converting from low-level ByteStrings
-- This module is responsible for converting from low-level ByteStrings
obtained from the 0MQ
--
obtained from the 0MQ sockets into Messages. The only exposed function is
--
sockets into Messages. The only exposed function is `parseMessage`, which should only be used in
--
`parseMessage`, which should only be used in
the low-level 0MQ interface.
-- the low-level 0MQ interface.
module
IHaskell.IPython.Message.Parser
(
parseMessage
)
where
module
IHaskell.IPython.Message.Parser
(
parseMessage
)
where
import
Data.Aeson
((
.:
),
decode
,
Result
(
..
),
Object
)
import
Data.Aeson
((
.:
),
decode
,
Result
(
..
),
Object
)
...
@@ -17,9 +18,7 @@ import IHaskell.IPython.Types
...
@@ -17,9 +18,7 @@ import IHaskell.IPython.Types
type
LByteString
=
Lazy
.
ByteString
type
LByteString
=
Lazy
.
ByteString
----- External interface -----
-- --- External interface ----- | Parse a message from its ByteString components into a Message.
-- | Parse a message from its ByteString components into a Message.
parseMessage
::
[
ByteString
]
-- ^ The list of identifiers sent with the message.
parseMessage
::
[
ByteString
]
-- ^ The list of identifiers sent with the message.
->
ByteString
-- ^ The header data.
->
ByteString
-- ^ The header data.
->
ByteString
-- ^ The parent header, which is just "{}" if there is no header.
->
ByteString
-- ^ The parent header, which is just "{}" if there is no header.
...
@@ -32,26 +31,25 @@ parseMessage idents headerData parentHeader metadata content =
...
@@ -32,26 +31,25 @@ parseMessage idents headerData parentHeader metadata content =
messageWithoutHeader
=
parser
messageType
$
Lazy
.
fromStrict
content
messageWithoutHeader
=
parser
messageType
$
Lazy
.
fromStrict
content
in
messageWithoutHeader
{
header
=
header
}
in
messageWithoutHeader
{
header
=
header
}
----- Module internals -----
-- --- Module internals ----- | Parse a header from its ByteString components into a MessageHeader.
-- | Parse a header from its ByteString components into a MessageHeader.
parseHeader
::
[
ByteString
]
-- ^ The list of identifiers.
parseHeader
::
[
ByteString
]
-- ^ The list of identifiers.
->
ByteString
-- ^ The header data.
->
ByteString
-- ^ The header data.
->
ByteString
-- ^ The parent header, or "{}" for Nothing.
->
ByteString
-- ^ The parent header, or "{}" for Nothing.
->
ByteString
-- ^ The metadata, or "{}" for an empty map.
->
ByteString
-- ^ The metadata, or "{}" for an empty map.
->
MessageHeader
-- The resulting message header.
->
MessageHeader
-- The resulting message header.
parseHeader
idents
headerData
parentHeader
metadata
=
parseHeader
idents
headerData
parentHeader
metadata
=
MessageHeader
{
identifiers
=
idents
MessageHeader
,
parentHeader
=
parentResult
{
identifiers
=
idents
,
metadata
=
metadataMap
,
parentHeader
=
parentResult
,
messageId
=
messageUUID
,
metadata
=
metadataMap
,
sessionId
=
sessionUUID
,
messageId
=
messageUUID
,
username
=
username
,
sessionId
=
sessionUUID
,
msgType
=
messageType
,
username
=
username
}
,
msgType
=
messageType
}
where
where
-- Decode the header data and the parent header data into JSON objects.
-- Decode the header data and the parent header data into JSON objects.
If the parent header data is
--
If the parent header data is
absent, just have Nothing instead.
-- absent, just have Nothing instead.
Just
result
=
decode
$
Lazy
.
fromStrict
headerData
::
Maybe
Object
Just
result
=
decode
$
Lazy
.
fromStrict
headerData
::
Maybe
Object
parentResult
=
if
parentHeader
==
"{}"
parentResult
=
if
parentHeader
==
"{}"
then
Nothing
then
Nothing
...
@@ -71,27 +69,26 @@ noHeader :: MessageHeader
...
@@ -71,27 +69,26 @@ noHeader :: MessageHeader
noHeader
=
error
"No header created"
noHeader
=
error
"No header created"
parser
::
MessageType
-- ^ The message type being parsed.
parser
::
MessageType
-- ^ The message type being parsed.
->
LByteString
->
Message
-- ^ The parser that converts the body into a message.
->
LByteString
->
Message
-- ^ The parser that converts the body into a message.
This message
--
This message
should have an undefined header.
-- should have an undefined header.
parser
KernelInfoRequestMessage
=
kernelInfoRequestParser
parser
KernelInfoRequestMessage
=
kernelInfoRequestParser
parser
ExecuteRequestMessage
=
executeRequestParser
parser
ExecuteRequestMessage
=
executeRequestParser
parser
CompleteRequestMessage
=
completeRequestParser
parser
CompleteRequestMessage
=
completeRequestParser
parser
ObjectInfoRequestMessage
=
objectInfoRequestParser
parser
ObjectInfoRequestMessage
=
objectInfoRequestParser
parser
ShutdownRequestMessage
=
shutdownRequestParser
parser
ShutdownRequestMessage
=
shutdownRequestParser
parser
InputReplyMessage
=
inputReplyParser
parser
InputReplyMessage
=
inputReplyParser
parser
CommOpenMessage
=
commOpenParser
parser
CommOpenMessage
=
commOpenParser
parser
CommDataMessage
=
commDataParser
parser
CommDataMessage
=
commDataParser
parser
CommCloseMessage
=
commCloseParser
parser
CommCloseMessage
=
commCloseParser
parser
HistoryRequestMessage
=
historyRequestParser
parser
HistoryRequestMessage
=
historyRequestParser
parser
other
=
error
$
"Unknown message type "
++
show
other
parser
other
=
error
$
"Unknown message type "
++
show
other
-- | Parse a kernel info request.
-- | Parse a kernel info request.
A kernel info request has no auxiliary information, so ignore the
--
A kernel info request has no auxiliary information, so ignore the
body.
-- body.
kernelInfoRequestParser
::
LByteString
->
Message
kernelInfoRequestParser
::
LByteString
->
Message
kernelInfoRequestParser
_
=
KernelInfoRequest
{
header
=
noHeader
}
kernelInfoRequestParser
_
=
KernelInfoRequest
{
header
=
noHeader
}
-- | Parse an execute request.
-- | Parse an execute request. Fields used are:
-- Fields used are:
-- 1. "code": the code to execute.
-- 1. "code": the code to execute.
-- 2. "silent": whether to execute silently.
-- 2. "silent": whether to execute silently.
-- 3. "store_history": whether to include this in history.
-- 3. "store_history": whether to include this in history.
...
@@ -99,22 +96,23 @@ kernelInfoRequestParser _ = KernelInfoRequest { header = noHeader }
...
@@ -99,22 +96,23 @@ kernelInfoRequestParser _ = KernelInfoRequest { header = noHeader }
executeRequestParser
::
LByteString
->
Message
executeRequestParser
::
LByteString
->
Message
executeRequestParser
content
=
executeRequestParser
content
=
let
parser
obj
=
do
let
parser
obj
=
do
code
<-
obj
.:
"code"
code
<-
obj
.:
"code"
silent
<-
obj
.:
"silent"
silent
<-
obj
.:
"silent"
storeHistory
<-
obj
.:
"store_history"
storeHistory
<-
obj
.:
"store_history"
allowStdin
<-
obj
.:
"allow_stdin"
allowStdin
<-
obj
.:
"allow_stdin"
return
(
code
,
silent
,
storeHistory
,
allowStdin
)
return
(
code
,
silent
,
storeHistory
,
allowStdin
)
Just
decoded
=
decode
content
Just
decoded
=
decode
content
Success
(
code
,
silent
,
storeHistory
,
allowStdin
)
=
parse
parser
decoded
Success
(
code
,
silent
,
storeHistory
,
allowStdin
)
=
parse
parser
decoded
in
ExecuteRequest
{
header
=
noHeader
in
ExecuteRequest
,
getCode
=
code
{
header
=
noHeader
,
getSilent
=
silent
,
getCode
=
code
,
getAllowStdin
=
allowStdin
,
getSilent
=
silent
,
getStoreHistory
=
storeHistory
,
getAllowStdin
=
allowStdin
,
getUserVariables
=
[]
,
getStoreHistory
=
storeHistory
,
getUserExpressions
=
[]
,
getUserVariables
=
[]
}
,
getUserExpressions
=
[]
}
requestParser
parser
content
=
parsed
requestParser
parser
content
=
parsed
where
where
...
@@ -147,7 +145,6 @@ objectInfoRequestParser = requestParser $ \obj -> do
...
@@ -147,7 +145,6 @@ objectInfoRequestParser = requestParser $ \obj -> do
dlevel
<-
obj
.:
"detail_level"
dlevel
<-
obj
.:
"detail_level"
return
$
ObjectInfoRequest
noHeader
oname
dlevel
return
$
ObjectInfoRequest
noHeader
oname
dlevel
shutdownRequestParser
::
LByteString
->
Message
shutdownRequestParser
::
LByteString
->
Message
shutdownRequestParser
=
requestParser
$
\
obj
->
do
shutdownRequestParser
=
requestParser
$
\
obj
->
do
code
<-
obj
.:
"restart"
code
<-
obj
.:
"restart"
...
...
ipython-kernel/src/IHaskell/IPython/Message/UUID.hs
View file @
c53f70d8
-- | Description : UUID generator and data structure
-- | Description : UUID generator and data structure
--
--
-- Generate, parse, and pretty print UUIDs for use with IPython.
-- Generate, parse, and pretty print UUIDs for use with IPython.
module
IHaskell.IPython.Message.UUID
(
module
IHaskell.IPython.Message.UUID
(
UUID
,
random
,
randoms
)
where
UUID
,
random
,
randoms
,
)
where
import
Control.Monad
(
mzero
,
replicateM
)
import
Control.Monad
(
mzero
,
replicateM
)
import
Control.Applicative
((
<$>
))
import
Control.Applicative
((
<$>
))
import
Data.Text
(
pack
)
import
Data.Text
(
pack
)
import
Data.Aeson
import
Data.Aeson
import
Data.UUID.V4
(
nextRandom
)
import
Data.UUID.V4
(
nextRandom
)
-- We use an internal string representation because for the purposes of
-- IPython, it matters whether the letters are uppercase or lowercase and
-- whether the dashes are present in the correct locations. For the
-- purposes of new UUIDs, it does not matter, but IPython expects UUIDs
-- passed to kernels to be returned unchanged, so we cannot actually parse
-- them.
-- | A UUID (universally unique identifier).
-- | A UUID (universally unique identifier).
data
UUID
=
UUID
String
deriving
(
Show
,
Read
,
Eq
,
Ord
)
data
UUID
=
-- We use an internal string representation because for the purposes of IPython, it
-- matters whether the letters are uppercase or lowercase and whether the dashes are
-- present in the correct locations. For the purposes of new UUIDs, it does not matter,
-- but IPython expects UUIDs passed to kernels to be returned unchanged, so we cannot
-- actually parse them.
UUID
String
deriving
(
Show
,
Read
,
Eq
,
Ord
)
-- | Generate a list of random UUIDs.
-- | Generate a list of random UUIDs.
randoms
::
Int
-- ^ Number of UUIDs to generate.
randoms
::
Int
-- ^ Number of UUIDs to generate.
...
...
ipython-kernel/src/IHaskell/IPython/Message/Writer.hs
View file @
c53f70d8
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedStrings #-}
-- | Description : @ToJSON@ for Messages
-- | Description : @ToJSON@ for Messages
--
--
-- This module contains the @ToJSON@ instance for @Message@.
-- This module contains the @ToJSON@ instance for @Message@.
module
IHaskell.IPython.Message.Writer
(
module
IHaskell.IPython.Message.Writer
(
ToJSON
(
..
))
where
ToJSON
(
..
)
)
where
import
Data.Aeson
import
Data.Aeson
import
Data.Map
(
Map
)
import
Data.Map
(
Map
)
import
Data.Text
(
Text
,
pack
)
import
Data.Text
(
Text
,
pack
)
import
Data.Monoid
(
mempty
)
import
Data.Monoid
(
mempty
)
import
qualified
Data.ByteString.Lazy
as
L
import
qualified
Data.ByteString.Lazy
as
L
import
qualified
Data.ByteString
as
B
import
qualified
Data.ByteString
as
B
import
Data.Text.Encoding
import
Data.Text.Encoding
import
IHaskell.IPython.Types
import
IHaskell.IPython.Types
-- Convert message bodies into JSON.
-- Convert message bodies into JSON.
instance
ToJSON
Message
where
instance
ToJSON
Message
where
toJSON
KernelInfoReply
{
versionList
=
vers
,
language
=
language
}
=
object
[
toJSON
KernelInfoReply
{
versionList
=
vers
,
language
=
language
}
=
"protocol_version"
.=
string
"5.0"
,
-- current protocol version, major and minor
object
[
"protocol_version"
.=
string
"5.0"
-- current protocol version, major and minor
"language_version"
.=
vers
,
,
"language_version"
.=
vers
,
"language"
.=
language
]
"language"
.=
language
]
toJSON
ExecuteReply
{
status
=
status
,
executionCounter
=
counter
,
pagerOutput
=
pager
}
=
object
toJSON
ExecuteReply
{
status
=
status
,
executionCounter
=
counter
,
pagerOutput
=
pager
}
=
object
[
[
"status"
.=
show
status
"status"
.=
show
status
,
,
"execution_count"
.=
counter
"execution_count"
.=
counter
,
,
"payload"
.=
"payload"
.=
if
null
pager
if
null
pager
then
[]
then
[]
else
[
object
[
"source"
.=
string
"page"
,
"text"
.=
pager
]]
else
[
object
[
,
"user_variables"
.=
emptyMap
"source"
.=
string
"page"
,
,
"user_expressions"
.=
emptyMap
"text"
.=
pager
]
]],
toJSON
PublishStatus
{
executionState
=
executionState
}
=
"user_variables"
.=
emptyMap
,
object
[
"execution_state"
.=
executionState
]
"user_expressions"
.=
emptyMap
toJSON
PublishStream
{
streamType
=
streamType
,
streamContent
=
content
}
=
]
object
[
"data"
.=
content
,
"name"
.=
streamType
]
toJSON
PublishStatus
{
executionState
=
executionState
}
=
object
[
toJSON
PublishDisplayData
{
source
=
src
,
displayData
=
datas
}
=
"execution_state"
.=
executionState
object
]
[
"source"
.=
src
,
"metadata"
.=
toJSON
PublishStream
{
streamType
=
streamType
,
streamContent
=
content
}
=
object
[
object
[]
,
"data"
.=
"data"
.=
content
,
object
(
map
displayDataToJson
datas
)]
"name"
.=
streamType
]
toJSON
PublishOutput
{
executionCount
=
execCount
,
reprText
=
reprText
}
=
toJSON
PublishDisplayData
{
source
=
src
,
displayData
=
datas
}
=
object
[
object
"source"
.=
src
,
[
"data"
.=
"metadata"
.=
object
[]
,
object
[
"text/plain"
.=
reprText
],
"execution_count"
.=
execCount
,
"metadata"
.=
"data"
.=
object
(
map
displayDataToJson
datas
)
object
[]
]
]
toJSON
PublishInput
{
executionCount
=
execCount
,
inCode
=
code
}
=
object
[
"execution_count"
.=
execCount
,
"code"
.=
code
]
toJSON
PublishOutput
{
executionCount
=
execCount
,
reprText
=
reprText
}
=
object
[
toJSON
(
CompleteReply
_
matches
start
end
metadata
status
)
=
"data"
.=
object
[
"text/plain"
.=
reprText
],
object
"execution_count"
.=
execCount
,
[
"matches"
.=
matches
"metadata"
.=
object
[]
,
"cursor_start"
.=
start
]
,
"cursor_end"
.=
end
toJSON
PublishInput
{
executionCount
=
execCount
,
inCode
=
code
}
=
object
[
,
"metadata"
.=
metadata
"execution_count"
.=
execCount
,
,
"status"
.=
if
status
"code"
.=
code
then
string
"ok"
]
else
"error"
toJSON
(
CompleteReply
_
matches
start
end
metadata
status
)
=
object
[
]
"matches"
.=
matches
,
toJSON
o
@
ObjectInfoReply
{}
=
"cursor_start"
.=
start
,
object
"cursor_end"
.=
end
,
[
"oname"
.=
"metadata"
.=
metadata
,
objectName
o
"status"
.=
if
status
then
string
"ok"
else
"error"
,
"found"
.=
objectFound
o
]
,
"ismagic"
.=
False
toJSON
o
@
ObjectInfoReply
{}
=
object
[
,
"isalias"
.=
False
"oname"
.=
objectName
o
,
,
"type_name"
.=
objectTypeString
o
"found"
.=
objectFound
o
,
,
"docstring"
.=
objectDocString
o
"ismagic"
.=
False
,
]
"isalias"
.=
False
,
"type_name"
.=
objectTypeString
o
,
toJSON
ShutdownReply
{
restartPending
=
restart
}
=
"docstring"
.=
objectDocString
o
object
[
"restart"
.=
restart
]
]
toJSON
ClearOutput
{
wait
=
wait
}
=
toJSON
ShutdownReply
{
restartPending
=
restart
}
=
object
[
object
[
"wait"
.=
wait
]
"restart"
.=
restart
]
toJSON
RequestInput
{
inputPrompt
=
prompt
}
=
object
[
"prompt"
.=
prompt
]
toJSON
ClearOutput
{
wait
=
wait
}
=
object
[
"wait"
.=
wait
toJSON
req
@
CommOpen
{}
=
]
object
[
"comm_id"
.=
commUuid
req
,
"target_name"
.=
commTargetName
req
,
"data"
.=
commData
req
]
toJSON
RequestInput
{
inputPrompt
=
prompt
}
=
object
[
toJSON
req
@
CommData
{}
=
"prompt"
.=
prompt
object
[
"comm_id"
.=
commUuid
req
,
"data"
.=
commData
req
]
]
toJSON
req
@
CommClose
{}
=
toJSON
req
@
CommOpen
{}
=
object
[
object
[
"comm_id"
.=
commUuid
req
,
"data"
.=
commData
req
]
"comm_id"
.=
commUuid
req
,
"target_name"
.=
commTargetName
req
,
toJSON
req
@
HistoryReply
{}
=
"data"
.=
commData
req
object
[
"history"
.=
map
tuplify
(
historyReply
req
)]
]
where
tuplify
(
HistoryReplyElement
sess
linum
res
)
=
(
sess
,
linum
,
case
res
of
toJSON
req
@
CommData
{}
=
object
[
Left
inp
->
toJSON
inp
"comm_id"
.=
commUuid
req
,
Right
(
inp
,
out
)
->
toJSON
out
)
"data"
.=
commData
req
]
toJSON
req
@
CommClose
{}
=
object
[
"comm_id"
.=
commUuid
req
,
"data"
.=
commData
req
]
toJSON
req
@
HistoryReply
{}
=
object
[
"history"
.=
map
tuplify
(
historyReply
req
)
]
where
tuplify
(
HistoryReplyElement
sess
linum
res
)
=
(
sess
,
linum
,
case
res
of
Left
inp
->
toJSON
inp
Right
(
inp
,
out
)
->
toJSON
out
)
toJSON
body
=
error
$
"Do not know how to convert to JSON for message "
++
show
body
toJSON
body
=
error
$
"Do not know how to convert to JSON for message "
++
show
body
-- | Print an execution state as "busy", "idle", or "starting".
-- | Print an execution state as "busy", "idle", or "starting".
instance
ToJSON
ExecutionState
where
instance
ToJSON
ExecutionState
where
toJSON
Busy
=
String
"busy"
toJSON
Busy
=
String
"busy"
toJSON
Idle
=
String
"idle"
toJSON
Idle
=
String
"idle"
toJSON
Starting
=
String
"starting"
toJSON
Starting
=
String
"starting"
-- | Print a stream as "stdin" or "stdout" strings.
-- | Print a stream as "stdin" or "stdout" strings.
instance
ToJSON
StreamType
where
instance
ToJSON
StreamType
where
toJSON
Stdin
=
String
"stdin"
toJSON
Stdin
=
String
"stdin"
toJSON
Stdout
=
String
"stdout"
toJSON
Stdout
=
String
"stdout"
-- | Convert a MIME type and value into a JSON dictionary pair.
-- | Convert a MIME type and value into a JSON dictionary pair.
displayDataToJson
::
DisplayData
->
(
Text
,
Value
)
displayDataToJson
::
DisplayData
->
(
Text
,
Value
)
displayDataToJson
(
DisplayData
mimeType
dataStr
)
=
displayDataToJson
(
DisplayData
mimeType
dataStr
)
=
pack
(
show
mimeType
)
.=
String
dataStr
pack
(
show
mimeType
)
.=
String
dataStr
----- Constants -----
----- Constants -----
emptyMap
::
Map
String
String
emptyMap
::
Map
String
String
emptyMap
=
mempty
emptyMap
=
mempty
...
...
ipython-kernel/src/IHaskell/IPython/Stdin.hs
View file @
c53f70d8
{-# LANGUAGE OverloadedStrings, DoAndIfThenElse #-}
{-# 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
--
| This module provides a way in which the Haskell standard input may be forwarded to the IPython
-- the standard input.
--
frontend and thus allows the notebook to use
the standard input.
--
--
-- This relies on the implementation of file handles in GHC, and is
-- This relies on the implementation of file handles in GHC, and is generally unsafe and terrible.
-- generally unsafe and terrible. However, it is difficult to find another
-- However, it is difficult to find another way to do it, as file handles are generally meant to
-- way to do it, as file handles are generally meant to point to streams
-- point to streams and files, and not networked communication protocols.
-- and files, and not networked communication protocols.
--
--
-- In order to use this module, it must first be initialized with two
-- In order to use this module, it must first be initialized with two things. First of all, in order
-- things. First of all, in order to know how to communicate with the
-- to know how to communicate with the IPython frontend, it must know the kernel profile used for
-- IPython frontend, it must know the kernel profile used for
-- communication. For this, use @recordKernelProfile@ once the profile is known. Both this and
-- communication. For this, use @recordKernelProfile@ once the profile is
-- @recordParentHeader@ take a directory name where they can store this data.
-- 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
-- Finally, the module must know what @execute_request@ message is currently being replied to (which
-- currently being replied to (which will request the input). Thus, every
-- will request the input). Thus, every time the language kernel receives an @execute_request@
-- time the language kernel receives an @execute_request@ message, it
-- message, it should inform this module via @recordParentHeader@, so that the module may generate
-- should inform this module via @recordParentHeader@, so that the module
-- messages with an appropriate parent header set. If this is not done, the IPython frontends will
-- may generate messages with an appropriate parent header set. If this is
-- not recognize the target of the communication.
-- not done, the IPython frontends will not recognize the target of the
-- communication.
--
--
-- Finally, in order to activate this module, @fixStdin@ must be called
-- Finally, in order to activate this module, @fixStdin@ must be called once. It must be passed the
-- once. It must be passed the same directory name as @recordParentHeader@
-- same directory name as @recordParentHeader@ and @recordKernelProfile@. Note that if this is being
-- and @recordKernelProfile@. Note that if this is being used from within
-- used from within the GHC API, @fixStdin@ /must/ be called from within the GHC session not from
-- the GHC API, @fixStdin@ /must/ be called from within the GHC session
-- the host code.
-- not from the host code.
module
IHaskell.IPython.Stdin
(
fixStdin
,
recordParentHeader
,
recordKernelProfile
)
where
module
IHaskell.IPython.Stdin
(
fixStdin
,
recordParentHeader
,
recordKernelProfile
)
where
import
Control.Concurrent
import
Control.Concurrent
import
Control.Applicative
((
<$>
))
import
Control.Applicative
((
<$>
))
import
Control.Concurrent.Chan
import
Control.Concurrent.Chan
import
Control.Monad
import
Control.Monad
import
GHC.IO.Handle
import
GHC.IO.Handle
import
GHC.IO.Handle.Types
import
GHC.IO.Handle.Types
import
System.IO
import
System.IO
import
System.Posix.IO
import
System.Posix.IO
import
System.IO.Unsafe
import
System.IO.Unsafe
import
qualified
Data.Map
as
Map
import
qualified
Data.Map
as
Map
import
IHaskell.IPython.Types
import
IHaskell.IPython.Types
import
IHaskell.IPython.ZeroMQ
import
IHaskell.IPython.ZeroMQ
import
IHaskell.IPython.Message.UUID
as
UUID
import
IHaskell.IPython.Message.UUID
as
UUID
stdinInterface
::
MVar
ZeroMQStdin
stdinInterface
::
MVar
ZeroMQStdin
{-# NOINLINE stdinInterface #-}
{-# NOINLINE stdinInterface #-}
stdinInterface
=
unsafePerformIO
newEmptyMVar
stdinInterface
=
unsafePerformIO
newEmptyMVar
-- | Manipulate standard input so that it is sourced from the IPython
-- | Manipulate standard input so that it is sourced from the IPython frontend. This function is
-- frontend. This function is build on layers of deep magical hackery, so
-- build on layers of deep magical hackery, so be careful modifying it.
-- be careful modifying it.
fixStdin
::
String
->
IO
()
fixStdin
::
String
->
IO
()
fixStdin
dir
=
do
fixStdin
dir
=
do
-- Initialize the stdin interface.
-- Initialize the stdin interface.
...
@@ -78,17 +67,18 @@ stdinOnce dir = do
...
@@ -78,17 +67,18 @@ stdinOnce dir = do
hDuplicateTo
newStdin
stdin
hDuplicateTo
newStdin
stdin
loop
stdinInput
oldStdin
newStdin
loop
stdinInput
oldStdin
newStdin
where
where
loop
stdinInput
oldStdin
newStdin
=
do
loop
stdinInput
oldStdin
newStdin
=
do
let
FileHandle
_
mvar
=
stdin
let
FileHandle
_
mvar
=
stdin
threadDelay
$
150
*
1000
threadDelay
$
150
*
1000
empty
<-
isEmptyMVar
mvar
empty
<-
isEmptyMVar
mvar
if
not
empty
if
not
empty
then
loop
stdinInput
oldStdin
newStdin
then
loop
stdinInput
oldStdin
newStdin
else
do
else
do
line
<-
getInputLine
dir
line
<-
getInputLine
dir
hPutStr
stdinInput
$
line
++
"
\n
"
hPutStr
stdinInput
$
line
++
"
\n
"
loop
stdinInput
oldStdin
newStdin
loop
stdinInput
oldStdin
newStdin
-- | Get a line of input from the IPython frontend.
-- | Get a line of input from the IPython frontend.
getInputLine
::
String
->
IO
String
getInputLine
::
String
->
IO
String
...
@@ -98,15 +88,15 @@ getInputLine dir = do
...
@@ -98,15 +88,15 @@ getInputLine dir = do
-- Send a request for input.
-- Send a request for input.
uuid
<-
UUID
.
random
uuid
<-
UUID
.
random
parentHeader
<-
read
<$>
readFile
(
dir
++
"/.last-req-header"
)
parentHeader
<-
read
<$>
readFile
(
dir
++
"/.last-req-header"
)
let
header
=
MessageHeader
{
let
header
=
MessageHeader
username
=
username
parentHeader
,
{
username
=
username
parentHeader
identifiers
=
identifiers
parentHeader
,
,
identifiers
=
identifiers
parentHeader
parentHeader
=
Just
parentHeader
,
,
parentHeader
=
Just
parentHeader
messageId
=
uuid
,
,
messageId
=
uuid
sessionId
=
sessionId
parentHeader
,
,
sessionId
=
sessionId
parentHeader
metadata
=
Map
.
fromList
[]
,
,
metadata
=
Map
.
fromList
[]
msgType
=
InputRequestMessage
,
msgType
=
InputRequestMessage
}
}
let
msg
=
RequestInput
header
""
let
msg
=
RequestInput
header
""
writeChan
req
msg
writeChan
req
msg
...
...
ipython-kernel/src/IHaskell/IPython/Types.hs
View file @
c53f70d8
This diff is collapsed.
Click to expand it.
ipython-kernel/src/IHaskell/IPython/ZeroMQ.hs
View file @
c53f70d8
This diff is collapsed.
Click to expand it.
verify_formatting.py
View file @
c53f70d8
...
@@ -44,10 +44,15 @@ except:
...
@@ -44,10 +44,15 @@ except:
# Find all the source files
# Find all the source files
sources
=
[]
sources
=
[]
for
root
,
dirnames
,
filenames
in
os
.
walk
(
"src"
):
for
source_dir
in
[
"src"
,
"ipython-kernel"
]:
for
filename
in
filenames
:
for
root
,
dirnames
,
filenames
in
os
.
walk
(
source_dir
):
if
filename
.
endswith
(
".hs"
):
# Skip cabal dist directories
sources
.
append
(
os
.
path
.
join
(
root
,
filename
))
if
"dist"
in
root
:
continue
for
filename
in
filenames
:
if
filename
.
endswith
(
".hs"
):
sources
.
append
(
os
.
path
.
join
(
root
,
filename
))
hindent_outputs
=
{}
hindent_outputs
=
{}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment