##// END OF EJS Templates
allow disabling SQLite history...
MinRK -
Show More
@@ -27,7 +27,9 b' import threading'
27 from IPython.config.configurable import Configurable
27 from IPython.config.configurable import Configurable
28 from IPython.external.decorator import decorator
28 from IPython.external.decorator import decorator
29 from IPython.utils.path import locate_profile
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 from IPython.utils.warn import warn
33 from IPython.utils.warn import warn
32
34
33 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
@@ -52,12 +54,12 b' class DummyDB(object):'
52
54
53
55
54 @decorator
56 @decorator
55 def needs_sqlite(f,*a,**kw):
57 def needs_sqlite(f, self, *a, **kw):
56 """return an empty list in the absence of sqlite"""
58 """return an empty list in the absence of sqlite"""
57 if sqlite3 is None:
59 if sqlite is None or self.disabled:
58 return []
60 return []
59 else:
61 else:
60 return f(*a,**kw)
62 return f(self, *a, **kw)
61
63
62
64
63 class HistoryAccessor(Configurable):
65 class HistoryAccessor(Configurable):
@@ -81,12 +83,32 b' class HistoryAccessor(Configurable):'
81 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
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 # The SQLite database
104 # The SQLite database
86 if sqlite3:
105 db = Any()
87 db = Instance(sqlite3.Connection)
106 def _db_changed(self, name, old, new):
88 else:
107 """validate the db, since it can be an Instance of two different types"""
89 db = Instance(DummyDB)
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 def __init__(self, profile='default', hist_file=u'', config=None, **traits):
113 def __init__(self, profile='default', hist_file=u'', config=None, **traits):
92 """Create a new history accessor.
114 """Create a new history accessor.
@@ -113,14 +135,18 b' class HistoryAccessor(Configurable):'
113 # No one has set the hist_file, yet.
135 # No one has set the hist_file, yet.
114 self.hist_file = self._get_hist_file_name(profile)
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 warn("IPython History requires SQLite, your history will not be saved\n")
139 warn("IPython History requires SQLite, your history will not be saved\n")
118 self.db = DummyDB()
140 self.disabled = True
119 return
141
142 if sqlite3 is not None:
143 DatabaseError = sqlite3.DatabaseError
144 else:
145 DatabaseError = Exception
120
146
121 try:
147 try:
122 self.init_db()
148 self.init_db()
123 except sqlite3.DatabaseError:
149 except DatabaseError:
124 if os.path.isfile(self.hist_file):
150 if os.path.isfile(self.hist_file):
125 # Try to move the file out of the way
151 # Try to move the file out of the way
126 base,ext = os.path.splitext(self.hist_file)
152 base,ext = os.path.splitext(self.hist_file)
@@ -148,9 +174,14 b' class HistoryAccessor(Configurable):'
148
174
149 def init_db(self):
175 def init_db(self):
150 """Connect to the database, and create tables if necessary."""
176 """Connect to the database, and create tables if necessary."""
177 if self.disabled:
178 self.db = DummyDB()
179 return
180
151 # use detect_types so that timestamps return datetime objects
181 # use detect_types so that timestamps return datetime objects
152 self.db = sqlite3.connect(self.hist_file,
182 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
153 detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
183 kwargs.update(self.connection_options)
184 self.db = sqlite3.connect(self.hist_file, **kwargs)
154 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
185 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
155 primary key autoincrement, start timestamp,
186 primary key autoincrement, start timestamp,
156 end timestamp, num_cmds integer, remark text)""")
187 end timestamp, num_cmds integer, remark text)""")
@@ -402,7 +433,7 b' class HistoryManager(HistoryAccessor):'
402 self.save_flag = threading.Event()
433 self.save_flag = threading.Event()
403 self.db_input_cache_lock = threading.Lock()
434 self.db_input_cache_lock = threading.Lock()
404 self.db_output_cache_lock = threading.Lock()
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 self.save_thread = HistorySavingThread(self)
437 self.save_thread = HistorySavingThread(self)
407 self.save_thread.start()
438 self.save_thread.start()
408
439
@@ -638,16 +669,20 b' class HistorySavingThread(threading.Thread):'
638 the cache size reaches a defined threshold."""
669 the cache size reaches a defined threshold."""
639 daemon = True
670 daemon = True
640 stop_now = False
671 stop_now = False
672 disabled = False
641 def __init__(self, history_manager):
673 def __init__(self, history_manager):
642 super(HistorySavingThread, self).__init__()
674 super(HistorySavingThread, self).__init__()
643 self.history_manager = history_manager
675 self.history_manager = history_manager
676 self.disabled = history_manager.disabled
644 atexit.register(self.stop)
677 atexit.register(self.stop)
645
678
646 @needs_sqlite
679 @needs_sqlite
647 def run(self):
680 def run(self):
648 # We need a separate db connection per thread:
681 # We need a separate db connection per thread:
649 try:
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 while True:
686 while True:
652 self.history_manager.save_flag.wait()
687 self.history_manager.save_flag.wait()
653 if self.stop_now:
688 if self.stop_now:
General Comments 0
You need to be logged in to leave comments. Login now