def replay(self, merge_envs=DEFAULT_MERGE_ENVS, target=None): """Replays the history specified, returns the history object where the code was executed. Parameters ---------- merge_env : tuple of str or Mappings, optional Describes how to merge the environments, in order of increasing precednce. Available strings are 'replay' and 'native'. The 'replay' env comes from the history file that we are replaying. The 'native' env comes from what this instance of xonsh was started up with. Instead of a string, a dict or other mapping may be passed in as well. Defaults to ('replay', 'native'). target : str, optional Path to new history file. """ shell = builtins.__xonsh_shell__ re_env = self._lj['env'].load() new_env = self._merge_envs(merge_envs, re_env) new_hist = History(env=new_env.detype(), locked=True, ts=[time.time(), None], gc=False, filename=target) with swap(builtins, '__xonsh_env__', new_env), \ swap(builtins, '__xonsh_history__', new_hist): for cmd in self._lj['cmds']: inp = cmd['inp'] shell.default(inp) if builtins.__xonsh_exit__: # prevent premature exit builtins.__xonsh_exit__ = False new_hist.flush(at_exit=True) return new_hist
def test_hist_append(): FNAME = 'xonsh-SESSIONID.json' FNAME += '.append' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) hf = hist.append({'joco': 'still alive'}) yield assert_true, hf is None yield assert_equal, 'still alive', hist.buffer[0]['joco'] os.remove(FNAME)
def test_hist_append(): """Verify appending to the history works.""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.append' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) hf = hist.append({'joco': 'still alive'}) yield assert_is_none, hf yield assert_equal, 'still alive', hist.buffer[0]['joco'] os.remove(FNAME)
def test_hist_append(xonsh_builtins): """Verify appending to the history works.""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.append' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set() hf = hist.append({'joco': 'still alive'}) assert hf is None assert 'still alive' == hist.buffer[0]['joco'] os.remove(FNAME)
def test_hist_flush(): FNAME = 'xonsh-SESSIONID.json' FNAME += '.flush' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) hf = hist.flush() yield assert_true, hf is None hist.append({'joco': 'still alive'}) hf = hist.flush() yield assert_true, hf is not None while hf.is_alive(): pass with LazyJSON(FNAME) as lj: obs = lj['cmds'][0]['joco'] yield assert_equal, 'still alive', obs os.remove(FNAME)
def hist(): h = History(filename='xonsh-HISTORY-TEST.json', here='yup', sessionid='SESSIONID', gc=False) yield h os.remove(h.filename)
def test_hist_flush(): """Verify explicit flushing of the history works.""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.flush' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) hf = hist.flush() yield assert_is_none, hf hist.append({'joco': 'still alive'}) hf = hist.flush() yield assert_is_not_none, hf while hf.is_alive(): pass with LazyJSON(FNAME) as lj: obs = lj['cmds'][0]['joco'] yield assert_equal, 'still alive', obs os.remove(FNAME)
def load_builtins(execer=None, config=None, login=False, ctx=None): """Loads the xonsh builtins into the Python builtins. Sets the BUILTINS_LOADED variable to True. """ global BUILTINS_LOADED # private built-ins builtins.__xonsh_config__ = {} builtins.__xonsh_env__ = env = Env(default_env(config=config, login=login)) builtins.__xonsh_help__ = helper builtins.__xonsh_superhelp__ = superhelper builtins.__xonsh_pathsearch__ = pathsearch builtins.__xonsh_globsearch__ = globsearch builtins.__xonsh_regexsearch__ = regexsearch builtins.__xonsh_glob__ = globpath builtins.__xonsh_expand_path__ = expand_path builtins.__xonsh_exit__ = False builtins.__xonsh_stdout_uncaptured__ = None builtins.__xonsh_stderr_uncaptured__ = None if hasattr(builtins, 'exit'): builtins.__xonsh_pyexit__ = builtins.exit del builtins.exit if hasattr(builtins, 'quit'): builtins.__xonsh_pyquit__ = builtins.quit del builtins.quit builtins.__xonsh_subproc_captured_stdout__ = subproc_captured_stdout builtins.__xonsh_subproc_captured_inject__ = subproc_captured_inject builtins.__xonsh_subproc_captured_object__ = subproc_captured_object builtins.__xonsh_subproc_captured_hiddenobject__ = subproc_captured_hiddenobject builtins.__xonsh_subproc_uncaptured__ = subproc_uncaptured builtins.__xonsh_execer__ = execer builtins.__xonsh_commands_cache__ = CommandsCache() builtins.__xonsh_all_jobs__ = {} builtins.__xonsh_ensure_list_of_strs__ = ensure_list_of_strs builtins.__xonsh_list_of_strs_or_callables__ = list_of_strs_or_callables builtins.__xonsh_completers__ = xonsh.completers.init.default_completers() builtins.__xonsh_call_macro__ = call_macro builtins.__xonsh_enter_macro__ = enter_macro # public built-ins builtins.XonshError = XonshError builtins.XonshBlockError = XonshBlockError builtins.XonshCalledProcessError = XonshCalledProcessError builtins.evalx = None if execer is None else execer.eval builtins.execx = None if execer is None else execer.exec builtins.compilex = None if execer is None else execer.compile builtins.events = events # sneak the path search functions into the aliases # Need this inline/lazy import here since we use locate_binary that relies on __xonsh_env__ in default aliases builtins.default_aliases = builtins.aliases = Aliases(make_default_aliases()) if login: builtins.aliases.update(load_foreign_aliases(issue_warning=False)) # history needs to be started after env and aliases # would be nice to actually include non-detyped versions. builtins.__xonsh_history__ = History(env=env.detype(), ts=[time.time(), None], locked=True) atexit.register(_lastflush) for sig in AT_EXIT_SIGNALS: resetting_signal_handle(sig, _lastflush) BUILTINS_LOADED = True
def test_hist_init(): FNAME = 'xonsh-SESSIONID.json' FNAME += '.init' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) with LazyJSON(FNAME) as lj: obs = lj['here'] assert_equal('yup', obs) os.remove(FNAME)
def test_hist_flush(xonsh_builtins): """Verify explicit flushing of the history works.""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.flush' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) hf = hist.flush() assert hf is None xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set() hist.append({'joco': 'still alive'}) hf = hist.flush() assert hf is not None while hf.is_alive(): pass with LazyJSON(FNAME) as lj: obs = lj['cmds'][0]['joco'] assert 'still alive' == obs os.remove(FNAME)
def test_hist_init(): """Test initialization of the shell history.""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.init' History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) with LazyJSON(FNAME) as lj: obs = lj['here'] assert_equal('yup', obs) os.remove(FNAME)
def test_cmd_field(): FNAME = 'xonsh-SESSIONID.json' FNAME += '.cmdfield' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) # in-memory hf = hist.append({'rtn': 1}) yield assert_true, hf is None yield assert_equal, 1, hist.rtns[0] yield assert_equal, 1, hist.rtns[-1] yield assert_equal, None, hist.outs[-1] # slice yield assert_equal, [1], hist.rtns[:] # on disk hf = hist.flush() yield assert_true, hf is not None yield assert_equal, 1, hist.rtns[0] yield assert_equal, 1, hist.rtns[-1] yield assert_equal, None, hist.outs[-1] os.remove(FNAME)
def test_cmd_field(): """Test basic history behavior.""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.cmdfield' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) # in-memory with mock_xonsh_env({'HISTCONTROL': set()}): hf = hist.append({'rtn': 1}) yield assert_is_none, hf yield assert_equal, 1, hist.rtns[0] yield assert_equal, 1, hist.rtns[-1] yield assert_equal, None, hist.outs[-1] # slice yield assert_equal, [1], hist.rtns[:] # on disk hf = hist.flush() yield assert_is_not_none, hf yield assert_equal, 1, hist.rtns[0] yield assert_equal, 1, hist.rtns[-1] yield assert_equal, None, hist.outs[-1] os.remove(FNAME)
def test_cmd_field(xonsh_builtins): """Test basic history behavior.""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.cmdfield' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) # in-memory xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set() hf = hist.append({'rtn': 1}) assert hf is None assert 1 == hist.rtns[0] assert 1 == hist.rtns[-1] assert None == hist.outs[-1] # slice assert [1] == hist.rtns[:] # on disk hf = hist.flush() assert hf is not None assert 1 == hist.rtns[0] assert 1 == hist.rtns[-1] assert None == hist.outs[-1] os.remove(FNAME)
def load_builtins(execer=None, config=None): """Loads the xonsh builtins into the Python builtins. Sets the BUILTINS_LOADED variable to True. """ global BUILTINS_LOADED, ENV # private built-ins builtins.__xonsh_env__ = ENV = Env(default_env(config=config)) builtins.__xonsh_ctx__ = {} builtins.__xonsh_help__ = helper builtins.__xonsh_superhelp__ = superhelper builtins.__xonsh_regexpath__ = regexpath builtins.__xonsh_glob__ = globpath builtins.__xonsh_expand_path__ = expand_path builtins.__xonsh_exit__ = False builtins.__xonsh_stdout_uncaptured__ = None builtins.__xonsh_stderr_uncaptured__ = None if hasattr(builtins, 'exit'): builtins.__xonsh_pyexit__ = builtins.exit del builtins.exit if hasattr(builtins, 'quit'): builtins.__xonsh_pyquit__ = builtins.quit del builtins.quit builtins.__xonsh_subproc_captured__ = subproc_captured builtins.__xonsh_subproc_uncaptured__ = subproc_uncaptured builtins.__xonsh_execer__ = execer builtins.__xonsh_all_jobs__ = {} builtins.__xonsh_active_job__ = None builtins.__xonsh_ensure_list_of_strs__ = ensure_list_of_strs # public built-ins builtins.evalx = None if execer is None else execer.eval builtins.execx = None if execer is None else execer.exec builtins.compilex = None if execer is None else execer.compile builtins.default_aliases = builtins.aliases = Aliases(DEFAULT_ALIASES) builtins.aliases.update(load_foreign_aliases(issue_warning=False)) # history needs to be started after env and aliases # would be nice to actually include non-detyped versions. builtins.__xonsh_history__ = History( env=ENV.detype(), #aliases=builtins.aliases, ts=[time.time(), None], locked=True) lastflush = lambda s=None, f=None: builtins.__xonsh_history__.flush(at_exit =True) atexit.register(lastflush) for sig in AT_EXIT_SIGNALS: resetting_signal_handle(sig, lastflush) BUILTINS_LOADED = True
def test_show_cmd(): FNAME = 'xonsh-SESSIONID.json' FNAME += '.show_cmd' cmds = ['ls', 'cat hello kitty', 'abc', 'def', 'touch me', 'grep from me'] def format_hist_line(idx, cmd): return ' {:d} {:s}\n'.format(idx, cmd) def run_show_cmd(hist_args, commands, base_idx=0, step=1): stdout.seek(0, io.SEEK_SET) stdout.truncate() history._main(hist, hist_args) # pylint: disable=protected-access stdout.seek(0, io.SEEK_SET) hist_lines = stdout.readlines() yield assert_equal, len(commands), len(hist_lines) for idx, (cmd, actual) in enumerate(zip(commands, hist_lines)): expected = format_hist_line(base_idx + idx * step, cmd) yield assert_equal, expected, actual hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) stdout = io.StringIO() saved_stdout = sys.stdout sys.stdout = stdout for cmd in cmds: # populate the shell history hist.append({'inp': cmd, 'rtn': 0}) # Verify an implicit "show" emits the entire history. for x in run_show_cmd([], cmds): yield x # Verify an explicit "show" with no qualifiers emits the entire history. for x in run_show_cmd(['show'], cmds): yield x # Verify an explicit "show" with a reversed qualifier emits the entire # history in reverse order. for x in run_show_cmd(['show', '-r'], list(reversed(cmds)), len(cmds) - 1, -1): yield x # Verify that showing a specific history entry relative to the start of the # history works. for x in run_show_cmd(['show', '0'], [cmds[0]], 0): yield x for x in run_show_cmd(['show', '1'], [cmds[1]], 1): yield x # Verify that showing a specific history entry relative to the end of the # history works. for x in run_show_cmd(['show', '-2'], [cmds[-2]], len(cmds) - 2): yield x # Verify that showing a history range relative to the start of the # history works. for x in run_show_cmd(['show', '0:2'], cmds[0:2], 0): yield x for x in run_show_cmd(['show', '1::2'], cmds[1::2], 1, 2): yield x # Verify that showing a history range relative to the end of the # history works. for x in run_show_cmd(['show', '-2:'], cmds[-2:], len(cmds) - 2): yield x for x in run_show_cmd(['show', '-4:-2'], cmds[-4:-2], len(cmds) - 4): yield x sys.stdout = saved_stdout os.remove(FNAME)
def test_histcontrol(xonsh_builtins): """Test HISTCONTROL=ignoredups,ignoreerr""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.append' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) xonsh_builtins.__xonsh_env__['HISTCONTROL'] = 'ignoredups,ignoreerr' assert len(hist.buffer) == 0 # An error, buffer remains empty hist.append({'inp': 'ls foo', 'rtn': 2}) assert len(hist.buffer) == 0 # Success hist.append({'inp': 'ls foobazz', 'rtn': 0}) assert len(hist.buffer) == 1 assert 'ls foobazz' == hist.buffer[-1]['inp'] assert 0 == hist.buffer[-1]['rtn'] # Error hist.append({'inp': 'ls foo', 'rtn': 2}) assert len(hist.buffer) == 1 assert 'ls foobazz' == hist.buffer[-1]['inp'] assert 0 == hist.buffer[-1]['rtn'] # File now exists, success hist.append({'inp': 'ls foo', 'rtn': 0}) assert len(hist.buffer) == 2 assert 'ls foo' == hist.buffer[-1]['inp'] assert 0 == hist.buffer[-1]['rtn'] # Success hist.append({'inp': 'ls', 'rtn': 0}) assert len(hist.buffer) == 3 assert 'ls' == hist.buffer[-1]['inp'] assert 0 == hist.buffer[-1]['rtn'] # Dup hist.append({'inp': 'ls', 'rtn': 0}) assert len(hist.buffer) == 3 # Success hist.append({'inp': '/bin/ls', 'rtn': 0}) assert len(hist.buffer) == 4 assert '/bin/ls' == hist.buffer[-1]['inp'] assert 0 == hist.buffer[-1]['rtn'] # Error hist.append({'inp': 'ls bazz', 'rtn': 1}) assert len(hist.buffer) == 4 assert '/bin/ls' == hist.buffer[-1]['inp'] assert 0 == hist.buffer[-1]['rtn'] # Error hist.append({'inp': 'ls bazz', 'rtn': -1}) assert len(hist.buffer) == 4 assert '/bin/ls' == hist.buffer[-1]['inp'] assert 0 == hist.buffer[-1]['rtn'] os.remove(FNAME)
def test_show_cmd(xonsh_builtins): """Verify that CLI history commands work.""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.show_cmd' cmds = ['ls', 'cat hello kitty', 'abc', 'def', 'touch me', 'grep from me'] def format_hist_line(idx, cmd): """Construct a history output line.""" return ' {:d}: {:s}\n'.format(idx, cmd) def run_show_cmd(hist_args, commands, base_idx=0, step=1): """Run and evaluate the output of the given show command.""" stdout.seek(0, io.SEEK_SET) stdout.truncate() history._hist_main(hist, hist_args) stdout.seek(0, io.SEEK_SET) hist_lines = stdout.readlines() assert len(commands) == len(hist_lines) for idx, (cmd, actual) in enumerate(zip(commands, hist_lines)): expected = format_hist_line(base_idx + idx * step, cmd) assert expected == actual hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) stdout = io.StringIO() saved_stdout = sys.stdout sys.stdout = stdout xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set() for ts,cmd in enumerate(cmds): # populate the shell history hist.append({'inp': cmd, 'rtn': 0, 'ts':(ts+1, ts+1.5)}) # Verify an implicit "show" emits show history run_show_cmd([], cmds) # Verify an explicit "show" with no qualifiers emits # show history. run_show_cmd(['show'], cmds) # Verify an explicit "show" with a reversed qualifier # emits show history in reverse order. run_show_cmd(['show', '-r'], list(reversed(cmds)), len(cmds) - 1, -1) # Verify that showing a specific history entry relative to # the start of the history works. run_show_cmd(['show', '0'], [cmds[0]], 0) run_show_cmd(['show', '1'], [cmds[1]], 1) # Verify that showing a specific history entry relative to # the end of the history works. run_show_cmd(['show', '-2'], [cmds[-2]], len(cmds) - 2) # Verify that showing a history range relative to the start of the # history works. run_show_cmd(['show', '0:2'], cmds[0:2], 0) run_show_cmd(['show', '1::2'], cmds[1::2], 1, 2) # Verify that showing a history range relative to the end of the # history works. run_show_cmd(['show', '-2:'], cmds[-2:], len(cmds) - 2) run_show_cmd(['show', '-4:-2'], cmds[-4:-2], len(cmds) - 4) sys.stdout = saved_stdout os.remove(FNAME)
def test_show_cmd(): """Verify that CLI history commands work.""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.show_cmd' cmds = ['ls', 'cat hello kitty', 'abc', 'def', 'touch me', 'grep from me'] def format_hist_line(idx, cmd): """Construct a history output line.""" return ' {:d}: {:s}\n'.format(idx, cmd) def run_show_cmd(hist_args, commands, base_idx=0, step=1): """Run and evaluate the output of the given show command.""" stdout.seek(0, io.SEEK_SET) stdout.truncate() history._hist_main(hist, hist_args) stdout.seek(0, io.SEEK_SET) hist_lines = stdout.readlines() yield assert_equal, len(commands), len(hist_lines) for idx, (cmd, actual) in enumerate(zip(commands, hist_lines)): expected = format_hist_line(base_idx + idx * step, cmd) yield assert_equal, expected, actual hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) stdout = io.StringIO() saved_stdout = sys.stdout sys.stdout = stdout with mock_xonsh_env({'HISTCONTROL': set()}): for ts,cmd in enumerate(cmds): # populate the shell history hist.append({'inp': cmd, 'rtn': 0, 'ts':(ts+1, ts+1.5)}) # Verify an implicit "show" emits show history for x in run_show_cmd([], cmds): yield x # Verify an explicit "show" with no qualifiers emits # show history. for x in run_show_cmd(['show'], cmds): yield x # Verify an explicit "show" with a reversed qualifier # emits show history in reverse order. for x in run_show_cmd(['show', '-r'], list(reversed(cmds)), len(cmds) - 1, -1): yield x # Verify that showing a specific history entry relative to # the start of the history works. for x in run_show_cmd(['show', '0'], [cmds[0]], 0): yield x for x in run_show_cmd(['show', '1'], [cmds[1]], 1): yield x # Verify that showing a specific history entry relative to # the end of the history works. for x in run_show_cmd(['show', '-2'], [cmds[-2]], len(cmds) - 2): yield x # Verify that showing a history range relative to the start of the # history works. for x in run_show_cmd(['show', '0:2'], cmds[0:2], 0): yield x for x in run_show_cmd(['show', '1::2'], cmds[1::2], 1, 2): yield x # Verify that showing a history range relative to the end of the # history works. for x in run_show_cmd(['show', '-2:'], cmds[-2:], len(cmds) - 2): yield x for x in run_show_cmd(['show', '-4:-2'], cmds[-4:-2], len(cmds) - 4): yield x sys.stdout = saved_stdout os.remove(FNAME)
def test_histcontrol(): """Test HISTCONTROL=ignoredups,ignoreerr""" FNAME = 'xonsh-SESSIONID.json' FNAME += '.append' hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS) with mock_xonsh_env({'HISTCONTROL': 'ignoredups,ignoreerr'}): yield assert_equal, len(hist.buffer), 0 # An error, buffer remains empty hist.append({'inp': 'ls foo', 'rtn': 2}) yield assert_equal, len(hist.buffer), 0 # Success hist.append({'inp': 'ls foobazz', 'rtn': 0}) yield assert_equal, len(hist.buffer), 1 yield assert_equal, 'ls foobazz', hist.buffer[-1]['inp'] yield assert_equal, 0, hist.buffer[-1]['rtn'] # Error hist.append({'inp': 'ls foo', 'rtn': 2}) yield assert_equal, len(hist.buffer), 1 yield assert_equal, 'ls foobazz', hist.buffer[-1]['inp'] yield assert_equal, 0, hist.buffer[-1]['rtn'] # File now exists, success hist.append({'inp': 'ls foo', 'rtn': 0}) yield assert_equal, len(hist.buffer), 2 yield assert_equal, 'ls foo', hist.buffer[-1]['inp'] yield assert_equal, 0, hist.buffer[-1]['rtn'] # Success hist.append({'inp': 'ls', 'rtn': 0}) yield assert_equal, len(hist.buffer), 3 yield assert_equal, 'ls', hist.buffer[-1]['inp'] yield assert_equal, 0, hist.buffer[-1]['rtn'] # Dup hist.append({'inp': 'ls', 'rtn': 0}) yield assert_equal, len(hist.buffer), 3 # Success hist.append({'inp': '/bin/ls', 'rtn': 0}) yield assert_equal, len(hist.buffer), 4 yield assert_equal, '/bin/ls', hist.buffer[-1]['inp'] yield assert_equal, 0, hist.buffer[-1]['rtn'] # Error hist.append({'inp': 'ls bazz', 'rtn': 1}) yield assert_equal, len(hist.buffer), 4 yield assert_equal, '/bin/ls', hist.buffer[-1]['inp'] yield assert_equal, 0, hist.buffer[-1]['rtn'] # Error hist.append({'inp': 'ls bazz', 'rtn': -1}) yield assert_equal, len(hist.buffer), 4 yield assert_equal, '/bin/ls', hist.buffer[-1]['inp'] yield assert_equal, 0, hist.buffer[-1]['rtn'] os.remove(FNAME)