Show More
@@ -19,7 +19,6 b' from traitlets import (' | |||||
19 | Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError, |
|
19 | Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError, | |
20 | default, observe, |
|
20 | default, observe, | |
21 | ) |
|
21 | ) | |
22 | from warnings import warn |
|
|||
23 |
|
22 | |||
24 | #----------------------------------------------------------------------------- |
|
23 | #----------------------------------------------------------------------------- | |
25 | # Classes and functions |
|
24 | # Classes and functions | |
@@ -43,8 +42,14 b' class DummyDB(object):' | |||||
43 | pass |
|
42 | pass | |
44 |
|
43 | |||
45 |
|
44 | |||
46 | DatabaseError = sqlite3.DatabaseError |
|
45 | @decorator | |
47 | OperationalError = sqlite3.OperationalError |
|
46 | def needs_sqlite(f, self, *a, **kw): | |
|
47 | """Decorator: return an empty list in the absence of sqlite.""" | |||
|
48 | if not self.enabled: | |||
|
49 | return [] | |||
|
50 | else: | |||
|
51 | return f(self, *a, **kw) | |||
|
52 | ||||
48 |
|
53 | |||
49 | # use 16kB as threshold for whether a corrupt history db should be saved |
|
54 | # use 16kB as threshold for whether a corrupt history db should be saved | |
50 | # that should be at least 100 entries or so |
|
55 | # that should be at least 100 entries or so | |
@@ -61,7 +66,7 b' def catch_corrupt_db(f, self, *a, **kw):' | |||||
61 | """ |
|
66 | """ | |
62 | try: |
|
67 | try: | |
63 | return f(self, *a, **kw) |
|
68 | return f(self, *a, **kw) | |
64 | except (DatabaseError, OperationalError) as e: |
|
69 | except (sqlite3.DatabaseError, sqlite3.OperationalError) as e: | |
65 | self._corrupt_db_counter += 1 |
|
70 | self._corrupt_db_counter += 1 | |
66 | self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e) |
|
71 | self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e) | |
67 | if self.hist_file != ':memory:': |
|
72 | if self.hist_file != ':memory:': | |
@@ -165,9 +170,7 b' class HistoryAccessor(HistoryAccessorBase):' | |||||
165 | def _db_changed(self, change): |
|
170 | def _db_changed(self, change): | |
166 | """validate the db, since it can be an Instance of two different types""" |
|
171 | """validate the db, since it can be an Instance of two different types""" | |
167 | new = change['new'] |
|
172 | new = change['new'] | |
168 | connection_types = (DummyDB,) |
|
173 | connection_types = (DummyDB, sqlite3.Connection) | |
169 | if sqlite3 is not None: |
|
|||
170 | connection_types = (DummyDB, sqlite3.Connection) |
|
|||
171 | if not isinstance(new, connection_types): |
|
174 | if not isinstance(new, connection_types): | |
172 | msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \ |
|
175 | msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \ | |
173 | (self.__class__.__name__, new) |
|
176 | (self.__class__.__name__, new) | |
@@ -197,10 +200,6 b' class HistoryAccessor(HistoryAccessorBase):' | |||||
197 | if self.hist_file == u'': |
|
200 | if self.hist_file == u'': | |
198 | # No one has set the hist_file, yet. |
|
201 | # No one has set the hist_file, yet. | |
199 | self.hist_file = self._get_hist_file_name(profile) |
|
202 | self.hist_file = self._get_hist_file_name(profile) | |
200 |
|
||||
201 | if sqlite3 is None and self.enabled: |
|
|||
202 | warn("IPython History requires SQLite, your history will not be saved") |
|
|||
203 | self.enabled = False |
|
|||
204 |
|
203 | |||
205 | self.init_db() |
|
204 | self.init_db() | |
206 |
|
205 | |||
@@ -278,6 +277,7 b' class HistoryAccessor(HistoryAccessorBase):' | |||||
278 | return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur) |
|
277 | return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur) | |
279 | return cur |
|
278 | return cur | |
280 |
|
279 | |||
|
280 | @needs_sqlite | |||
281 | @catch_corrupt_db |
|
281 | @catch_corrupt_db | |
282 | def get_session_info(self, session): |
|
282 | def get_session_info(self, session): | |
283 | """Get info about a session. |
|
283 | """Get info about a session. | |
@@ -516,7 +516,7 b' class HistoryManager(HistoryAccessor):' | |||||
516 |
|
516 | |||
517 | try: |
|
517 | try: | |
518 | self.new_session() |
|
518 | self.new_session() | |
519 | except OperationalError: |
|
519 | except sqlite3.OperationalError: | |
520 | self.log.error("Failed to create history session in %s. History will not be saved.", |
|
520 | self.log.error("Failed to create history session in %s. History will not be saved.", | |
521 | self.hist_file, exc_info=True) |
|
521 | self.hist_file, exc_info=True) | |
522 | self.hist_file = ':memory:' |
|
522 | self.hist_file = ':memory:' | |
@@ -533,6 +533,7 b' class HistoryManager(HistoryAccessor):' | |||||
533 | profile_dir = self.shell.profile_dir.location |
|
533 | profile_dir = self.shell.profile_dir.location | |
534 | return os.path.join(profile_dir, 'history.sqlite') |
|
534 | return os.path.join(profile_dir, 'history.sqlite') | |
535 |
|
535 | |||
|
536 | @needs_sqlite | |||
536 | def new_session(self, conn=None): |
|
537 | def new_session(self, conn=None): | |
537 | """Get a new session number.""" |
|
538 | """Get a new session number.""" | |
538 | if conn is None: |
|
539 | if conn is None: | |
@@ -743,6 +744,7 b' class HistoryManager(HistoryAccessor):' | |||||
743 | conn.execute("INSERT INTO output_history VALUES (?, ?, ?)", |
|
744 | conn.execute("INSERT INTO output_history VALUES (?, ?, ?)", | |
744 | (self.session_number,)+line) |
|
745 | (self.session_number,)+line) | |
745 |
|
746 | |||
|
747 | @needs_sqlite | |||
746 | def writeout_cache(self, conn=None): |
|
748 | def writeout_cache(self, conn=None): | |
747 | """Write any entries in the cache to the database.""" |
|
749 | """Write any entries in the cache to the database.""" | |
748 | if conn is None: |
|
750 | if conn is None: | |
@@ -791,6 +793,7 b' class HistorySavingThread(threading.Thread):' | |||||
791 | self.enabled = history_manager.enabled |
|
793 | self.enabled = history_manager.enabled | |
792 | atexit.register(self.stop) |
|
794 | atexit.register(self.stop) | |
793 |
|
795 | |||
|
796 | @needs_sqlite | |||
794 | def run(self): |
|
797 | def run(self): | |
795 | # We need a separate db connection per thread: |
|
798 | # We need a separate db connection per thread: | |
796 | try: |
|
799 | try: |
General Comments 0
You need to be logged in to leave comments.
Login now