Show More
@@ -0,0 +1,111 b'' | |||||
|
1 | """ ZMQ Kernel History accessor and manager. """ | |||
|
2 | #----------------------------------------------------------------------------- | |||
|
3 | # Copyright (C) 2010-2011 The IPython Development Team. | |||
|
4 | # | |||
|
5 | # Distributed under the terms of the BSD License. | |||
|
6 | # | |||
|
7 | # The full license is in the file COPYING.txt, distributed with this software. | |||
|
8 | #----------------------------------------------------------------------------- | |||
|
9 | ||||
|
10 | #----------------------------------------------------------------------------- | |||
|
11 | # Imports | |||
|
12 | #----------------------------------------------------------------------------- | |||
|
13 | ||||
|
14 | from IPython.core.history import HistoryAccessorBase | |||
|
15 | from IPython.utils import py3compat | |||
|
16 | from IPython.utils.traitlets import Dict, List | |||
|
17 | ||||
|
18 | try: | |||
|
19 | from queue import Empty # Py 3 | |||
|
20 | except ImportError: | |||
|
21 | from Queue import Empty # Py 2 | |||
|
22 | ||||
|
23 | class ZMQHistoryManager(HistoryAccessorBase): | |||
|
24 | """History accessor and manager for ZMQ-based kernels""" | |||
|
25 | input_hist_parsed = List([""]) | |||
|
26 | output_hist = Dict() | |||
|
27 | dir_hist = List() | |||
|
28 | output_hist_reprs = Dict() | |||
|
29 | ||||
|
30 | def __init__(self, client): | |||
|
31 | """ | |||
|
32 | Class to load the command-line history from a ZMQ-based kernel, | |||
|
33 | and access the history. | |||
|
34 | ||||
|
35 | Parameters | |||
|
36 | ---------- | |||
|
37 | ||||
|
38 | client: `IPython.kernel.KernelClient` | |||
|
39 | The kernel client in order to request the history. | |||
|
40 | """ | |||
|
41 | self.client = client | |||
|
42 | ||||
|
43 | def _load_history(self, raw=True, output=False, hist_access_type='range', | |||
|
44 | **kwargs): | |||
|
45 | """ | |||
|
46 | Load the history over ZMQ from the kernel. Wraps the history | |||
|
47 | messaging with loop to wait to get history results. | |||
|
48 | """ | |||
|
49 | # 'range' (fill in session, start and stop params), | |||
|
50 | # 'tail' (fill in n) | |||
|
51 | # 'search' (fill in pattern param). | |||
|
52 | msg_id = self.client.history(raw=raw, output=output, | |||
|
53 | hist_access_type=hist_access_type, | |||
|
54 | **kwargs) | |||
|
55 | history = [] | |||
|
56 | while True: | |||
|
57 | try: | |||
|
58 | reply = self.client.get_shell_msg(timeout=1) | |||
|
59 | except Empty: | |||
|
60 | break | |||
|
61 | else: | |||
|
62 | if reply['parent_header'].get('msg_id') == msg_id: | |||
|
63 | history = reply['content'].get('history', []) | |||
|
64 | break | |||
|
65 | return history | |||
|
66 | ||||
|
67 | def writeout_cache(self): | |||
|
68 | """ | |||
|
69 | Not needed for ZMQ-based histories. | |||
|
70 | """ | |||
|
71 | pass | |||
|
72 | ||||
|
73 | def get_tail(self, n=10, raw=True, output=False, include_latest=False): | |||
|
74 | return self._load_history(hist_access_type='tail', n=n, raw=raw, | |||
|
75 | output=output) | |||
|
76 | ||||
|
77 | def search(self, pattern="*", raw=True, search_raw=True, | |||
|
78 | output=False, n=None, unique=False): | |||
|
79 | return self._load_history(hist_access_type='search', pattern=pattern, | |||
|
80 | raw=raw, search_raw=search_raw, | |||
|
81 | output=output, n=n, unique=unique) | |||
|
82 | ||||
|
83 | def get_range(self, session, start=1, stop=None, raw=True,output=False): | |||
|
84 | return self._load_history(hist_access_type='range', raw=raw, | |||
|
85 | output=output, start=start, stop=stop, | |||
|
86 | session=session) | |||
|
87 | ||||
|
88 | def get_range_by_str(self, rangestr, raw=True, output=False): | |||
|
89 | return self._load_history(hist_access_type='range', raw=raw, | |||
|
90 | output=output, rangestr=rangetr) | |||
|
91 | ||||
|
92 | def end_session(self): | |||
|
93 | """ | |||
|
94 | Nothing to do for ZMQ-based histories. | |||
|
95 | """ | |||
|
96 | pass | |||
|
97 | ||||
|
98 | def reset(self, new_session=True): | |||
|
99 | """Clear the session history, releasing all object references, and | |||
|
100 | optionally open a new session.""" | |||
|
101 | self.output_hist.clear() | |||
|
102 | # The directory history can't be completely empty | |||
|
103 | self.dir_hist[:] = [py3compat.getcwd()] | |||
|
104 | ||||
|
105 | if new_session: | |||
|
106 | if self.session_number: | |||
|
107 | self.end_session() | |||
|
108 | self.input_hist_parsed[:] = [""] | |||
|
109 | self.input_hist_raw[:] = [""] | |||
|
110 | self.new_session() | |||
|
111 |
@@ -15,6 +15,7 b' from __future__ import print_function' | |||||
15 | # Stdlib imports |
|
15 | # Stdlib imports | |
16 | import atexit |
|
16 | import atexit | |
17 | import datetime |
|
17 | import datetime | |
|
18 | import abc | |||
18 | import os |
|
19 | import os | |
19 | import re |
|
20 | import re | |
20 | try: |
|
21 | try: | |
@@ -26,17 +27,13 b' except ImportError:' | |||||
26 | sqlite3 = None |
|
27 | sqlite3 = None | |
27 | import threading |
|
28 | import threading | |
28 |
|
29 | |||
29 | try: |
|
|||
30 | from queue import Empty # Py 3 |
|
|||
31 | except ImportError: |
|
|||
32 | from Queue import Empty # Py 2 |
|
|||
33 |
|
||||
34 | # Our own packages |
|
30 | # Our own packages | |
35 | from IPython.config.configurable import Configurable |
|
31 | from IPython.config.configurable import Configurable | |
36 | from IPython.external.decorator import decorator |
|
32 | from IPython.external.decorator import decorator | |
37 | from IPython.utils.decorators import undoc |
|
33 | from IPython.utils.decorators import undoc | |
38 | from IPython.utils.path import locate_profile |
|
34 | from IPython.utils.path import locate_profile | |
39 | from IPython.utils import py3compat |
|
35 | from IPython.utils import py3compat | |
|
36 | from IPython.utils.py3compat import with_metaclass | |||
40 | from IPython.utils.traitlets import ( |
|
37 | from IPython.utils.traitlets import ( | |
41 | Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError, |
|
38 | Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError, | |
42 | ) |
|
39 | ) | |
@@ -104,52 +101,23 b' def catch_corrupt_db(f, self, *a, **kw):' | |||||
104 | raise |
|
101 | raise | |
105 |
|
102 | |||
106 | class HistoryAccessorBase(Configurable): |
|
103 | class HistoryAccessorBase(Configurable): | |
107 | input_hist_parsed = List([""]) |
|
104 | """An abstract class for History Accessors """ | |
108 | input_hist_raw = List([""]) |
|
|||
109 | output_hist = Dict() |
|
|||
110 | dir_hist = List() |
|
|||
111 | output_hist_reprs = Dict() |
|
|||
112 |
|
||||
113 | def end_session(self): |
|
|||
114 | pass |
|
|||
115 |
|
||||
116 | def reset(self, new_session=True): |
|
|||
117 | """Clear the session history, releasing all object references, and |
|
|||
118 | optionally open a new session.""" |
|
|||
119 | self.output_hist.clear() |
|
|||
120 | # The directory history can't be completely empty |
|
|||
121 | self.dir_hist[:] = [py3compat.getcwd()] |
|
|||
122 |
|
||||
123 | if new_session: |
|
|||
124 | if self.session_number: |
|
|||
125 | self.end_session() |
|
|||
126 | self.input_hist_parsed[:] = [""] |
|
|||
127 | self.input_hist_raw[:] = [""] |
|
|||
128 | self.new_session() |
|
|||
129 |
|
||||
130 | def new_session(self, conn=None): |
|
|||
131 | pass |
|
|||
132 |
|
||||
133 | def writeout_cache(self): |
|
|||
134 | pass |
|
|||
135 |
|
105 | |||
|
106 | @abc.abstractmethod | |||
136 | def get_tail(self, n=10, raw=True, output=False, include_latest=False): |
|
107 | def get_tail(self, n=10, raw=True, output=False, include_latest=False): | |
137 | return [] |
|
108 | pass | |
138 |
|
109 | |||
|
110 | @abc.abstractmethod | |||
139 | def search(self, pattern="*", raw=True, search_raw=True, |
|
111 | def search(self, pattern="*", raw=True, search_raw=True, | |
140 | output=False, n=None, unique=False): |
|
112 | output=False, n=None, unique=False): | |
141 | return [] |
|
113 | pass | |
142 |
|
114 | |||
|
115 | @abc.abstractmethod | |||
143 | def get_range(self, session, start=1, stop=None, raw=True,output=False): |
|
116 | def get_range(self, session, start=1, stop=None, raw=True,output=False): | |
144 | return [] |
|
|||
145 |
|
||||
146 | def get_range_by_str(self, rangestr, raw=True, output=False): |
|
|||
147 | return [] |
|
|||
148 |
|
||||
149 | def store_inputs(self, line_num, source, source_raw=None): |
|
|||
150 | pass |
|
117 | pass | |
151 |
|
118 | |||
152 | def store_output(self, line_num): |
|
119 | @abc.abstractmethod | |
|
120 | def get_range_by_str(self, rangestr, raw=True, output=False): | |||
153 | pass |
|
121 | pass | |
154 |
|
122 | |||
155 | class HistoryAccessor(HistoryAccessorBase): |
|
123 | class HistoryAccessor(HistoryAccessorBase): | |
@@ -800,54 +768,6 b' class HistoryManager(HistoryAccessor):' | |||||
800 | finally: |
|
768 | finally: | |
801 | self.db_output_cache = [] |
|
769 | self.db_output_cache = [] | |
802 |
|
770 | |||
803 | class KernelHistoryManager(HistoryAccessorBase): |
|
|||
804 | def __init__(self, client): |
|
|||
805 | self.client = client |
|
|||
806 | self._load_history() |
|
|||
807 |
|
||||
808 | def _load_history(self): |
|
|||
809 | msg_id = self.client.history() |
|
|||
810 | while True: |
|
|||
811 | try: |
|
|||
812 | reply = self.client.get_shell_msg(timeout=1) |
|
|||
813 | except Empty: |
|
|||
814 | break |
|
|||
815 | else: |
|
|||
816 | if reply['parent_header'].get('msg_id') == msg_id: |
|
|||
817 | history = reply['content'].get('history', []) |
|
|||
818 | break |
|
|||
819 | self.history = history |
|
|||
820 | print("_load_history:", self.history) |
|
|||
821 |
|
||||
822 | def writeout_cache(self): |
|
|||
823 | """dump cache before certain database lookups.""" |
|
|||
824 | print("write_cache") |
|
|||
825 |
|
||||
826 | def get_tail(self, n=10, raw=True, output=False, include_latest=False): |
|
|||
827 | print("get_tail: ", n) |
|
|||
828 | return self.history[-n:] |
|
|||
829 |
|
||||
830 | def search(self, pattern="*", raw=True, search_raw=True, |
|
|||
831 | output=False, n=None, unique=False): |
|
|||
832 | print("search: ", pattern) |
|
|||
833 | return [] |
|
|||
834 |
|
||||
835 | def get_range(self, session, start=1, stop=None, raw=True,output=False): |
|
|||
836 | print("get_range: ", start, stop) |
|
|||
837 | if stop is None: |
|
|||
838 | stop = -1 |
|
|||
839 | return self.history[start:stop] |
|
|||
840 |
|
||||
841 | def get_range_by_str(self, rangestr, raw=True, output=False): |
|
|||
842 | print("get_range_by_str: " + rangestr) |
|
|||
843 | return [] |
|
|||
844 |
|
||||
845 | def store_inputs(self, line_num, source, source_raw=None): |
|
|||
846 | print("store_inputs") |
|
|||
847 |
|
||||
848 | def store_output(self, line_num): |
|
|||
849 | print("store_output") |
|
|||
850 |
|
||||
851 |
|
771 | |||
852 | class HistorySavingThread(threading.Thread): |
|
772 | class HistorySavingThread(threading.Thread): | |
853 | """This thread takes care of writing history to the database, so that |
|
773 | """This thread takes care of writing history to the database, so that |
@@ -23,7 +23,7 b' except ImportError:' | |||||
23 |
|
23 | |||
24 | from IPython.core import page |
|
24 | from IPython.core import page | |
25 | from IPython.core import release |
|
25 | from IPython.core import release | |
26 |
from IPython. |
|
26 | from IPython.terminal.console.zmqhistory import ZMQHistoryManager | |
27 | from IPython.utils.warn import warn, error |
|
27 | from IPython.utils.warn import warn, error | |
28 | from IPython.utils import io |
|
28 | from IPython.utils import io | |
29 | from IPython.utils.py3compat import string_types, input |
|
29 | from IPython.utils.py3compat import string_types, input | |
@@ -573,6 +573,6 b' class ZMQTerminalInteractiveShell(TerminalInteractiveShell):' | |||||
573 |
|
573 | |||
574 | def init_history(self): |
|
574 | def init_history(self): | |
575 | """Sets up the command history. """ |
|
575 | """Sets up the command history. """ | |
576 |
self.history_manager = |
|
576 | self.history_manager = ZMQHistoryManager(client=self.client) | |
577 | self.configurables.append(self.history_manager) |
|
577 | self.configurables.append(self.history_manager) | |
578 |
|
578 |
General Comments 0
You need to be logged in to leave comments.
Login now