Skip to content

Commit b873e78

Browse files
committed
started docs on ipython_protocol. need to finish
1 parent 52f560f commit b873e78

File tree

3 files changed

+128
-33
lines changed

3 files changed

+128
-33
lines changed

src/cpp_plot.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ std::string LoadFile(std::string filename);
2020
*
2121
* The NumpyArray is named at construction with the name of the python
2222
* variable into which its data will be placed. The name is immutable, but
23-
* the data held by this array is not.
23+
* the data held by this array is not. The data must be of type
24+
* NumpyArray::dtype.
2425
*
2526
* Usage:
2627
\code
@@ -38,6 +39,9 @@ std::string LoadFile(std::string filename);
3839
*/
3940
class NumpyArray {
4041
public:
42+
/** The type expected by numpy when reading the raw data buffer. The data
43+
* passed to NumpyArray must be of this type.
44+
*/
4145
typedef double dtype;
4246

4347
//--------------------------------------------------

src/ipython_protocol.cc

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
#include "ipython_protocol.hpp"
77

8+
/// Delimeter used by the iPython messaging protocol to separate ZMQ
9+
/// identities from message data.
10+
static const std::string DELIM{"<IDS|MSG>"};
11+
812
std::string GetUuid (void) {
913
uuid_t uuid;
1014
char uuid_str[37] = {'\0'};
@@ -49,21 +53,21 @@ IPyKernelConfig::IPyKernelConfig (const std::string &jsonConfigFile) {
4953

5054

5155
std::vector<Json::Value> IPythonMessage::GetMessageParts (void) const {
52-
return {header_, parent_, metadata_, content_};
56+
return {header, parent, metadata, content};
5357
}
5458

5559

5660
IPythonMessage MessageBuilder::BuildExecuteRequest (
5761
const std::string &code) const {
5862
IPythonMessage message{ident_};
5963

60-
message.header_["msg_type"] = "execute_request";
61-
message.content_["code"] = code;
62-
message.content_["silent"] = false;
63-
message.content_["store_history"] = true;
64-
message.content_["user_variables"] = Json::Value(Json::arrayValue);
65-
message.content_["user_expressions"] = Json::Value(Json::objectValue);
66-
message.content_["allow_stdin"] = false;
64+
message.header["msg_type"] = "execute_request";
65+
message.content["code"] = code;
66+
message.content["silent"] = false;
67+
message.content["store_history"] = true;
68+
message.content["user_variables"] = Json::Value(Json::arrayValue);
69+
message.content["user_expressions"] = Json::Value(Json::objectValue);
70+
message.content["allow_stdin"] = false;
6771

6872
return message;
6973
}
@@ -141,9 +145,9 @@ void ShellConnection::RunCode (const std::string &code) {
141145

142146
bool ShellConnection::HasVariable (const std::string &variable_name) {
143147
IPythonMessage command = message_builder_.BuildExecuteRequest("None");
144-
command.content_["user_variables"].append(variable_name);
148+
command.content["user_variables"].append(variable_name);
145149
IPythonMessage response = Send(command);
146-
return response.content_["user_variables"][variable_name]["status"]
150+
return response.content["user_variables"][variable_name]["status"]
147151
.asString() == "ok";
148152
}
149153

src/ipython_protocol.hpp

Lines changed: 109 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,74 +20,161 @@ extern "C" {
2020

2121
struct IPyKernelConfig; // forward def
2222

23+
/// Function object that computes an HMAC hash from a vector of JSON values.
2324
typedef std::function<std::string(std::vector<Json::Value>)> HmacFn;
24-
enum class PortType {SHELL, IOPUB, STDIN, HB};
2525

26-
const std::string DELIM{"<IDS|MSG>"};
26+
/// The different kinds of socket ports that an iPython kernel listens on.
27+
enum class PortType {SHELL, IOPUB, STDIN, HB};
2728

29+
//--------------------------------------------------
30+
/** \brief Generates a new UUID
31+
*/
2832
std::string GetUuid(void);
2933

34+
35+
//--------------------------------------------------
36+
/** \brief Returns a string URI like "tcp://hostname:port" from its args.
37+
*
38+
* \param config Config containing hostname and transport type.
39+
* \param port Port the host is listening on.
40+
*/
3041
std::string BuildUri(const IPyKernelConfig &config, PortType port);
3142

3243

44+
//======================================================================
45+
/** \brief Configuration values for connecting to an iPython kernel. See
46+
* http://ipython.org/ipython-doc/1/development/messaging.html for more
47+
* details.
48+
*/
3349
struct IPyKernelConfig {
50+
/// The port the shell socket is listening on
3451
size_t shell_port;
52+
53+
/// The port the iopub socket is listening on
3554
size_t iopub_port;
55+
56+
/// The port the stdin socket is listening on
3657
size_t stdin_port;
58+
59+
/// The port the shell is listening on
3760
size_t hb_port;
61+
62+
/// The IP address the kernel is listening on
3863
std::string ip;
64+
65+
/// The transport used by the kernel, e.g., "tcp"
3966
std::string transport;
67+
68+
/// \brief The hash function used to generate HMACs. Only sha-256 is
69+
/// supported at this time.
4070
std::string signature_scheme;
71+
72+
/// The key used for HMAC generation
4173
std::string key;
4274

75+
//--------------------------------------------------
76+
/** \brief Constructs a new IPyKernelConfig from a JSON file on disk, such
77+
* as the one generated by \code ipython kernel --pylab \endcode.
78+
*/
4379
IPyKernelConfig (const std::string &jsonConfigFile);
4480
};
4581

4682

47-
class IPythonMessage {
48-
public:
49-
Json::Value header_;
50-
Json::Value parent_;
51-
Json::Value metadata_;
52-
Json::Value content_;
83+
//======================================================================
84+
/** \brief Struct that wraps up the different data (i.e. not metadata like
85+
* HMAC) fields for an IPython ZMQ General Message Format. See
86+
* http://ipython.org/ipython-doc/1/development/messaging.html#general-message-format
87+
* for more detail.
88+
*/
89+
struct IPythonMessage {
90+
/// The header = {'msg_id', 'username', 'session', 'msg_type'}
91+
Json::Value header;
92+
93+
/// The header of this message's parent. To associate response with request
94+
Json::Value parent;
5395

96+
/// Metadata for this message. Seems to be unused?
97+
Json::Value metadata;
98+
99+
/// Content payload for this message. msg_type dependant.
100+
Json::Value content;
101+
102+
//--------------------------------------------------
103+
/** \brief Constructs an empty message for a specific session.
104+
*
105+
* \param ident identity of the session this message belongs to.
106+
*/
54107
explicit IPythonMessage(const std::string &ident)
55-
: header_{Json::objectValue},
56-
parent_{Json::objectValue},
57-
metadata_{Json::objectValue},
58-
content_{Json::objectValue}
108+
: header{Json::objectValue},
109+
parent{Json::objectValue},
110+
metadata{Json::objectValue},
111+
content{Json::objectValue}
59112
{
60113
char username[80];
61114
getlogin_r(username, 80);
62-
header_["username"] = std::string(username);
63-
header_["session"] = ident;
64-
header_["msg_id"] = GetUuid();
115+
header["username"] = std::string(username);
116+
header["session"] = ident;
117+
header["msg_id"] = GetUuid();
65118
}
66119

120+
//--------------------------------------------------
121+
/** \brief Constructs a message with predefined fields.
122+
*
123+
* \param message_parts A vector of JSON objects to assign to each of the
124+
* fields. It assumes the elements will be in order
125+
* [header, parent_header, metadata, content].
126+
*/
67127
explicit IPythonMessage(const std::vector<Json::Value> &message_parts)
68-
: header_(message_parts[0]),
69-
parent_(message_parts[1]),
70-
metadata_(message_parts[2]),
71-
content_(message_parts[3])
128+
: header(message_parts[0]),
129+
parent(message_parts[1]),
130+
metadata(message_parts[2]),
131+
content(message_parts[3])
72132
{}
73133

74134
std::vector<Json::Value> GetMessageParts(void) const;
75135
};
76136

77137

138+
//======================================================================
139+
/** \brief Class of factory methods for constructing various kinds of
140+
* IPythonMessages associated with a particular session.
141+
*
142+
* Usage:
143+
\code
144+
MessageBuilder builder("my_session_id");
145+
IPythonMessage command = builder.BuildExecuteRequest("print 'Hello!'");
146+
\endcode
147+
*/
78148
class MessageBuilder {
79149
public:
80-
MessageBuilder(const std::string &ident) : ident_(ident) {}
81-
150+
//--------------------------------------------------
151+
/** \brief Constructs a new MessageBuilder associated with a specific
152+
* session.
153+
*
154+
* \param ident the identity of the session, any arbitrary string, but .
155+
*/
156+
explicit MessageBuilder(const std::string &ident) : ident_(ident) {}
157+
158+
//--------------------------------------------------
159+
/** \brief Returns a new ExecuteRequest message.
160+
*
161+
* \param code The code to be run in an iPython kernel.
162+
*/
82163
IPythonMessage BuildExecuteRequest (const std::string &code) const ;
83164

84165
private:
85166
const std::string ident_;
86167
};
87168

88169

170+
//======================================================================
171+
/** \brief A connection to the shell socket of an iPython kernel.
172+
*
173+
* TODO fill this out!
174+
*/
89175
class ShellConnection {
90176
public:
177+
//
91178
ShellConnection(const IPyKernelConfig &config, zmq::context_t &context,
92179
const HmacFn &hmac_fn)
93180
: hmac_fn_{hmac_fn},
@@ -113,7 +200,7 @@ class ShellConnection {
113200

114201
class IPythonSession {
115202
public:
116-
IPythonSession (const IPyKernelConfig &config)
203+
explicit IPythonSession (const IPyKernelConfig &config)
117204
: config_{config},
118205
zmq_context_{1},
119206
hmac_fn_{std::bind(&IPythonSession::ComputeHMAC_, this,

0 commit comments

Comments
 (0)