##// END OF EJS Templates
Fixes for notebook session manager
Thomas Kluyver -
Show More
@@ -1,202 +1,202 b''
1 """A base class session manager.
1 """A base class session manager.
2
2
3 Authors:
3 Authors:
4
4
5 * Zach Sailer
5 * Zach Sailer
6 """
6 """
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2013 The IPython Development Team
9 # Copyright (C) 2013 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 import uuid
19 import uuid
20 import sqlite3
20 import sqlite3
21
21
22 from tornado import web
22 from tornado import web
23
23
24 from IPython.config.configurable import LoggingConfigurable
24 from IPython.config.configurable import LoggingConfigurable
25 from IPython.utils.py3compat import unicode_type
25 from IPython.utils.py3compat import unicode_type
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Classes
28 # Classes
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 class SessionManager(LoggingConfigurable):
31 class SessionManager(LoggingConfigurable):
32
32
33 # Session database initialized below
33 # Session database initialized below
34 _cursor = None
34 _cursor = None
35 _connection = None
35 _connection = None
36 _columns = {'session_id', 'name', 'path', 'kernel_id', 'ws_url'}
36 _columns = {'session_id', 'name', 'path', 'kernel_id', 'ws_url'}
37
37
38 @property
38 @property
39 def cursor(self):
39 def cursor(self):
40 """Start a cursor and create a database called 'session'"""
40 """Start a cursor and create a database called 'session'"""
41 if self._cursor is None:
41 if self._cursor is None:
42 self._cursor = self.connection.cursor()
42 self._cursor = self.connection.cursor()
43 self._cursor.execute("""CREATE TABLE session
43 self._cursor.execute("""CREATE TABLE session
44 (session_id, name, path, kernel_id, ws_url)""")
44 (session_id, name, path, kernel_id, ws_url)""")
45 return self._cursor
45 return self._cursor
46
46
47 @property
47 @property
48 def connection(self):
48 def connection(self):
49 """Start a database connection"""
49 """Start a database connection"""
50 if self._connection is None:
50 if self._connection is None:
51 self._connection = sqlite3.connect(':memory:')
51 self._connection = sqlite3.connect(':memory:')
52 self._connection.row_factory = self.row_factory
52 self._connection.row_factory = self.row_factory
53 return self._connection
53 return self._connection
54
54
55 def __del__(self):
55 def __del__(self):
56 """Close connection once SessionManager closes"""
56 """Close connection once SessionManager closes"""
57 self.cursor.close()
57 self.cursor.close()
58
58
59 def session_exists(self, name, path):
59 def session_exists(self, name, path):
60 """Check to see if the session for a given notebook exists"""
60 """Check to see if the session for a given notebook exists"""
61 self.cursor.execute("SELECT * FROM session WHERE name=? AND path=?", (name, path))
61 self.cursor.execute("SELECT * FROM session WHERE name=? AND path=?", (name, path))
62 reply = self.cursor.fetchone()
62 reply = self.cursor.fetchone()
63 if reply is None:
63 if reply is None:
64 return False
64 return False
65 else:
65 else:
66 return True
66 return True
67
67
68 def new_session_id(self):
68 def new_session_id(self):
69 "Create a uuid for a new session"
69 "Create a uuid for a new session"
70 return unicode_type(uuid.uuid4())
70 return unicode_type(uuid.uuid4())
71
71
72 def create_session(self, name=None, path=None, kernel_id=None, ws_url=None):
72 def create_session(self, name=None, path=None, kernel_id=None, ws_url=None):
73 """Creates a session and returns its model"""
73 """Creates a session and returns its model"""
74 session_id = self.new_session_id()
74 session_id = self.new_session_id()
75 return self.save_session(session_id, name=name, path=path, kernel_id=kernel_id, ws_url=ws_url)
75 return self.save_session(session_id, name=name, path=path, kernel_id=kernel_id, ws_url=ws_url)
76
76
77 def save_session(self, session_id, name=None, path=None, kernel_id=None, ws_url=None):
77 def save_session(self, session_id, name=None, path=None, kernel_id=None, ws_url=None):
78 """Saves the items for the session with the given session_id
78 """Saves the items for the session with the given session_id
79
79
80 Given a session_id (and any other of the arguments), this method
80 Given a session_id (and any other of the arguments), this method
81 creates a row in the sqlite session database that holds the information
81 creates a row in the sqlite session database that holds the information
82 for a session.
82 for a session.
83
83
84 Parameters
84 Parameters
85 ----------
85 ----------
86 session_id : str
86 session_id : str
87 uuid for the session; this method must be given a session_id
87 uuid for the session; this method must be given a session_id
88 name : str
88 name : str
89 the .ipynb notebook name that started the session
89 the .ipynb notebook name that started the session
90 path : str
90 path : str
91 the path to the named notebook
91 the path to the named notebook
92 kernel_id : str
92 kernel_id : str
93 a uuid for the kernel associated with this session
93 a uuid for the kernel associated with this session
94 ws_url : str
94 ws_url : str
95 the websocket url
95 the websocket url
96
96
97 Returns
97 Returns
98 -------
98 -------
99 model : dict
99 model : dict
100 a dictionary of the session model
100 a dictionary of the session model
101 """
101 """
102 self.cursor.execute("INSERT INTO session VALUES (?,?,?,?,?)",
102 self.cursor.execute("INSERT INTO session VALUES (?,?,?,?,?)",
103 (session_id, name, path, kernel_id, ws_url)
103 (session_id, name, path, kernel_id, ws_url)
104 )
104 )
105 return self.get_session(session_id=session_id)
105 return self.get_session(session_id=session_id)
106
106
107 def get_session(self, **kwargs):
107 def get_session(self, **kwargs):
108 """Returns the model for a particular session.
108 """Returns the model for a particular session.
109
109
110 Takes a keyword argument and searches for the value in the session
110 Takes a keyword argument and searches for the value in the session
111 database, then returns the rest of the session's info.
111 database, then returns the rest of the session's info.
112
112
113 Parameters
113 Parameters
114 ----------
114 ----------
115 **kwargs : keyword argument
115 **kwargs : keyword argument
116 must be given one of the keywords and values from the session database
116 must be given one of the keywords and values from the session database
117 (i.e. session_id, name, path, kernel_id, ws_url)
117 (i.e. session_id, name, path, kernel_id, ws_url)
118
118
119 Returns
119 Returns
120 -------
120 -------
121 model : dict
121 model : dict
122 returns a dictionary that includes all the information from the
122 returns a dictionary that includes all the information from the
123 session described by the kwarg.
123 session described by the kwarg.
124 """
124 """
125 if not kwargs:
125 if not kwargs:
126 raise TypeError("must specify a column to query")
126 raise TypeError("must specify a column to query")
127
127
128 conditions = []
128 conditions = []
129 for column in kwargs.keys():
129 for column in kwargs.keys():
130 if column not in self._columns:
130 if column not in self._columns:
131 raise TypeError("No such column: %r", column)
131 raise TypeError("No such column: %r", column)
132 conditions.append("%s=?" % column)
132 conditions.append("%s=?" % column)
133
133
134 query = "SELECT * FROM session WHERE %s" % (' AND '.join(conditions))
134 query = "SELECT * FROM session WHERE %s" % (' AND '.join(conditions))
135
135
136 self.cursor.execute(query, kwargs.values())
136 self.cursor.execute(query, list(kwargs.values()))
137 model = self.cursor.fetchone()
137 model = self.cursor.fetchone()
138 if model is None:
138 if model is None:
139 q = []
139 q = []
140 for key, value in kwargs.items():
140 for key, value in kwargs.items():
141 q.append("%s=%r" % (key, value))
141 q.append("%s=%r" % (key, value))
142
142
143 raise web.HTTPError(404, u'Session not found: %s' % (', '.join(q)))
143 raise web.HTTPError(404, u'Session not found: %s' % (', '.join(q)))
144 return model
144 return model
145
145
146 def update_session(self, session_id, **kwargs):
146 def update_session(self, session_id, **kwargs):
147 """Updates the values in the session database.
147 """Updates the values in the session database.
148
148
149 Changes the values of the session with the given session_id
149 Changes the values of the session with the given session_id
150 with the values from the keyword arguments.
150 with the values from the keyword arguments.
151
151
152 Parameters
152 Parameters
153 ----------
153 ----------
154 session_id : str
154 session_id : str
155 a uuid that identifies a session in the sqlite3 database
155 a uuid that identifies a session in the sqlite3 database
156 **kwargs : str
156 **kwargs : str
157 the key must correspond to a column title in session database,
157 the key must correspond to a column title in session database,
158 and the value replaces the current value in the session
158 and the value replaces the current value in the session
159 with session_id.
159 with session_id.
160 """
160 """
161 self.get_session(session_id=session_id)
161 self.get_session(session_id=session_id)
162
162
163 if not kwargs:
163 if not kwargs:
164 # no changes
164 # no changes
165 return
165 return
166
166
167 sets = []
167 sets = []
168 for column in kwargs.keys():
168 for column in kwargs.keys():
169 if column not in self._columns:
169 if column not in self._columns:
170 raise TypeError("No such column: %r" % column)
170 raise TypeError("No such column: %r" % column)
171 sets.append("%s=?" % column)
171 sets.append("%s=?" % column)
172 query = "UPDATE session SET %s WHERE session_id=?" % (', '.join(sets))
172 query = "UPDATE session SET %s WHERE session_id=?" % (', '.join(sets))
173 self.cursor.execute(query, kwargs.values() + [session_id])
173 self.cursor.execute(query, list(kwargs.values()) + [session_id])
174
174
175 @staticmethod
175 @staticmethod
176 def row_factory(cursor, row):
176 def row_factory(cursor, row):
177 """Takes sqlite database session row and turns it into a dictionary"""
177 """Takes sqlite database session row and turns it into a dictionary"""
178 row = sqlite3.Row(cursor, row)
178 row = sqlite3.Row(cursor, row)
179 model = {
179 model = {
180 'id': row['session_id'],
180 'id': row['session_id'],
181 'notebook': {
181 'notebook': {
182 'name': row['name'],
182 'name': row['name'],
183 'path': row['path']
183 'path': row['path']
184 },
184 },
185 'kernel': {
185 'kernel': {
186 'id': row['kernel_id'],
186 'id': row['kernel_id'],
187 'ws_url': row['ws_url']
187 'ws_url': row['ws_url']
188 }
188 }
189 }
189 }
190 return model
190 return model
191
191
192 def list_sessions(self):
192 def list_sessions(self):
193 """Returns a list of dictionaries containing all the information from
193 """Returns a list of dictionaries containing all the information from
194 the session database"""
194 the session database"""
195 c = self.cursor.execute("SELECT * FROM session")
195 c = self.cursor.execute("SELECT * FROM session")
196 return list(c.fetchall())
196 return list(c.fetchall())
197
197
198 def delete_session(self, session_id):
198 def delete_session(self, session_id):
199 """Deletes the row in the session database with given session_id"""
199 """Deletes the row in the session database with given session_id"""
200 # Check that session exists before deleting
200 # Check that session exists before deleting
201 self.get_session(session_id=session_id)
201 self.get_session(session_id=session_id)
202 self.cursor.execute("DELETE FROM session WHERE session_id=?", (session_id,))
202 self.cursor.execute("DELETE FROM session WHERE session_id=?", (session_id,))
General Comments 0
You need to be logged in to leave comments. Login now