Hello community, here is the log from the commit of package xonsh for openSUSE:Factory checked in at 2020-04-07 10:28:37 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/xonsh (Old) and /work/SRC/openSUSE:Factory/.xonsh.new.3248 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "xonsh" Tue Apr 7 10:28:37 2020 rev:21 rq:791562 version:0.9.15 Changes: -------- --- /work/SRC/openSUSE:Factory/xonsh/xonsh.changes 2020-03-07 21:41:24.984400893 +0100 +++ /work/SRC/openSUSE:Factory/.xonsh.new.3248/xonsh.changes 2020-04-07 10:28:48.334328429 +0200 @@ -1,0 +2,26 @@ +Sun Mar 29 19:01:45 UTC 2020 - Sebastian Wagner <sebix+novell....@sebix.at> + +- update to version 0.9.15: + - Added: + - Adds documentation for how to setup an emacs editing mode for xonsh. + - New ``$XONSH_TRACE_SUBPROC`` environment variable. + - Added ``-l``, ``-c`` and ``-a`` options to ``xexec``, works now like ``exec`` + in bash/zsh + - **$HISTCONTROL** - *errordups* support for history-sqlite backend + - Changed: + - ``-l`` switch works like bash, loads environment in non-interactive shell + - The xonsh pytest plugin no longer messes up the test order for pytest. Xsh test + are still executed first to avoid a bug were other tests would prevent ``test_*.xsh`` + files to run correctly. + - New repo name for xxh + - Fixed: + - Correctly follow symlinks when using dot-dot paths with cd -P. + - ``execx`` does not require the input string to be newline-terminated. + - ``evalx`` accepts newline-terminated input string. + - Fixed issue where negative exit codes (such as those produced + by core dumps) where treated as logical successes when chaining + processes with other boolean expressions. + - Fixed XONSH_TRACE_SUBPROC for pipeline command. + - updated CONTRIBUTING.rst about running pylint for changed files + +------------------------------------------------------------------- Old: ---- xonsh-0.9.14.tar.gz New: ---- xonsh-0.9.15.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ xonsh.spec ++++++ --- /var/tmp/diff_new_pack.nfE4xF/_old 2020-04-07 10:28:48.854329007 +0200 +++ /var/tmp/diff_new_pack.nfE4xF/_new 2020-04-07 10:28:48.858329012 +0200 @@ -17,7 +17,7 @@ Name: xonsh -Version: 0.9.14 +Version: 0.9.15 Release: 0 Summary: A general purpose, Python-ish shell License: BSD-3-Clause AND BSD-2-Clause ++++++ xonsh-0.9.14.tar.gz -> xonsh-0.9.15.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/.appveyor.yml new/xonsh-0.9.15/.appveyor.yml --- old/xonsh-0.9.14/.appveyor.yml 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/.appveyor.yml 2020-03-19 21:38:46.000000000 +0100 @@ -1,4 +1,4 @@ -version: 0.9.14.{build} +version: 0.9.15.{build} os: Windows Server 2012 R2 environment: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/.authors.yml new/xonsh-0.9.15/.authors.yml --- old/xonsh-0.9.14/.authors.yml 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/.authors.yml 2020-03-19 21:38:46.000000000 +0100 @@ -68,7 +68,7 @@ github: gforsyth - name: Morten Enemark Lund email: mel...@gmail.com - num_commits: 486 + num_commits: 490 first_commit: 2015-07-10 07:54:10 github: melund - name: Ned Letcher @@ -384,7 +384,7 @@ email: laloc...@gmail.com aliases: - laloch - num_commits: 43 + num_commits: 47 first_commit: 2018-07-26 13:51:50 github: laloch - name: Nico Lehmann @@ -434,7 +434,7 @@ github: funkyfuture - name: Anthony Scopatz email: scop...@gmail.com - num_commits: 2587 + num_commits: 2593 first_commit: 2015-01-21 17:04:13 github: scopatz - name: anatoly techtonik @@ -1016,7 +1016,7 @@ first_commit: 2018-09-16 22:50:24 - name: Gyuri Horak email: dy...@horak.hu - num_commits: 1 + num_commits: 2 first_commit: 2019-06-18 12:00:16 github: dyuri - name: Ke Zhang @@ -1092,12 +1092,14 @@ email: drmikecr...@gmail.com aliases: - drmikecrowe - num_commits: 1 + num_commits: 6 first_commit: 2020-01-28 09:44:58 github: drmikecrowe - name: anki-code email: anki-c...@users.noreply.github.com - num_commits: 14 + alternate_emails: + - anki-code + num_commits: 21 first_commit: 2019-10-15 18:20:58 - name: Sylvain Corlay email: sylvain.cor...@gmail.com @@ -1118,3 +1120,26 @@ num_commits: 1 first_commit: 2020-02-05 13:38:52 github: marciomazza +- name: Noortheen Raja + email: jnoorth...@gmail.com + num_commits: 2 + first_commit: 2020-03-15 10:13:56 + github: jnoortheen +- name: Samuel Lotz + email: samuel.l...@salotz.info + num_commits: 3 + first_commit: 2020-03-03 11:30:33 + github: salotz +- name: Jerzy Drozdz + email: jerzy.dro...@gmail.com + num_commits: 1 + first_commit: 2020-03-01 11:56:23 +- name: Gabriel Vogel + email: gabriel.vo...@online.de + num_commits: 2 + first_commit: 2020-03-10 19:06:59 + github: Gobbel2000 +- name: anki + email: anki@code.email + num_commits: 2 + first_commit: 2020-03-02 04:59:17 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/.gitignore new/xonsh-0.9.15/.gitignore --- old/xonsh-0.9.14/.gitignore 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/.gitignore 2020-03-19 21:38:46.000000000 +0100 @@ -36,6 +36,7 @@ bin/ /lib/ include/ +venv/ # Mac .DS_Store diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/.mailmap new/xonsh-0.9.15/.mailmap --- old/xonsh-0.9.14/.mailmap 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/.mailmap 2020-03-19 21:38:46.000000000 +0100 @@ -27,8 +27,8 @@ Jean-Benoist Leger <j...@leger.tf> Jean-Benoist Leger <jble...@hds.utc.fr> christopher <cjwright4...@gmail.com> Klaus Alexander Seistrup <kl...@seistrup.dk> Klaus Alexander Seistrup <kseist...@users.noreply.github.com> -Leonardo Santagada <santag...@gmail.com> David Strobach <laloc...@gmail.com> laloch <laloc...@gmail.com> +Leonardo Santagada <santag...@gmail.com> Burak Yiğit Kaya <b...@byk.im> Burak Yigit Kaya <b...@byk.im> Aaron Griffin <aig...@gmail.com> Rob Brewer <rwb...@gmail.com> Robert W. Brewer <rwb...@gmail.com> @@ -40,6 +40,7 @@ Gordon Ball <gor...@chronitis.net> Travis Shirk <tra...@pobox.com> Joel Gerber <j...@grrbrr.ca> +anki-code <anki-c...@users.noreply.github.com> anki-code <anki-code> vaaaaanquish <6sy...@gmail.com> @vaaaaanquish <6sy...@gmail.com> vaaaaanquish <6sy...@gmail.com> vaaaaanquish <6sy...@gmail.com> vaaaaanquish <6sy...@gmail.com> 6syun9 <6sy...@gmail.com> @@ -53,7 +54,6 @@ Frank Sachsenheim <funkyfut...@riseup.net> Frank Sachsenheim <funkyfut...@users.noreply.github.com> Kurtis Rader <kra...@skepticism.us> cryzed <cry...@googlemail.com> -anki-code <anki-c...@users.noreply.github.com> Brian Visel <e...@eptitude.net> Andrew Hundt <athu...@gmail.com> Jonathan Slenders <jonat...@slenders.be> @@ -82,6 +82,7 @@ Nathan Goldbaum <ngold...@illinois.edu> Nathan Goldbaum <goldb...@ucolick.org> mel <m...@anybodytech.com> Jared Crawford <jmcrawfor...@gmail.com> +Mike Crowe <drmikecr...@gmail.com> drmikecrowe <drmikecr...@gmail.com> JuanPablo <jpabl...@gmail.com> Ollie Terrance <ollie.terra...@live.co.uk> Marcel Bollmann <bollm...@linguistics.rub.de> @@ -139,6 +140,7 @@ Sébastien Pierre <sebastien.pie...@gmail.com> shadow-light <42055707+shadow-li...@users.noreply.github.com> Jan Chren <dev.rind...@gmail.com> +Samuel Lotz <samuel.l...@salotz.info> Mark Wiebe <mwwi...@gmail.com> Nathan Hoad <nat...@getoffmalawn.com> Eric Dill <ed...@bnl.gov> @@ -161,11 +163,15 @@ Steven Kryskalla <skryska...@gmail.com> cclauss <ccla...@me.com> Eddie Peters <edward.paul.pet...@gmail.com> +Gyuri Horak <dy...@horak.hu> Ke Zhang <kezh...@bnl.gov> ke-zhang-rd <kezh...@bnl.gov> László Vaskó <vl...@balabit.hu> Allan Crooks <allan.cro...@sixtyten.org> micimize <rosenthal...@gmail.com> Edmund Miller <edmund.a.mil...@protonmail.com> +Noortheen Raja <jnoorth...@gmail.com> +Gabriel Vogel <gabriel.vo...@online.de> +anki <anki@code.email> Dan Allan <dal...@bnl.gov> Ned Letcher <nletc...@gmail.com> Zach Crownover <zachary.crowno...@gmail.com> @@ -222,16 +228,15 @@ Ronny Pfannschmidt <opensou...@ronnypfannschmidt.de> Troy de Freitas <9503857+nt...@users.noreply.github.com> Rodrigo Oliveira <rodrigo.olive...@byne.com.br> -Gyuri Horak <dy...@horak.hu> Daniel Smith <malor...@me.com> Nils ANDRÉ-CHANG <n...@nilsand.re> chengxuncc <chengxu...@gmail.com> nedsociety <nedsoci...@gmail.com> fanosta <git...@nageler.org> David Kalliecharan <david@david.science> -Mike Crowe <drmikecr...@gmail.com> drmikecrowe <drmikecr...@gmail.com> Sylvain Corlay <sylvain.cor...@gmail.com> Chris Lasher <chris.las...@gmail.com> Marcio Mazza <marcioma...@gmail.com> +Jerzy Drozdz <jerzy.dro...@gmail.com> goodboy <tgood...@users.noreply.github.com> Atsushi Morimoto <atsushi.morim...@dena.com> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/AUTHORS.rst new/xonsh-0.9.15/AUTHORS.rst --- old/xonsh-0.9.14/AUTHORS.rst 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/AUTHORS.rst 2020-03-19 21:38:46.000000000 +0100 @@ -13,8 +13,8 @@ * Jean-Benoist Leger * christopher * Klaus Alexander Seistrup -* Leonardo Santagada * David Strobach +* Leonardo Santagada * Burak Yiğit Kaya * Aaron Griffin * Rob Brewer @@ -26,6 +26,7 @@ * Gordon Ball * Travis Shirk * Joel Gerber +* anki-code * vaaaaanquish * Bernardas Ališauskas * Derek Thomas @@ -37,7 +38,6 @@ * Frank Sachsenheim * Kurtis Rader * cryzed -* anki-code * Brian Visel * Andrew Hundt * Jonathan Slenders @@ -66,6 +66,7 @@ * Nathan Goldbaum * mel * Jared Crawford +* Mike Crowe * JuanPablo * Ollie Terrance * Marcel Bollmann @@ -123,6 +124,7 @@ * Sébastien Pierre * shadow-light * Jan Chren +* Samuel Lotz * Mark Wiebe * Nathan Hoad * Eric Dill @@ -145,11 +147,15 @@ * Steven Kryskalla * cclauss * Eddie Peters +* Gyuri Horak * Ke Zhang * László Vaskó * Allan Crooks * micimize * Edmund Miller +* Noortheen Raja +* Gabriel Vogel +* anki * Dan Allan * Ned Letcher * Zach Crownover @@ -206,16 +212,15 @@ * Ronny Pfannschmidt * Troy de Freitas * Rodrigo Oliveira -* Gyuri Horak * Daniel Smith * Nils ANDRÉ-CHANG * chengxuncc * nedsociety * fanosta * David Kalliecharan -* Mike Crowe * Sylvain Corlay * Chris Lasher * Marcio Mazza +* Jerzy Drozdz * goodboy * Atsushi Morimoto diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/CHANGELOG.rst new/xonsh-0.9.15/CHANGELOG.rst --- old/xonsh-0.9.14/CHANGELOG.rst 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/CHANGELOG.rst 2020-03-19 21:38:46.000000000 +0100 @@ -4,6 +4,51 @@ .. current developments +v0.9.15 +==================== + +**Added:** + +* Adds documentation for how to setup an emacs editing mode for xonsh. +* New ``$XONSH_TRACE_SUBPROC`` environment variable. +* Added ``-l``, ``-c`` and ``-a`` options to ``xexec``, works now like ``exec`` + in bash/zsh +* **$HISTCONTROL** - *errordups* support for history-sqlite backend + +**Changed:** + +* ``-l`` switch works like bash, loads environment in non-interactive shell +* The xonsh pytest plugin no longer messes up the test order for pytest. Xsh test + are still executed first to avoid a bug were other tests would prevent ``test_*.xsh`` + files to run correctly. +* New repo name for xxh + +**Fixed:** + +* Correctly follow symlinks when using dot-dot paths with cd -P. +* ``execx`` does not require the input string to be newline-terminated. +* ``evalx`` accepts newline-terminated input string. +* Fixed issue where negative exit codes (such as those produced + by core dumps) where treated as logical successes when chaining + processes with other boolean expressions. +* Fixed XONSH_TRACE_SUBPROC for pipeline command. +* updated CONTRIBUTING.rst about running pylint for changed files + +**Authors:** + +* Anthony Scopatz +* Morten Enemark Lund +* David Strobach +* anki-code +* Samuel Lotz +* Gyuri Horak +* Noortheen Raja +* Gabriel Vogel +* anki +* Jerzy Drozdz + + + v0.9.14 ==================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/CONTRIBUTING.rst new/xonsh-0.9.15/CONTRIBUTING.rst --- old/xonsh-0.9.14/CONTRIBUTING.rst 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/CONTRIBUTING.rst 2020-03-19 21:38:46.000000000 +0100 @@ -119,7 +119,7 @@ need to run "conda install pylint" once. You can easily run pylint on the edited files in your uncommited git change:: - $ pylint $(git status -s | awk '/\.py$$/ { print $$2 }' | sort) + $ git status -s | awk '/\.py$$/ { print $2 }' | xargs pylint If you want to lint the entire code base run:: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/README.rst new/xonsh-0.9.15/README.rst --- old/xonsh-0.9.14/README.rst 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/README.rst 2020-03-19 21:38:46.000000000 +0100 @@ -29,4 +29,4 @@ - `gitsome <https://github.com/donnemartin/gitsome>`_: A supercharged Git/shell autocompleter with GitHub integration. - `rever <https://regro.github.io/rever-docs/>`_: Cross-platform software release tool. - `Regro autotick bot <https://github.com/regro/cf-scripts>`_: Regro Conda-Forge autoticker. -- `xxh <https://github.com/xonssh/xxh>`_: Using xonsh wherever you go through the ssh. +- `xxh <https://github.com/xxh/xxh>`_: Using xonsh wherever you go through the ssh. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/docs/editors.rst new/xonsh-0.9.15/docs/editors.rst --- old/xonsh-0.9.14/docs/editors.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/xonsh-0.9.15/docs/editors.rst 2020-03-19 21:38:46.000000000 +0100 @@ -0,0 +1,23 @@ + +============================== +Editor Support +============================== + +.. contents:: + :local: + +Emacs +===== + +There is an emacs mode for editing xonsh scripts available from the +`MELPA repository`_. If you are not familiar see the installation +instructions there. + +Then just add this line to your emacs configuration file: + +.. code-block:: emacs-lisp + + (require 'xonsh-mode) + + +.. _MELPA repository: https://melpa.org/#/xonsh-mode diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/docs/installation.rst new/xonsh-0.9.15/docs/installation.rst --- old/xonsh-0.9.14/docs/installation.rst 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/docs/installation.rst 2020-03-19 21:38:46.000000000 +0100 @@ -17,3 +17,4 @@ appimage containers customization + editors diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/tests/aliases/test_xexec.py new/xonsh-0.9.15/tests/aliases/test_xexec.py --- old/xonsh-0.9.14/tests/aliases/test_xexec.py 1970-01-01 01:00:00.000000000 +0100 +++ new/xonsh-0.9.15/tests/aliases/test_xexec.py 2020-03-19 21:38:46.000000000 +0100 @@ -0,0 +1,84 @@ +import os +import inspect +import pytest +import sys + +from xonsh.aliases import xexec + + +@pytest.fixture +def mockexecvpe(monkeypatch): + def mocked_execvpe(_command, _args, _env): + pass + + monkeypatch.setattr(os, "execvpe", mocked_execvpe) + + +def test_noargs(mockexecvpe): + assert xexec([]) == (None, "xonsh: exec: no args specified\n", 1) + + +def test_missing_command(mockexecvpe): + assert xexec(["-a", "foo"]) == (None, "xonsh: exec: no command specified\n", 1) + assert xexec(["-c"]) == (None, "xonsh: exec: no command specified\n", 1) + assert xexec(["-l"]) == (None, "xonsh: exec: no command specified\n", 1) + + +def test_command_not_found(monkeypatch): + + dummy_error_msg = "This is dummy error message, file not found or something like that" + command = "non_existing_command" + + def mocked_execvpe(_command, _args, _env): + raise FileNotFoundError(2, dummy_error_msg) + monkeypatch.setattr(os, "execvpe", mocked_execvpe) + + assert xexec([command]) == (None, + "xonsh: exec: file not found: {}: {}" "\n".format(dummy_error_msg, command), + 1) + + +def test_help(mockexecvpe): + assert xexec(["-h"]) == inspect.getdoc(xexec) + assert xexec(["--help"]) == inspect.getdoc(xexec) + + +def test_a_switch(monkeypatch): + called = {} + + def mocked_execvpe(command, args, env): + called.update({"command": command, "args": args, "env": env}) + + monkeypatch.setattr(os, "execvpe", mocked_execvpe) + proc_name = "foo" + command = "bar" + command_args = ["1"] + xexec(["-a", proc_name, command] + command_args) + assert called["command"] == command + assert called["args"][0] == proc_name + assert len(called["args"]) == len([command] + command_args) + + +def test_l_switch(monkeypatch): + called = {} + + def mocked_execvpe(command, args, env): + called.update({"command": command, "args": args, "env": env}) + + monkeypatch.setattr(os, "execvpe", mocked_execvpe) + command = "bar" + xexec(["-l", command, "1"]) + + assert called["args"][0].startswith("-") + + +def test_c_switch(monkeypatch): + called = {} + + def mocked_execvpe(command, args, env): + called.update({"command": command, "args": args, "env": env}) + + monkeypatch.setattr(os, "execvpe", mocked_execvpe) + command = "sleep" + xexec(["-c", command, "1"]) + assert called["env"] == {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/tests/test_environ.py new/xonsh-0.9.15/tests/test_environ.py --- old/xonsh-0.9.14/tests/test_environ.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/tests/test_environ.py 2020-03-19 21:38:46.000000000 +0100 @@ -101,6 +101,14 @@ assert "ignoredups" in env["HISTCONTROL"] +def test_histcontrol_ignoreerr_ignoredups_erase_dups(): + env = Env(HISTCONTROL="ignoreerr,ignoredups,ignoreerr,erasedups") + assert len(env["HISTCONTROL"]) == 3 + assert "ignoreerr" in env["HISTCONTROL"] + assert "ignoredups" in env["HISTCONTROL"] + assert "erasedups" in env["HISTCONTROL"] + + def test_swap(): env = Env(VAR="wakka") assert env["VAR"] == "wakka" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/tests/test_execer.py new/xonsh-0.9.15/tests/test_execer.py --- old/xonsh-0.9.14/tests/test_execer.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/tests/test_execer.py 2020-03-19 21:38:46.000000000 +0100 @@ -2,7 +2,13 @@ """Tests the xonsh lexer.""" import os -from tools import check_eval, check_parse, skip_if_on_unix, skip_if_on_windows +from tools import ( + check_eval, + check_exec, + check_parse, + skip_if_on_unix, + skip_if_on_windows, +) import pytest @@ -138,3 +144,12 @@ ) def test_two_echo_line_cont(code): assert check_parse(code) + + +def test_eval_eol(): + assert check_eval("0") and check_eval("0\n") + + +def test_exec_eol(): + locs = dict() + assert check_exec("a=0", locs=locs) and check_exec("a=0\n", locs=locs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/tests/test_history_sqlite.py new/xonsh-0.9.15/tests/test_history_sqlite.py --- old/xonsh-0.9.14/tests/test_history_sqlite.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/tests/test_history_sqlite.py 2020-03-19 21:38:46.000000000 +0100 @@ -169,6 +169,27 @@ assert -1 == hist.rtns[-1] +def test_histcontrol_erase_dup(hist, xonsh_builtins): + """Test HISTCONTROL=erasedups""" + + xonsh_builtins.__xonsh__.env["HISTCONTROL"] = "erasedups" + assert len(hist) == 0 + + hist.append({"inp": "ls foo", "rtn": 2}) + hist.append({"inp": "ls foobazz", "rtn": 0}) + hist.append({"inp": "ls foo", "rtn": 0}) + hist.append({"inp": "ls foobazz", "rtn": 0}) + hist.append({"inp": "ls foo", "rtn": 0}) + assert len(hist) == 2 + assert len(hist.inps) == 5 + + items = list(hist.items()) + assert "ls foo" == items[-1]["inp"] + assert "ls foobazz" == items[-2]["inp"] + assert items[-2]["frequency"] == 2 + assert items[-1]["frequency"] == 3 + + @pytest.mark.parametrize( "index, exp", [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/tests/test_integrations.py new/xonsh-0.9.15/tests/test_integrations.py --- old/xonsh-0.9.14/tests/test_integrations.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/tests/test_integrations.py 2020-03-19 21:38:46.000000000 +0100 @@ -559,3 +559,11 @@ "verify pipe between subprocesses doesn't throw an exception" check_run_xonsh(cmd, fmt, exp) + +@skip_if_on_windows +def test_negative_exit_codes_fail(): + # see issue 3309 + script = 'python -c "import os; os.abort()" && echo OK\n' + out, err, rtn = run_xonsh(script) + assert "OK" is not out + assert "OK" is not err diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/tests/tools.py new/xonsh-0.9.15/tests/tools.py --- old/xonsh-0.9.14/tests/tools.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/tests/tools.py 2020-03-19 21:38:46.000000000 +0100 @@ -174,8 +174,6 @@ def check_exec(input, **kwargs): - if not input.endswith("\n"): - input += "\n" builtins.__xonsh__.execer.exec(input, **kwargs) return True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/__init__.py new/xonsh-0.9.15/xonsh/__init__.py --- old/xonsh-0.9.14/xonsh/__init__.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/__init__.py 2020-03-19 21:38:46.000000000 +0100 @@ -1,4 +1,4 @@ -__version__ = "0.9.14" +__version__ = "0.9.15" # amalgamate exclude jupyter_kernel parser_table parser_test_table pyghooks diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/aliases.py new/xonsh-0.9.15/xonsh/aliases.py --- old/xonsh-0.9.14/xonsh/aliases.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/aliases.py 2020-03-19 21:38:46.000000000 +0100 @@ -610,7 +610,7 @@ def xexec(args, stdin=None): - """exec [-h|--help] command [args...] + """exec [-h|--help] [-cl] [-a name] command [args...] exec (also aliased as xexec) uses the os.execvpe() function to replace the xonsh process with the specified program. This provides @@ -620,6 +620,13 @@ bash $ The '-h' and '--help' options print this message and exit. + If the '-l' option is supplied, the shell places a dash at the + beginning of the zeroth argument passed to command to simulate login + shell. + The '-c' option causes command to be executed with an empty environment. + If '-a' is supplied, the shell passes name as the zeroth argument + to the executed command. + Notes ----- @@ -633,18 +640,40 @@ """ if len(args) == 0: return (None, "xonsh: exec: no args specified\n", 1) - elif args[0] == "-h" or args[0] == "--help": + + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("-h", "--help", action="store_true") + parser.add_argument("-l", dest="login", action="store_true") + parser.add_argument("-c", dest="clean", action="store_true") + parser.add_argument("-a", dest="name", nargs="?") + parser.add_argument("command", nargs=argparse.REMAINDER) + args = parser.parse_args(args) + + if args.help: return inspect.getdoc(xexec) - else: + + if len(args.command) == 0: + return (None, "xonsh: exec: no command specified\n", 1) + + command = args.command[0] + if args.name is not None: + args.command[0] = args.name + if args.login: + args.command[0] = "-{}".format(args.command[0]) + + denv = {} + if not args.clean: denv = builtins.__xonsh__.env.detype() - try: - os.execvpe(args[0], args, denv) - except FileNotFoundError as e: - return ( - None, - "xonsh: exec: file not found: {}: {}" "\n".format(e.args[1], args[0]), - 1, - ) + + try: + os.execvpe(command, args.command, denv) + except FileNotFoundError as e: + return ( + None, + "xonsh: exec: file not found: {}: {}" + "\n".format(e.args[1], args.command[0]), + 1, + ) class AWitchAWitch(argparse.Action): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/built_ins.py new/xonsh-0.9.15/xonsh/built_ins.py --- old/xonsh-0.9.14/xonsh/built_ins.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/built_ins.py 2020-03-19 21:38:46.000000000 +0100 @@ -934,6 +934,9 @@ Lastly, the captured argument affects only the last real command. """ + if builtins.__xonsh__.env.get("XONSH_TRACE_SUBPROC"): + print("TRACE SUBPROC: %s" % str(cmds), file=sys.stderr) + specs = cmds_to_specs(cmds, captured=captured) captured = specs[-1].captured if captured == "hiddenobject": diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/dirstack.py new/xonsh-0.9.15/xonsh/dirstack.py --- old/xonsh-0.9.14/xonsh/dirstack.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/dirstack.py 2020-03-19 21:38:46.000000000 +0100 @@ -147,10 +147,10 @@ env = builtins.__xonsh__.env old = env["PWD"] new = os.path.join(old, newdir) - absnew = os.path.abspath(new) if follow_symlinks: - absnew = os.path.realpath(absnew) + new = os.path.realpath(new) + absnew = os.path.abspath(new) try: os.chdir(absnew) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/environ.py new/xonsh-0.9.15/xonsh/environ.py --- old/xonsh-0.9.14/xonsh/environ.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/environ.py 2020-03-19 21:38:46.000000000 +0100 @@ -403,8 +403,8 @@ @property def style_name(self): """Current XONSH_COLOR_STYLE value""" - env = builtins.__xonsh__.env - env_style_name = env.get("XONSH_COLOR_STYLE") + env = getattr(builtins.__xonsh__, "env", {}) + env_style_name = env.get("XONSH_COLOR_STYLE", "default") if self._style_name is None or self._style_name != env_style_name: self._style_name = env_style_name self._style = self._dtyped = None @@ -626,6 +626,7 @@ "XONSH_STDERR_POSTFIX": (is_string, ensure_string, ensure_string), "XONSH_STORE_STDOUT": (is_bool, to_bool, bool_to_str), "XONSH_STORE_STDIN": (is_bool, to_bool, bool_to_str), + "XONSH_TRACE_SUBPROC": (is_bool, to_bool, bool_to_str), "XONSH_TRACEBACK_LOGFILE": (is_logfile_opt, to_logfile_opt, logfile_opt_to_str), "XONSH_DATETIME_FORMAT": (is_string, ensure_string, ensure_string), } @@ -805,6 +806,7 @@ "XONSH_HISTORY_SIZE": (8128, "commands"), "XONSH_LOGIN": False, "XONSH_PROC_FREQUENCY": 1e-4, + "XONSH_TRACE_SUBPROC": False, "XONSH_SHOW_TRACEBACK": False, "XONSH_STDERR_PREFIX": "", "XONSH_STDERR_POSTFIX": "", @@ -1002,8 +1004,10 @@ "that determine what commands are saved to the history list. By " "default all commands are saved. The option ``ignoredups`` will not " "save the command if it matches the previous command. The option " - "'ignoreerr' will cause any commands that fail (i.e. return non-zero " - "exit status) to not be added to the history list.", + "``ignoreerr`` will cause any commands that fail (i.e. return non-zero " + "exit status) to not be added to the history list. The option " + "``erasedups`` will remove all previous commands that matches and updates the frequency. " + "Note: ``erasedups`` is supported only in sqlite backend).", store_as_str=True, ), "IGNOREEOF": VarDocs("Prevents Ctrl-D from exiting the shell."), @@ -1363,6 +1367,9 @@ "xonsh process threads sleep for while running command pipelines. " "The value has units of seconds [s]." ), + "XONSH_TRACE_SUBPROC": VarDocs( + "Set to ``True`` to show arguments list of every executed subprocess command." + ), "XONSH_SHOW_TRACEBACK": VarDocs( "Controls if a traceback is shown if exceptions occur in the shell. " "Set to ``True`` to always show traceback or ``False`` to always hide. " diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/execer.py new/xonsh-0.9.15/xonsh/execer.py --- old/xonsh-0.9.14/xonsh/execer.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/execer.py 2020-03-19 21:38:46.000000000 +0100 @@ -145,6 +145,7 @@ if isinstance(input, types.CodeType): code = input else: + input = input.rstrip("\n") if filename is None: filename = self.filename code = self.compile( @@ -174,6 +175,8 @@ if isinstance(input, types.CodeType): code = input else: + if not input.endswith("\n"): + input += "\n" if filename is None: filename = self.filename code = self.compile( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/history/sqlite.py new/xonsh-0.9.15/xonsh/history/sqlite.py --- old/xonsh-0.9.14/xonsh/history/sqlite.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/history/sqlite.py 2020-03-19 21:38:46.000000000 +0100 @@ -12,6 +12,10 @@ from xonsh.history.base import History import xonsh.tools as xt +XH_SQLITE_CACHE = threading.local() +XH_SQLITE_TABLE_NAME = "xonsh_history" +XH_SQLITE_CREATED_SQL_TBL = "CREATED_SQL_TABLE" + def _xh_sqlite_get_file_name(): envs = builtins.__xonsh__.env @@ -33,35 +37,84 @@ Columns: info - JSON formatted, reserved for future extension. + frequency - in case of HISTCONTROL=erasedups, + it tracks the frequency of the inputs. helps in sorting autocompletion """ + if not getattr(XH_SQLITE_CACHE, XH_SQLITE_CREATED_SQL_TBL, False): + cursor.execute( + """ + CREATE TABLE IF NOT EXISTS {} + (inp TEXT, + rtn INTEGER, + tsb REAL, + tse REAL, + sessionid TEXT, + out TEXT, + info TEXT, + frequency INTEGER default 1 + ) + """.format( + XH_SQLITE_TABLE_NAME + ) + ) + # add frequency column if not exists for backward compatibility + try: + cursor.execute( + "ALTER TABLE " + + XH_SQLITE_TABLE_NAME + + " ADD COLUMN frequency INTEGER default 1" + ) + except sqlite3.OperationalError: + pass + + # mark that this function ran for this session + setattr(XH_SQLITE_CACHE, XH_SQLITE_CREATED_SQL_TBL, True) + + +def _xh_sqlite_get_frequency(cursor, input): + # type: (sqlite3.Cursor, str) -> int + sql = "SELECT sum(frequency) FROM {} WHERE inp=?".format(XH_SQLITE_TABLE_NAME) + cursor.execute(sql, (input,)) + return cursor.fetchone()[0] or 0 + + +def _xh_sqlite_erase_dups(cursor, input): + freq = _xh_sqlite_get_frequency(cursor, input) + sql = "DELETE FROM {} WHERE inp=?".format(XH_SQLITE_TABLE_NAME) + cursor.execute(sql, (input,)) + return freq + + +def _sql_insert(cursor, values): + # type: (sqlite3.Cursor, dict) -> None + """handy function to run insert query""" + sql = "INSERT INTO {} ({}) VALUES ({});" + fields = ", ".join(values) + marks = ", ".join(["?"] * len(values)) cursor.execute( - """ - CREATE TABLE IF NOT EXISTS xonsh_history - (inp TEXT, - rtn INTEGER, - tsb REAL, - tse REAL, - sessionid TEXT, - out TEXT, - info TEXT - ) - """ + sql.format(XH_SQLITE_TABLE_NAME, fields, marks), tuple(values.values()) ) -def _xh_sqlite_insert_command(cursor, cmd, sessionid, store_stdout): - sql = "INSERT INTO xonsh_history (inp, rtn, tsb, tse, sessionid" +def _xh_sqlite_insert_command(cursor, cmd, sessionid, store_stdout, remove_duplicates): tss = cmd.get("ts", [None, None]) - params = [cmd["inp"].rstrip(), cmd["rtn"], tss[0], tss[1], sessionid] + values = collections.OrderedDict( + [ + ("inp", cmd["inp"].rstrip()), + ("rtn", cmd["rtn"]), + ("tsb", tss[0]), + ("tse", tss[1]), + ("sessionid", sessionid), + ] + ) if store_stdout and "out" in cmd: - sql += ", out" - params.append(cmd["out"]) + values["out"] = cmd["out"] if "info" in cmd: - sql += ", info" info = json.dumps(cmd["info"]) - params.append(info) - sql += ") VALUES (" + ("?, " * len(params)).rstrip(", ") + ")" - cursor.execute(sql, tuple(params)) + values["info"] = info + if remove_duplicates: + values["frequency"] = _xh_sqlite_erase_dups(cursor, values["inp"]) + 1 + _sql_insert(cursor, values) def _xh_sqlite_get_count(cursor, sessionid=None): @@ -75,7 +128,7 @@ def _xh_sqlite_get_records(cursor, sessionid=None, limit=None, newest_first=False): - sql = "SELECT inp, tsb, rtn FROM xonsh_history " + sql = "SELECT inp, tsb, rtn, frequency FROM xonsh_history " params = [] if sessionid is not None: sql += "WHERE sessionid = ? " @@ -103,11 +156,13 @@ return result.rowcount -def xh_sqlite_append_history(cmd, sessionid, store_stdout, filename=None): +def xh_sqlite_append_history( + cmd, sessionid, store_stdout, filename=None, remove_duplicates=False +): with _xh_sqlite_get_conn(filename=filename) as conn: c = conn.cursor() _xh_sqlite_create_history_table(c) - _xh_sqlite_insert_command(c, cmd, sessionid, store_stdout) + _xh_sqlite_insert_command(c, cmd, sessionid, store_stdout, remove_duplicates) conn.commit() @@ -181,9 +236,11 @@ self.outs = [] self.tss = [] + # during init rerun create command + setattr(XH_SQLITE_CACHE, XH_SQLITE_CREATED_SQL_TBL, False) + def append(self, cmd): envs = builtins.__xonsh__.env - opts = envs.get("HISTCONTROL") inp = cmd["inp"].rstrip() self.inps.append(inp) store_stdout = envs.get("XONSH_STORE_STDOUT", False) @@ -203,22 +260,23 @@ return self._last_hist_inp = inp xh_sqlite_append_history( - cmd, str(self.sessionid), store_stdout, filename=self.filename + cmd, + str(self.sessionid), + store_stdout, + filename=self.filename, + remove_duplicates=("erasedups" in opts), ) - def all_items(self, newest_first=False): + def all_items(self, newest_first=False, session_id=None): """Display all history items.""" - for item in xh_sqlite_items(filename=self.filename, newest_first=newest_first): - yield {"inp": item[0], "ts": item[1], "rtn": item[2]} + for inp, ts, rtn, freq in xh_sqlite_items( + filename=self.filename, newest_first=newest_first, sessionid=session_id + ): + yield {"inp": inp, "ts": ts, "rtn": rtn, "frequency": freq} def items(self, newest_first=False): """Display history items of current session.""" - for item in xh_sqlite_items( - sessionid=str(self.sessionid), - filename=self.filename, - newest_first=newest_first, - ): - yield {"inp": item[0], "ts": item[1], "rtn": item[2]} + yield from self.all_items(newest_first, session_id=str(self.sessionid)) def info(self): data = collections.OrderedDict() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/main.py new/xonsh-0.9.15/xonsh/main.py --- old/xonsh-0.9.14/xonsh/main.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/main.py 2020-03-19 21:38:46.000000000 +0100 @@ -292,7 +292,11 @@ env = builtins.__xonsh__.env rc = shell_kwargs.get("rc", None) rc = env.get("XONSHRC") if rc is None else rc - if args.mode != XonshMode.interactive and not args.force_interactive: + if ( + args.mode != XonshMode.interactive + and not args.force_interactive + and not args.login + ): # Don't load xonshrc if not interactive shell rc = None events.on_pre_rc.fire() @@ -329,7 +333,8 @@ "cacheall": args.cacheall, "ctx": builtins.__xonsh__.ctx, } - if args.login: + if args.login or sys.argv[0].startswith("-"): + args.login = True shell_kwargs["login"] = True if args.norc: shell_kwargs["rc"] = () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/proc.py new/xonsh-0.9.15/xonsh/proc.py --- old/xonsh-0.9.14/xonsh/proc.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/proc.py 2020-03-19 21:38:46.000000000 +0100 @@ -2288,7 +2288,7 @@ rtn = self.returncode if ( rtn is not None - and rtn > 0 + and rtn != 0 and builtins.__xonsh__.env.get("RAISE_SUBPROC_ERROR") ): try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xonsh-0.9.14/xonsh/pytest_plugin.py new/xonsh-0.9.15/xonsh/pytest_plugin.py --- old/xonsh-0.9.14/xonsh/pytest_plugin.py 2020-02-28 22:07:39.000000000 +0100 +++ new/xonsh-0.9.15/xonsh/pytest_plugin.py 2020-03-19 21:38:46.000000000 +0100 @@ -14,7 +14,17 @@ def pytest_collection_modifyitems(items): - items.sort(key=lambda x: 0 if isinstance(x, XshFunction) else 1) + """ Move xsh test first to work around a bug in normal + pytest cleanup. The order of tests are otherwise preserved. + """ + xsh_items = [] + other_items = [] + for item in items: + if isinstance(item, XshFunction): + xsh_items.append(item) + else: + other_items.append(item) + items[:] = xsh_items + other_items def _limited_traceback(excinfo):