##// END OF EJS Templates
Allow IPython to run without sqlite3...
MinRK -
Show More
@@ -17,12 +17,15 b' import atexit'
17 17 import datetime
18 18 import os
19 19 import re
20 import sqlite3
20 try:
21 import sqlite3
22 except ImportError:
23 sqlite3 = None
21 24 import threading
22 25
23 26 # Our own packages
24 27 from IPython.config.configurable import Configurable
25
28 from IPython.external.decorator import decorator
26 29 from IPython.testing.skipdoctest import skip_doctest
27 30 from IPython.utils import io
28 31 from IPython.utils.path import locate_profile
@@ -33,6 +36,30 b' from IPython.utils.warn import warn'
33 36 # Classes and functions
34 37 #-----------------------------------------------------------------------------
35 38
39 class DummyDB(object):
40 """Dummy DB that will act as a black hole for history.
41
42 Only used in the absence of sqlite"""
43 def execute(*args, **kwargs):
44 return []
45
46 def commit(self, *args, **kwargs):
47 pass
48
49 def __enter__(self, *args, **kwargs):
50 pass
51
52 def __exit__(self, *args, **kwargs):
53 pass
54
55 @decorator
56 def needs_sqlite(f,*a,**kw):
57 """return an empty list in the absence of sqlite"""
58 if sqlite3 is None:
59 return []
60 else:
61 return f(*a,**kw)
62
36 63 class HistoryAccessor(Configurable):
37 64 """Access the history database without adding to it.
38 65
@@ -42,7 +69,10 b' class HistoryAccessor(Configurable):'
42 69 hist_file = Unicode(config=True)
43 70
44 71 # The SQLite database
45 db = Instance(sqlite3.Connection)
72 if sqlite3:
73 db = Instance(sqlite3.Connection)
74 else:
75 db = Instance(DummyDB)
46 76
47 77 def __init__(self, profile='default', hist_file=u'', shell=None, config=None, **traits):
48 78 """Create a new history accessor.
@@ -67,6 +97,11 b' class HistoryAccessor(Configurable):'
67 97 # No one has set the hist_file, yet.
68 98 self.hist_file = self._get_hist_file_name(profile)
69 99
100 if sqlite3 is None:
101 warn("IPython History requires SQLite, your history will not be saved\n")
102 self.db = DummyDB()
103 return
104
70 105 try:
71 106 self.init_db()
72 107 except sqlite3.DatabaseError:
@@ -146,6 +181,7 b' class HistoryAccessor(Configurable):'
146 181 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
147 182 return cur
148 183
184 @needs_sqlite
149 185 def get_session_info(self, session=0):
150 186 """get info about a session
151 187
@@ -351,7 +387,7 b' class HistoryManager(HistoryAccessor):'
351 387 self.save_thread.start()
352 388
353 389 self.new_session()
354
390
355 391 def _get_hist_file_name(self, profile=None):
356 392 """Get default history file name based on the Shell's profile.
357 393
@@ -360,6 +396,7 b' class HistoryManager(HistoryAccessor):'
360 396 profile_dir = self.shell.profile_dir.location
361 397 return os.path.join(profile_dir, 'history.sqlite')
362 398
399 @needs_sqlite
363 400 def new_session(self, conn=None):
364 401 """Get a new session number."""
365 402 if conn is None:
@@ -537,6 +574,7 b' class HistoryManager(HistoryAccessor):'
537 574 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
538 575 (self.session_number,)+line)
539 576
577 @needs_sqlite
540 578 def writeout_cache(self, conn=None):
541 579 """Write any entries in the cache to the database."""
542 580 if conn is None:
@@ -581,6 +619,7 b' class HistorySavingThread(threading.Thread):'
581 619 self.history_manager = history_manager
582 620 atexit.register(self.stop)
583 621
622 @needs_sqlite
584 623 def run(self):
585 624 # We need a separate db connection per thread:
586 625 try:
@@ -55,7 +55,8 b' def test_magic_parse_options():'
55 55 expected = path
56 56 nt.assert_equals(opts['f'], expected)
57 57
58
58
59 @dec.skip_without('sqlite3')
59 60 def doctest_hist_f():
60 61 """Test %hist -f with temporary filename.
61 62
@@ -69,6 +70,7 b' def doctest_hist_f():'
69 70 """
70 71
71 72
73 @dec.skip_without('sqlite3')
72 74 def doctest_hist_r():
73 75 """Test %hist -r
74 76
@@ -86,6 +88,8 b' def doctest_hist_r():'
86 88 %hist -r 2
87 89 """
88 90
91
92 @dec.skip_without('sqlite3')
89 93 def doctest_hist_op():
90 94 """Test %hist -op
91 95
@@ -151,7 +155,9 b' def doctest_hist_op():'
151 155 's'
152 156 >>>
153 157 """
154
158
159
160 @dec.skip_without('sqlite3')
155 161 def test_macro():
156 162 ip = get_ipython()
157 163 ip.history_manager.reset() # Clear any existing history.
@@ -164,6 +170,8 b' def test_macro():'
164 170 # List macros.
165 171 assert "test" in ip.magic("macro")
166 172
173
174 @dec.skip_without('sqlite3')
167 175 def test_macro_run():
168 176 """Test that we can run a multi-line macro successfully."""
169 177 ip = get_ipython()
@@ -169,9 +169,13 b' class TestMagicRunSimple(tt.TempFileMixin):'
169 169 " print 'object A deleted'\n"
170 170 "a = A()\n")
171 171 self.mktmp(py3compat.doctest_refactor_print(src))
172 tt.ipexec_validate(self.fname, 'object A deleted')
173
174 @dec.skip_known_failure
172 if dec.module_not_available('sqlite3'):
173 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
174 else:
175 err = None
176 tt.ipexec_validate(self.fname, 'object A deleted', err)
177
178 @dec.skip_known_failure
175 179 def test_aggressive_namespace_cleanup(self):
176 180 """Test that namespace cleanup is not too aggressive GH-238
177 181
@@ -207,4 +211,8 b" ARGV 1-: ['C-third']"
207 211 tclass.py: deleting object: C-second
208 212 tclass.py: deleting object: C-third
209 213 """
210 tt.ipexec_validate(self.fname, out)
214 if dec.module_not_available('sqlite3'):
215 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
216 else:
217 err = None
218 tt.ipexec_validate(self.fname, out, err)
@@ -16,7 +16,10 b' import os'
16 16 import cPickle as pickle
17 17 from datetime import datetime
18 18
19 import sqlite3
19 try:
20 import sqlite3
21 except ImportError:
22 sqlite3 = None
20 23
21 24 from zmq.eventloop import ioloop
22 25
@@ -99,7 +102,10 b' class SQLiteDB(BaseDB):'
99 102 in tasks from previous sessions being available via Clients' db_query and
100 103 get_result methods.""")
101 104
102 _db = Instance('sqlite3.Connection')
105 if sqlite3 is not None:
106 _db = Instance('sqlite3.Connection')
107 else:
108 _db = None
103 109 # the ordered list of column names
104 110 _keys = List(['msg_id' ,
105 111 'header' ,
@@ -145,6 +151,8 b' class SQLiteDB(BaseDB):'
145 151
146 152 def __init__(self, **kwargs):
147 153 super(SQLiteDB, self).__init__(**kwargs)
154 if sqlite3 is None:
155 raise ImportError("SQLiteDB requires sqlite3")
148 156 if not self.table:
149 157 # use session, and prefix _, since starting with # is illegal
150 158 self.table = '_'+self.session.replace('-','_')
@@ -24,13 +24,12 b' import time'
24 24 from datetime import datetime, timedelta
25 25 from unittest import TestCase
26 26
27 from nose import SkipTest
28
29 27 from IPython.parallel import error
30 28 from IPython.parallel.controller.dictdb import DictDB
31 29 from IPython.parallel.controller.sqlitedb import SQLiteDB
32 30 from IPython.parallel.controller.hub import init_record, empty_record
33 31
32 from IPython.testing import decorators as dec
34 33 from IPython.zmq.session import Session
35 34
36 35
@@ -171,8 +170,11 b' class TestDictBackend(TestCase):'
171 170 self.db.drop_matching_records(query)
172 171 recs = self.db.find_records(query)
173 172 self.assertEquals(len(recs), 0)
174
173
174
175 175 class TestSQLiteBackend(TestDictBackend):
176
177 @dec.skip_without('sqlite3')
176 178 def create_db(self):
177 179 return SQLiteDB(location=tempfile.gettempdir())
178 180
@@ -128,6 +128,7 b" have['pymongo'] = test_for('pymongo')"
128 128 have['wx'] = test_for('wx')
129 129 have['wx.aui'] = test_for('wx.aui')
130 130 have['qt'] = test_for('IPython.external.qt')
131 have['sqlite3'] = test_for('sqlite3')
131 132
132 133 have['tornado'] = test_for('tornado.version_info', (2,1,0), callback=None)
133 134
@@ -204,7 +205,9 b' def make_exclude():'
204 205 ipjoin('config', 'default'),
205 206 ipjoin('config', 'profile'),
206 207 ]
207
208 if not have['sqlite3']:
209 exclusions.append(ipjoin('core', 'tests', 'test_history'))
210 exclusions.append(ipjoin('core', 'history'))
208 211 if not have['wx']:
209 212 exclusions.append(ipjoin('lib', 'inputhookwx'))
210 213
General Comments 0
You need to be logged in to leave comments. Login now