##// END OF EJS Templates
allow disabling SQLite history...
MinRK -
Show More
@@ -27,7 +27,9 b' import threading'
27 27 from IPython.config.configurable import Configurable
28 28 from IPython.external.decorator import decorator
29 29 from IPython.utils.path import locate_profile
30 from IPython.utils.traitlets import Bool, Dict, Instance, Integer, List, Unicode
30 from IPython.utils.traitlets import (
31 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
32 )
31 33 from IPython.utils.warn import warn
32 34
33 35 #-----------------------------------------------------------------------------
@@ -52,12 +54,12 b' class DummyDB(object):'
52 54
53 55
54 56 @decorator
55 def needs_sqlite(f,*a,**kw):
57 def needs_sqlite(f, self, *a, **kw):
56 58 """return an empty list in the absence of sqlite"""
57 if sqlite3 is None:
59 if sqlite is None or self.disabled:
58 60 return []
59 61 else:
60 return f(*a,**kw)
62 return f(self, *a, **kw)
61 63
62 64
63 65 class HistoryAccessor(Configurable):
@@ -81,12 +83,32 b' class HistoryAccessor(Configurable):'
81 83 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
82 84
83 85 """)
86
87 disabled = Bool(False, config=True,
88 help="""disable the SQLite history
89
90 If True there will be no stored history, no SQLite connection,
91 and no background saving thread. This may be necessary in some
92 threaded environments where IPython is embedded.
93 """
94 )
95
96 connection_options = Dict(config=True,
97 help="""Options for configuring the SQLite connection
98
99 These options are passed as keyword args to sqlite3.connect
100 when establishing database conenctions.
101 """
102 )
84 103
85 104 # The SQLite database
86 if sqlite3:
87 db = Instance(sqlite3.Connection)
88 else:
89 db = Instance(DummyDB)
105 db = Any()
106 def _db_changed(self, name, old, new):
107 """validate the db, since it can be an Instance of two different types"""
108 if not isinstance(new, (sqlite3.Connection, DummyDB)):
109 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
110 (self.__class__.__name__, new)
111 raise TraitError(msg)
90 112
91 113 def __init__(self, profile='default', hist_file=u'', config=None, **traits):
92 114 """Create a new history accessor.
@@ -113,14 +135,18 b' class HistoryAccessor(Configurable):'
113 135 # No one has set the hist_file, yet.
114 136 self.hist_file = self._get_hist_file_name(profile)
115 137
116 if sqlite3 is None:
138 if sqlite3 is None and not self.disabled:
117 139 warn("IPython History requires SQLite, your history will not be saved\n")
118 self.db = DummyDB()
119 return
140 self.disabled = True
141
142 if sqlite3 is not None:
143 DatabaseError = sqlite3.DatabaseError
144 else:
145 DatabaseError = Exception
120 146
121 147 try:
122 148 self.init_db()
123 except sqlite3.DatabaseError:
149 except DatabaseError:
124 150 if os.path.isfile(self.hist_file):
125 151 # Try to move the file out of the way
126 152 base,ext = os.path.splitext(self.hist_file)
@@ -148,9 +174,14 b' class HistoryAccessor(Configurable):'
148 174
149 175 def init_db(self):
150 176 """Connect to the database, and create tables if necessary."""
177 if self.disabled:
178 self.db = DummyDB()
179 return
180
151 181 # use detect_types so that timestamps return datetime objects
152 self.db = sqlite3.connect(self.hist_file,
153 detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
182 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
183 kwargs.update(self.connection_options)
184 self.db = sqlite3.connect(self.hist_file, **kwargs)
154 185 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
155 186 primary key autoincrement, start timestamp,
156 187 end timestamp, num_cmds integer, remark text)""")
@@ -402,7 +433,7 b' class HistoryManager(HistoryAccessor):'
402 433 self.save_flag = threading.Event()
403 434 self.db_input_cache_lock = threading.Lock()
404 435 self.db_output_cache_lock = threading.Lock()
405 if self.hist_file != ':memory:':
436 if not self.disabled and self.hist_file != ':memory:':
406 437 self.save_thread = HistorySavingThread(self)
407 438 self.save_thread.start()
408 439
@@ -638,16 +669,20 b' class HistorySavingThread(threading.Thread):'
638 669 the cache size reaches a defined threshold."""
639 670 daemon = True
640 671 stop_now = False
672 disabled = False
641 673 def __init__(self, history_manager):
642 674 super(HistorySavingThread, self).__init__()
643 675 self.history_manager = history_manager
676 self.disabled = history_manager.disabled
644 677 atexit.register(self.stop)
645 678
646 679 @needs_sqlite
647 680 def run(self):
648 681 # We need a separate db connection per thread:
649 682 try:
650 self.db = sqlite3.connect(self.history_manager.hist_file)
683 self.db = sqlite3.connect(self.history_manager.hist_file,
684 **self.history_manager.connection_options
685 )
651 686 while True:
652 687 self.history_manager.save_flag.wait()
653 688 if self.stop_now:
General Comments 0
You need to be logged in to leave comments. Login now