Show More
@@ -46,7 +46,7 b' from datetime import datetime' | |||||
46 |
|
46 | |||
47 | from IPython.config.configurable import Configurable |
|
47 | from IPython.config.configurable import Configurable | |
48 |
|
48 | |||
49 | from IPython.utils.traitlets import Dict, Unicode |
|
49 | from IPython.utils.traitlets import Dict, Unicode, Instance | |
50 |
|
50 | |||
51 | filters = { |
|
51 | filters = { | |
52 | '$lt' : lambda a,b: a < b, |
|
52 | '$lt' : lambda a,b: a < b, | |
@@ -83,6 +83,7 b' class BaseDB(Configurable):' | |||||
83 | """Empty Parent class so traitlets work on DB.""" |
|
83 | """Empty Parent class so traitlets work on DB.""" | |
84 | # base configurable traits: |
|
84 | # base configurable traits: | |
85 | session = Unicode("") |
|
85 | session = Unicode("") | |
|
86 | log = Instance('logging.Logger', ('root',)) | |||
86 |
|
87 | |||
87 | class DictDB(BaseDB): |
|
88 | class DictDB(BaseDB): | |
88 | """Basic in-memory dict-based object for saving Task Records. |
|
89 | """Basic in-memory dict-based object for saving Task Records. |
@@ -15,9 +15,9 b' import sqlite3' | |||||
15 |
|
15 | |||
16 | from zmq.eventloop import ioloop |
|
16 | from zmq.eventloop import ioloop | |
17 |
|
17 | |||
18 | from IPython.utils.traitlets import Unicode, Instance, List |
|
18 | from IPython.utils.traitlets import Unicode, Instance, List, Dict | |
19 | from .dictdb import BaseDB |
|
19 | from .dictdb import BaseDB | |
20 | from IPython.utils.jsonutil import date_default, extract_dates |
|
20 | from IPython.utils.jsonutil import date_default, extract_dates, squash_dates | |
21 |
|
21 | |||
22 | #----------------------------------------------------------------------------- |
|
22 | #----------------------------------------------------------------------------- | |
23 | # SQLite operators, adapters, and converters |
|
23 | # SQLite operators, adapters, and converters | |
@@ -42,15 +42,6 b' null_operators = {' | |||||
42 | '!=' : "IS NOT NULL", |
|
42 | '!=' : "IS NOT NULL", | |
43 | } |
|
43 | } | |
44 |
|
44 | |||
45 | def _adapt_datetime(dt): |
|
|||
46 | return dt.strftime(ISO8601) |
|
|||
47 |
|
||||
48 | def _convert_datetime(ds): |
|
|||
49 | if ds is None: |
|
|||
50 | return ds |
|
|||
51 | else: |
|
|||
52 | return datetime.strptime(ds, ISO8601) |
|
|||
53 |
|
||||
54 | def _adapt_dict(d): |
|
45 | def _adapt_dict(d): | |
55 | return json.dumps(d, default=date_default) |
|
46 | return json.dumps(d, default=date_default) | |
56 |
|
47 | |||
@@ -95,6 +86,7 b' class SQLiteDB(BaseDB):' | |||||
95 | get_result methods.""") |
|
86 | get_result methods.""") | |
96 |
|
87 | |||
97 | _db = Instance('sqlite3.Connection') |
|
88 | _db = Instance('sqlite3.Connection') | |
|
89 | # the ordered list of column names | |||
98 | _keys = List(['msg_id' , |
|
90 | _keys = List(['msg_id' , | |
99 | 'header' , |
|
91 | 'header' , | |
100 | 'content', |
|
92 | 'content', | |
@@ -115,6 +107,27 b' class SQLiteDB(BaseDB):' | |||||
115 | 'stdout', |
|
107 | 'stdout', | |
116 | 'stderr', |
|
108 | 'stderr', | |
117 | ]) |
|
109 | ]) | |
|
110 | # sqlite datatypes for checking that db is current format | |||
|
111 | _types = Dict({'msg_id' : 'text' , | |||
|
112 | 'header' : 'dict text', | |||
|
113 | 'content' : 'dict text', | |||
|
114 | 'buffers' : 'bufs blob', | |||
|
115 | 'submitted' : 'timestamp', | |||
|
116 | 'client_uuid' : 'text', | |||
|
117 | 'engine_uuid' : 'text', | |||
|
118 | 'started' : 'timestamp', | |||
|
119 | 'completed' : 'timestamp', | |||
|
120 | 'resubmitted' : 'timestamp', | |||
|
121 | 'result_header' : 'dict text', | |||
|
122 | 'result_content' : 'dict text', | |||
|
123 | 'result_buffers' : 'bufs blob', | |||
|
124 | 'queue' : 'text', | |||
|
125 | 'pyin' : 'text', | |||
|
126 | 'pyout' : 'text', | |||
|
127 | 'pyerr' : 'text', | |||
|
128 | 'stdout' : 'text', | |||
|
129 | 'stderr' : 'text', | |||
|
130 | }) | |||
118 |
|
131 | |||
119 | def __init__(self, **kwargs): |
|
132 | def __init__(self, **kwargs): | |
120 | super(SQLiteDB, self).__init__(**kwargs) |
|
133 | super(SQLiteDB, self).__init__(**kwargs) | |
@@ -149,11 +162,36 b' class SQLiteDB(BaseDB):' | |||||
149 | d[key] = None |
|
162 | d[key] = None | |
150 | return d |
|
163 | return d | |
151 |
|
164 | |||
|
165 | def _check_table(self): | |||
|
166 | """Ensure that an incorrect table doesn't exist | |||
|
167 | ||||
|
168 | If a bad (old) table does exist, return False | |||
|
169 | """ | |||
|
170 | cursor = self._db.execute("PRAGMA table_info(%s)"%self.table) | |||
|
171 | lines = cursor.fetchall() | |||
|
172 | if not lines: | |||
|
173 | # table does not exist | |||
|
174 | return True | |||
|
175 | types = {} | |||
|
176 | keys = [] | |||
|
177 | for line in lines: | |||
|
178 | keys.append(line[1]) | |||
|
179 | types[line[1]] = line[2] | |||
|
180 | if self._keys != keys: | |||
|
181 | # key mismatch | |||
|
182 | self.log.warn('keys mismatch') | |||
|
183 | return False | |||
|
184 | for key in self._keys: | |||
|
185 | if types[key] != self._types[key]: | |||
|
186 | self.log.warn( | |||
|
187 | 'type mismatch: %s: %s != %s'%(key,types[key],self._types[key]) | |||
|
188 | ) | |||
|
189 | return False | |||
|
190 | return True | |||
|
191 | ||||
152 | def _init_db(self): |
|
192 | def _init_db(self): | |
153 | """Connect to the database and get new session number.""" |
|
193 | """Connect to the database and get new session number.""" | |
154 | # register adapters |
|
194 | # register adapters | |
155 | sqlite3.register_adapter(datetime, _adapt_datetime) |
|
|||
156 | sqlite3.register_converter('datetime', _convert_datetime) |
|
|||
157 | sqlite3.register_adapter(dict, _adapt_dict) |
|
195 | sqlite3.register_adapter(dict, _adapt_dict) | |
158 | sqlite3.register_converter('dict', _convert_dict) |
|
196 | sqlite3.register_converter('dict', _convert_dict) | |
159 | sqlite3.register_adapter(list, _adapt_bufs) |
|
197 | sqlite3.register_adapter(list, _adapt_bufs) | |
@@ -164,18 +202,27 b' class SQLiteDB(BaseDB):' | |||||
164 | # isolation_level = None)#, |
|
202 | # isolation_level = None)#, | |
165 | cached_statements=64) |
|
203 | cached_statements=64) | |
166 | # print dir(self._db) |
|
204 | # print dir(self._db) | |
|
205 | first_table = self.table | |||
|
206 | i=0 | |||
|
207 | while not self._check_table(): | |||
|
208 | i+=1 | |||
|
209 | self.table = first_table+'_%i'%i | |||
|
210 | self.log.warn( | |||
|
211 | "Table %s exists and doesn't match db format, trying %s"% | |||
|
212 | (first_table,self.table) | |||
|
213 | ) | |||
167 |
|
214 | |||
168 | self._db.execute("""CREATE TABLE IF NOT EXISTS %s |
|
215 | self._db.execute("""CREATE TABLE IF NOT EXISTS %s | |
169 | (msg_id text PRIMARY KEY, |
|
216 | (msg_id text PRIMARY KEY, | |
170 | header dict text, |
|
217 | header dict text, | |
171 | content dict text, |
|
218 | content dict text, | |
172 | buffers bufs blob, |
|
219 | buffers bufs blob, | |
173 |
submitted |
|
220 | submitted timestamp, | |
174 | client_uuid text, |
|
221 | client_uuid text, | |
175 | engine_uuid text, |
|
222 | engine_uuid text, | |
176 |
started |
|
223 | started timestamp, | |
177 |
completed |
|
224 | completed timestamp, | |
178 |
resubmitted |
|
225 | resubmitted timestamp, | |
179 | result_header dict text, |
|
226 | result_header dict text, | |
180 | result_content dict text, |
|
227 | result_content dict text, | |
181 | result_buffers bufs blob, |
|
228 | result_buffers bufs blob, |
General Comments 0
You need to be logged in to leave comments.
Login now