mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 16:34:47 +01:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
8e28a2e8af
48 changed files with 580 additions and 281 deletions
|
@ -1,4 +1,4 @@
|
||||||
version: 0.8.3.{build}
|
version: 0.8.5.{build}
|
||||||
os: Windows Server 2012 R2
|
os: Windows Server 2012 R2
|
||||||
environment:
|
environment:
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,10 @@ IF "%XONSH_TEST_ENV%" == "MSYS2" (
|
||||||
%MSYS2_PATH%\usr\bin\pacman.exe -Syu --noconfirm
|
%MSYS2_PATH%\usr\bin\pacman.exe -Syu --noconfirm
|
||||||
%MSYS2_PATH%\usr\bin\pacman.exe -S --noconfirm python3 python3-pip
|
%MSYS2_PATH%\usr\bin\pacman.exe -S --noconfirm python3 python3-pip
|
||||||
%MSYS2_PATH%\usr\bin\bash.exe -c "/usr/bin/pip install -r requirements-tests.txt"
|
%MSYS2_PATH%\usr\bin\bash.exe -c "/usr/bin/pip install -r requirements-tests.txt"
|
||||||
|
%MSYS2_PATH%\usr\bin\bash.exe -c "/usr/bin/python setup.py install"
|
||||||
) ELSE (
|
) ELSE (
|
||||||
echo "Windows Environment"
|
echo "Windows Environment"
|
||||||
%PYTHON%\Scripts\pip install -r requirements-tests.txt --upgrade --upgrade-strategy eager
|
%PYTHON%\Scripts\pip install -r requirements-tests.txt --upgrade --upgrade-strategy eager
|
||||||
|
%PYTHON%\python.exe --version
|
||||||
|
%PYTHON%\python.exe setup.py install
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,8 +5,10 @@ IF "%XONSH_TEST_ENV%" == "MSYS2" (
|
||||||
REM We monkey path `py._path.local.PosixPath` here such that it does not
|
REM We monkey path `py._path.local.PosixPath` here such that it does not
|
||||||
REM allow to create symlinks which are not supported by MSYS2 anyway. As a
|
REM allow to create symlinks which are not supported by MSYS2 anyway. As a
|
||||||
REM result the other pytest code uses a workaround.
|
REM result the other pytest code uses a workaround.
|
||||||
call %MSYS2_PATH%\usr\bin\bash.exe -c "/usr/bin/python -u -c 'import py._path.local; del py._path.local.PosixPath.mksymlinkto; import pytest; raise SystemExit(pytest.main())'" || EXIT 1
|
SET "PATH=%MSYS2_PATH%\usr\bin;%PATH%"
|
||||||
|
call bash.exe -c "/usr/bin/xonsh run-tests.xsh" || EXIT 1
|
||||||
) ELSE (
|
) ELSE (
|
||||||
echo "Windows Environment"
|
echo "Windows Environment"
|
||||||
call %PYTHON%\Scripts\py.test || EXIT 1
|
SET "PATH=%PYTHON%\Scripts;%PATH%"
|
||||||
|
call xonsh run-tests.xsh || EXIT 1
|
||||||
)
|
)
|
||||||
|
|
|
@ -43,7 +43,9 @@ jobs:
|
||||||
pip install . --no-deps
|
pip install . --no-deps
|
||||||
- run:
|
- run:
|
||||||
command: |
|
command: |
|
||||||
/home/circleci/miniconda/envs/py34-xonsh-test/bin/pytest --timeout=10
|
export PATH="$HOME/miniconda/bin:$PATH"
|
||||||
|
source activate ${ENV_NAME}
|
||||||
|
xonsh run-tests.xsh --timeout=10
|
||||||
build_35:
|
build_35:
|
||||||
machine: true
|
machine: true
|
||||||
environment:
|
environment:
|
||||||
|
@ -87,7 +89,9 @@ jobs:
|
||||||
pip install . --no-deps
|
pip install . --no-deps
|
||||||
- run:
|
- run:
|
||||||
command: |
|
command: |
|
||||||
/home/circleci/miniconda/envs/py35-xonsh-test/bin/pytest --timeout=10
|
export PATH="$HOME/miniconda/bin:$PATH"
|
||||||
|
source activate ${ENV_NAME}
|
||||||
|
xonsh run-tests.xsh --timeout=10
|
||||||
build_36:
|
build_36:
|
||||||
machine: true
|
machine: true
|
||||||
environment:
|
environment:
|
||||||
|
@ -131,7 +135,9 @@ jobs:
|
||||||
pip install . --no-deps
|
pip install . --no-deps
|
||||||
- run:
|
- run:
|
||||||
command: |
|
command: |
|
||||||
/home/circleci/miniconda/envs/py36-xonsh-test/bin/pytest --timeout=10 --flake8 --cov=./xonsh
|
export PATH="$HOME/miniconda/bin:$PATH"
|
||||||
|
source activate ${ENV_NAME}
|
||||||
|
xonsh run-tests.xsh --timeout=10 --flake8 --cov=./xonsh
|
||||||
build_37:
|
build_37:
|
||||||
machine: true
|
machine: true
|
||||||
environment:
|
environment:
|
||||||
|
@ -175,7 +181,9 @@ jobs:
|
||||||
pip install . --no-deps
|
pip install . --no-deps
|
||||||
- run:
|
- run:
|
||||||
command: |
|
command: |
|
||||||
/home/circleci/miniconda/envs/py37-xonsh-test/bin/pytest --timeout=10 --flake8 --cov=./xonsh
|
export PATH="$HOME/miniconda/bin:$PATH"
|
||||||
|
source activate ${ENV_NAME}
|
||||||
|
xonsh run-tests.xsh --timeout=10 --flake8 --cov=./xonsh
|
||||||
build_black:
|
build_black:
|
||||||
machine: true
|
machine: true
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -51,6 +51,7 @@ install:
|
||||||
python setup.py install;
|
python setup.py install;
|
||||||
else
|
else
|
||||||
pip install --upgrade -r requirements-tests.txt;
|
pip install --upgrade -r requirements-tests.txt;
|
||||||
|
python setup.py install;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
@ -71,6 +72,6 @@ script:
|
||||||
cd ..;
|
cd ..;
|
||||||
doctr deploy --deploy-repo xonsh/xonsh-docs .;
|
doctr deploy --deploy-repo xonsh/xonsh-docs .;
|
||||||
else
|
else
|
||||||
py.test --timeout=10;
|
xonsh run-tests.xsh --timeout=10;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
119
CHANGELOG.rst
119
CHANGELOG.rst
|
@ -4,6 +4,125 @@ Xonsh Change Log
|
||||||
|
|
||||||
.. current developments
|
.. current developments
|
||||||
|
|
||||||
|
v0.8.5
|
||||||
|
====================
|
||||||
|
|
||||||
|
**Added:**
|
||||||
|
|
||||||
|
* Add alias to `base16 shell <https://github.com/chriskempson/base16-shell>`_
|
||||||
|
|
||||||
|
* Installation / Usage
|
||||||
|
1. To install use pip
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
python3 -m pip install xontrib-base16-shell
|
||||||
|
|
||||||
|
2. Add on ``~/.xonshrc``
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
:number-lines:
|
||||||
|
|
||||||
|
$BASE16_SHELL = $HOME + "/.config/base16-shell/"
|
||||||
|
xontrib load base16_shell
|
||||||
|
|
||||||
|
|
||||||
|
3. See image
|
||||||
|
|
||||||
|
.. image:: https://raw.githubusercontent.com/ErickTucto/xontrib-base16-shell/master/docs/terminal.png
|
||||||
|
:width: 600px
|
||||||
|
:alt: terminal.png
|
||||||
|
* New ``DumbShell`` class that kicks in whenever ``$TERM == "dumb"``.
|
||||||
|
This usually happens in emacs. Currently, this class inherits from
|
||||||
|
the ``ReadlineShell`` but adds some light customization to make
|
||||||
|
sure that xonsh looks good in the resultant terminal emulator.
|
||||||
|
* Aliases from foreign shells (e.g. Bash) that are more than single expressions,
|
||||||
|
or contain sub-shell executions, are now evaluated and run in the foreign shell.
|
||||||
|
Previously, xonsh would attempt to translate the alias from sh-lang into
|
||||||
|
xonsh. These restrictions have been removed. For example, the following now
|
||||||
|
works:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
$ source-bash 'alias eee="echo aaa \$(echo b)"'
|
||||||
|
$ eee
|
||||||
|
aaa b
|
||||||
|
|
||||||
|
* New ``ForeignShellBaseAlias``, ``ForeignShellFunctionAlias``, and
|
||||||
|
``ForeignShellExecAlias`` classes have been added which manage foreign shell
|
||||||
|
alias execution.
|
||||||
|
|
||||||
|
|
||||||
|
**Changed:**
|
||||||
|
|
||||||
|
* String aliases will now first be checked to see if they contain sub-expressions
|
||||||
|
that require evaluations, such as ``@(expr)``, ``$[cmd]``, etc. If they do,
|
||||||
|
then an ``ExecAlias`` will be constructed, rather than a simple list-of-strs
|
||||||
|
substitutiuon alias being used. For example:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
$ aliases['uuu'] = "echo ccc $(echo ddd)"
|
||||||
|
$ aliases['uuu']
|
||||||
|
ExecAlias('echo ccc $(echo ddd)\n', filename='<exec-alias:uuu>')
|
||||||
|
$ uuu
|
||||||
|
ccc ddd
|
||||||
|
|
||||||
|
* The ``parse_aliases()`` function now requires the shell name.
|
||||||
|
* ``ForeignShellFunctionAlias`` now inherits from ``ForeignShellBaseAlias``
|
||||||
|
rather than ``object``.
|
||||||
|
|
||||||
|
|
||||||
|
**Fixed:**
|
||||||
|
|
||||||
|
* Fixed issues where the prompt-toolkit v2 shell would print an extra newline
|
||||||
|
after Python evaluations in interactive mode.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
v0.8.4
|
||||||
|
====================
|
||||||
|
|
||||||
|
**Added:**
|
||||||
|
|
||||||
|
* Added the possibility of arbitrary paths to the help strings in ``vox activate`` and
|
||||||
|
``vox remove``; also updated the documentation accordingly.
|
||||||
|
* New ``xonsh.aliases.ExecAlias`` class enables multi-statement aliases.
|
||||||
|
* New ``xonsh.ast.isexpression()`` function will return a boolean of whether
|
||||||
|
code is a simple xonsh expression or not.
|
||||||
|
* Added top-level ``run-tests.xsh`` script for safely running the test suite.
|
||||||
|
|
||||||
|
|
||||||
|
**Changed:**
|
||||||
|
|
||||||
|
* String aliases are no longer split with ``shlex.split()``, but instead use
|
||||||
|
``xonsh.lexer.Lexer.split()``.
|
||||||
|
* Update xonsh/prompt/cwd.py _collapsed_pwd to print 2 chars if a directory begins with "."
|
||||||
|
* test which determines whether a directory is a virtualenv
|
||||||
|
|
||||||
|
previously it used to check the existence of 'pyvenv.cfg'
|
||||||
|
now it checks if 'bin/python' is executable
|
||||||
|
|
||||||
|
|
||||||
|
**Fixed:**
|
||||||
|
|
||||||
|
* Fixed issue with ``and`` & ``or`` being incorrectly tokenized in implicit
|
||||||
|
subprocesses. Auto-wrapping of certain subprocesses will now correctly work.
|
||||||
|
For example::
|
||||||
|
|
||||||
|
$ echo x-and-y
|
||||||
|
x-and-y
|
||||||
|
* Fix EOFError when press `control+d`
|
||||||
|
* fix no candidates if no permission files in PATH
|
||||||
|
* Fixed interpretation of color names with PTK2 and Pygments 2.3.
|
||||||
|
* Several ResourceWarnings: unclosed file in tests
|
||||||
|
* AttributeError crash when using --timings flag
|
||||||
|
* issue #2929
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
v0.8.3
|
v0.8.3
|
||||||
====================
|
====================
|
||||||
|
|
||||||
|
|
|
@ -20,15 +20,16 @@ jobs:
|
||||||
architecture: 'x64'
|
architecture: 'x64'
|
||||||
|
|
||||||
# Conda Environment
|
# Conda Environment
|
||||||
# Create and activate a Conda environment.
|
# Create and activate a Conda environment.
|
||||||
- task: CondaEnvironment@1
|
- task: CondaEnvironment@1
|
||||||
inputs:
|
inputs:
|
||||||
packageSpecs: 'python=$(python.version) pygments prompt_toolkit ply pytest pytest-timeout numpy psutil matplotlib flake8 coverage pyflakes pytest-cov pytest-flake8 codecov'
|
packageSpecs: 'python=$(python.version) pygments prompt_toolkit ply pytest pytest-timeout numpy psutil matplotlib flake8 coverage pyflakes pytest-cov pytest-flake8 codecov'
|
||||||
installOptions: '-c conda-forge'
|
installOptions: '-c conda-forge'
|
||||||
updateConda: false
|
updateConda: false
|
||||||
- script: |
|
- script: |
|
||||||
pytest --timeout=10 --junitxml=junit/test-results.xml
|
pip install .
|
||||||
displayName: 'pytest'
|
xonsh run-tests.xsh --timeout=10 --junitxml=junit/test-results.xml
|
||||||
|
displayName: 'Tests'
|
||||||
|
|
||||||
# Publish build results
|
# Publish build results
|
||||||
- task: PublishTestResults@2
|
- task: PublishTestResults@2
|
||||||
|
|
10
docs/api/dumb_shell.rst
Normal file
10
docs/api/dumb_shell.rst
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
.. _xonsh_dumb_shell:
|
||||||
|
|
||||||
|
******************************************************
|
||||||
|
Dumb Shell (``xonsh.dumb_shell``)
|
||||||
|
******************************************************
|
||||||
|
|
||||||
|
.. automodule:: xonsh.dumb_shell
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:inherited-members:
|
|
@ -74,6 +74,7 @@ For those of you who want the gritty details.
|
||||||
pyghooks
|
pyghooks
|
||||||
jupyter_kernel
|
jupyter_kernel
|
||||||
jupyter_shell
|
jupyter_shell
|
||||||
|
dumb_shell
|
||||||
wizard
|
wizard
|
||||||
xonfig
|
xonfig
|
||||||
codecache
|
codecache
|
||||||
|
|
|
@ -1122,7 +1122,14 @@ matching only occurs for the first element of a subprocess command.
|
||||||
The keys of ``aliases`` are strings that act as commands in subprocess-mode.
|
The keys of ``aliases`` are strings that act as commands in subprocess-mode.
|
||||||
The values are lists of strings, where the first element is the command, and
|
The values are lists of strings, where the first element is the command, and
|
||||||
the rest are the arguments. You can also set the value to a string, in which
|
the rest are the arguments. You can also set the value to a string, in which
|
||||||
case it will be converted to a list automatically with ``shlex.split``.
|
one of two things will happen:
|
||||||
|
|
||||||
|
1. If the string is a xonsh expression, it will be converted to a list
|
||||||
|
automatically with xonsh's ``Lexer.split()`` method.
|
||||||
|
2. If the string is more complex (representing a block of xonsh code),
|
||||||
|
the alias will be registered as an ``ExecAlias``, which is a callable
|
||||||
|
alias. This block of code will then be executed whenever the alias is
|
||||||
|
run.
|
||||||
|
|
||||||
For example, the following creates several aliases for the ``git``
|
For example, the following creates several aliases for the ``git``
|
||||||
version control software. Both styles (list of strings and single
|
version control software. Both styles (list of strings and single
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
**Added:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Changed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Deprecated:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Removed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Fixed:**
|
|
||||||
|
|
||||||
* Fixed issue with ``and`` & ``or`` being incoreectly tokenized in implicit
|
|
||||||
subprocesses. Auto-wrapping of certain subprocesses will now correctly work.
|
|
||||||
For example::
|
|
||||||
|
|
||||||
$ echo x-and-y
|
|
||||||
x-and-y
|
|
||||||
|
|
||||||
**Security:**
|
|
||||||
|
|
||||||
* <news item>
|
|
|
@ -1,24 +0,0 @@
|
||||||
**Added:**
|
|
||||||
|
|
||||||
* Added the possibility of arbitrary paths to the help strings in ``vox activate`` and
|
|
||||||
``vox remove``; also updated the documentation accordingly.
|
|
||||||
|
|
||||||
**Changed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Deprecated:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Removed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Fixed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Security:**
|
|
||||||
|
|
||||||
* <news item>
|
|
|
@ -1,23 +0,0 @@
|
||||||
**Added:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Changed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Deprecated:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Removed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Fixed:**
|
|
||||||
|
|
||||||
* fix no candidates if no permission files in PATH
|
|
||||||
|
|
||||||
**Security:**
|
|
||||||
|
|
||||||
* <news item>
|
|
|
@ -1,23 +0,0 @@
|
||||||
**Added:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Changed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Deprecated:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Removed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Fixed:**
|
|
||||||
|
|
||||||
* Several ResourceWarnings: unclosed file in tests
|
|
||||||
|
|
||||||
**Security:**
|
|
||||||
|
|
||||||
* <news item>
|
|
|
@ -1,23 +0,0 @@
|
||||||
**Added:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Changed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Deprecated:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Removed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Fixed:**
|
|
||||||
|
|
||||||
* AttributeError crash when using --timings flag
|
|
||||||
|
|
||||||
**Security:**
|
|
||||||
|
|
||||||
* <news item>
|
|
|
@ -1,23 +0,0 @@
|
||||||
**Added:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Changed:**
|
|
||||||
|
|
||||||
* Update xonsh/prompt/cwd.py _collapsed_pwd to print 2 chars if a directory begins with "."
|
|
||||||
|
|
||||||
**Deprecated:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Removed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Fixed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Security:**
|
|
||||||
|
|
||||||
* <news item>
|
|
|
@ -1,26 +0,0 @@
|
||||||
**Added:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Changed:**
|
|
||||||
|
|
||||||
* test which determines whether a directory is a virtualenv
|
|
||||||
|
|
||||||
previously it used to check the existence of 'pyvenv.cfg'
|
|
||||||
now it checks if 'bin/python' is executable
|
|
||||||
|
|
||||||
**Deprecated:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Removed:**
|
|
||||||
|
|
||||||
* <news item>
|
|
||||||
|
|
||||||
**Fixed:**
|
|
||||||
|
|
||||||
* issue #2929
|
|
||||||
|
|
||||||
**Security:**
|
|
||||||
|
|
||||||
* <news item>
|
|
|
@ -12,6 +12,8 @@ $VERSION_BUMP_PATTERNS = [
|
||||||
$CHANGELOG_FILENAME = 'CHANGELOG.rst'
|
$CHANGELOG_FILENAME = 'CHANGELOG.rst'
|
||||||
$CHANGELOG_TEMPLATE = 'TEMPLATE.rst'
|
$CHANGELOG_TEMPLATE = 'TEMPLATE.rst'
|
||||||
|
|
||||||
|
$PYTEST_COMMAND = "./run-tests.xsh"
|
||||||
|
|
||||||
$TAG_REMOTE = 'git@github.com:xonsh/xonsh.git'
|
$TAG_REMOTE = 'git@github.com:xonsh/xonsh.git'
|
||||||
$TAG_TARGET = 'master'
|
$TAG_TARGET = 'master'
|
||||||
|
|
||||||
|
|
10
run-tests.xsh
Executable file
10
run-tests.xsh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env xonsh
|
||||||
|
$RAISE_SUBPROC_ERROR = True
|
||||||
|
|
||||||
|
run_separately = [
|
||||||
|
'tests/test_ptk_highlight.py',
|
||||||
|
]
|
||||||
|
|
||||||
|
![pytest @($ARGS[1:]) --ignore @(run_separately)]
|
||||||
|
for fname in run_separately:
|
||||||
|
![pytest @($ARGS[1:]) @(fname)]
|
|
@ -33,8 +33,24 @@ def source_path():
|
||||||
return os.path.dirname(pwd)
|
return os.path.dirname(pwd)
|
||||||
|
|
||||||
|
|
||||||
def ensure_attached_session(session):
|
def ensure_attached_session(monkeypatch, session):
|
||||||
for i in range(1, 11):
|
for i in range(1, 11):
|
||||||
|
|
||||||
|
# next try to monkey patch with raising.
|
||||||
|
try:
|
||||||
|
monkeypatch.setattr(builtins, "__xonsh__", session, raising=True)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if hasattr(builtins, "__xonsh__"):
|
||||||
|
break
|
||||||
|
# first try to monkey patch without raising.
|
||||||
|
try:
|
||||||
|
monkeypatch.setattr(builtins, "__xonsh__", session, raising=False)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if hasattr(builtins, "__xonsh__"):
|
||||||
|
break
|
||||||
|
# now just try to apply it
|
||||||
builtins.__xonsh__ = session
|
builtins.__xonsh__ = session
|
||||||
if hasattr(builtins, "__xonsh__"):
|
if hasattr(builtins, "__xonsh__"):
|
||||||
break
|
break
|
||||||
|
@ -56,11 +72,15 @@ def xonsh_execer(monkeypatch):
|
||||||
"xonsh.built_ins.load_builtins.__code__",
|
"xonsh.built_ins.load_builtins.__code__",
|
||||||
(lambda *args, **kwargs: None).__code__,
|
(lambda *args, **kwargs: None).__code__,
|
||||||
)
|
)
|
||||||
|
added_session = False
|
||||||
if not hasattr(builtins, "__xonsh__"):
|
if not hasattr(builtins, "__xonsh__"):
|
||||||
ensure_attached_session(XonshSession())
|
added_session = True
|
||||||
|
ensure_attached_session(monkeypatch, XonshSession())
|
||||||
execer = Execer(unload=False)
|
execer = Execer(unload=False)
|
||||||
builtins.__xonsh__.execer = execer
|
builtins.__xonsh__.execer = execer
|
||||||
return execer
|
yield execer
|
||||||
|
if added_session:
|
||||||
|
monkeypatch.delattr(builtins, "__xonsh__", raising=False)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -71,7 +91,7 @@ def monkeypatch_stderr(monkeypatch):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture
|
@pytest.fixture
|
||||||
def xonsh_events():
|
def xonsh_events():
|
||||||
yield events
|
yield events
|
||||||
for name, oldevent in vars(events).items():
|
for name, oldevent in vars(events).items():
|
||||||
|
@ -81,13 +101,13 @@ def xonsh_events():
|
||||||
setattr(events, name, newevent)
|
setattr(events, name, newevent)
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture
|
@pytest.fixture
|
||||||
def xonsh_builtins(xonsh_events):
|
def xonsh_builtins(monkeypatch, xonsh_events):
|
||||||
"""Mock out most of the builtins xonsh attributes."""
|
"""Mock out most of the builtins xonsh attributes."""
|
||||||
old_builtins = set(dir(builtins))
|
old_builtins = set(dir(builtins))
|
||||||
execer = getattr(getattr(builtins, "__xonsh__", None), "execer", None)
|
execer = getattr(getattr(builtins, "__xonsh__", None), "execer", None)
|
||||||
session = XonshSession(execer=execer, ctx={})
|
session = XonshSession(execer=execer, ctx={})
|
||||||
ensure_attached_session(session)
|
ensure_attached_session(monkeypatch, session)
|
||||||
builtins.__xonsh__.env = DummyEnv()
|
builtins.__xonsh__.env = DummyEnv()
|
||||||
if ON_WINDOWS:
|
if ON_WINDOWS:
|
||||||
builtins.__xonsh__.env["PATHEXT"] = [".EXE", ".BAT", ".CMD"]
|
builtins.__xonsh__.env["PATHEXT"] = [".EXE", ".BAT", ".CMD"]
|
||||||
|
@ -131,6 +151,7 @@ def xonsh_builtins(xonsh_events):
|
||||||
# be firing events on the global instance.
|
# be firing events on the global instance.
|
||||||
builtins.events = xonsh_events
|
builtins.events = xonsh_events
|
||||||
yield builtins
|
yield builtins
|
||||||
|
monkeypatch.delattr(builtins, "__xonsh__", raising=False)
|
||||||
for attr in set(dir(builtins)) - old_builtins:
|
for attr in set(dir(builtins)) - old_builtins:
|
||||||
if hasattr(builtins, attr):
|
if hasattr(builtins, attr):
|
||||||
delattr(builtins, attr)
|
delattr(builtins, attr)
|
||||||
|
|
|
@ -17,17 +17,19 @@ def cd(args, stdin=None):
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
ALIASES = Aliases(
|
def make_aliases():
|
||||||
{"o": ["omg", "lala"]},
|
ales = Aliases(
|
||||||
color_ls=["ls", "--color=true"],
|
{"o": ["omg", "lala"]},
|
||||||
ls="ls '- -'",
|
color_ls=["ls", "--color=true"],
|
||||||
cd=cd,
|
ls="ls '- -'",
|
||||||
indirect_cd="cd ..",
|
cd=cd,
|
||||||
)
|
indirect_cd="cd ..",
|
||||||
RAW = ALIASES._raw
|
)
|
||||||
|
return ales
|
||||||
|
|
||||||
|
|
||||||
def test_imports():
|
def test_imports(xonsh_execer, xonsh_builtins):
|
||||||
|
ales = make_aliases()
|
||||||
expected = {
|
expected = {
|
||||||
"o": ["omg", "lala"],
|
"o": ["omg", "lala"],
|
||||||
"ls": ["ls", "- -"],
|
"ls": ["ls", "- -"],
|
||||||
|
@ -35,22 +37,27 @@ def test_imports():
|
||||||
"cd": cd,
|
"cd": cd,
|
||||||
"indirect_cd": ["cd", ".."],
|
"indirect_cd": ["cd", ".."],
|
||||||
}
|
}
|
||||||
assert RAW == expected
|
raw = ales._raw
|
||||||
|
assert raw == expected
|
||||||
|
|
||||||
|
|
||||||
def test_eval_normal(xonsh_builtins):
|
def test_eval_normal(xonsh_execer, xonsh_builtins):
|
||||||
assert ALIASES.get("o") == ["omg", "lala"]
|
ales = make_aliases()
|
||||||
|
assert ales.get("o") == ["omg", "lala"]
|
||||||
|
|
||||||
|
|
||||||
def test_eval_self_reference(xonsh_builtins):
|
def test_eval_self_reference(xonsh_execer, xonsh_builtins):
|
||||||
assert ALIASES.get("ls") == ["ls", "- -"]
|
ales = make_aliases()
|
||||||
|
assert ales.get("ls") == ["ls", "- -"]
|
||||||
|
|
||||||
|
|
||||||
def test_eval_recursive(xonsh_builtins):
|
def test_eval_recursive(xonsh_execer, xonsh_builtins):
|
||||||
assert ALIASES.get("color_ls") == ["ls", "- -", "--color=true"]
|
ales = make_aliases()
|
||||||
|
assert ales.get("color_ls") == ["ls", "- -", "--color=true"]
|
||||||
|
|
||||||
|
|
||||||
@skip_if_on_windows
|
@skip_if_on_windows
|
||||||
def test_eval_recursive_callable_partial(xonsh_builtins):
|
def test_eval_recursive_callable_partial(xonsh_execer, xonsh_builtins):
|
||||||
|
ales = make_aliases()
|
||||||
xonsh_builtins.__xonsh__.env = Env(HOME=os.path.expanduser("~"))
|
xonsh_builtins.__xonsh__.env = Env(HOME=os.path.expanduser("~"))
|
||||||
assert ALIASES.get("indirect_cd")(["arg2", "arg3"]) == ["..", "arg2", "arg3"]
|
assert ales.get("indirect_cd")(["arg2", "arg3"]) == ["..", "arg2", "arg3"]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import ast as pyast
|
import ast as pyast
|
||||||
|
|
||||||
from xonsh import ast
|
from xonsh import ast
|
||||||
from xonsh.ast import Tuple, Name, Store, min_line, Call, BinOp, pdump
|
from xonsh.ast import Tuple, Name, Store, min_line, Call, BinOp, pdump, isexpression
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ def test_gather_load_store_names_tuple():
|
||||||
"l = 1",
|
"l = 1",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_multilline_num(line1):
|
def test_multilline_num(xonsh_execer, line1):
|
||||||
code = line1 + "\nls -l\n"
|
code = line1 + "\nls -l\n"
|
||||||
tree = check_parse(code)
|
tree = check_parse(code)
|
||||||
lsnode = tree.body[1]
|
lsnode = tree.body[1]
|
||||||
|
@ -115,10 +115,28 @@ def test_unmodified(inp):
|
||||||
|
|
||||||
assert nodes_equal(exp, obs)
|
assert nodes_equal(exp, obs)
|
||||||
|
|
||||||
@pytest.mark.parametrize("test_input", [
|
|
||||||
"echo; echo && echo\n",
|
@pytest.mark.parametrize(
|
||||||
"echo; echo && echo a\n",
|
"test_input",
|
||||||
"true && false && true\n",
|
["echo; echo && echo\n", "echo; echo && echo a\n", "true && false && true\n"],
|
||||||
])
|
)
|
||||||
def test_whitespace_subproc(test_input):
|
def test_whitespace_subproc(test_input):
|
||||||
assert check_parse(test_input)
|
assert check_parse(test_input)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"inp,exp",
|
||||||
|
[
|
||||||
|
("1+1", True),
|
||||||
|
("1+1;", True),
|
||||||
|
("1+1\n", True),
|
||||||
|
("1+1; 2+2", False),
|
||||||
|
("1+1; 2+2;", False),
|
||||||
|
("1+1; 2+2\n", False),
|
||||||
|
("1+1; 2+2;\n", False),
|
||||||
|
("x = 42", False),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_isexpression(xonsh_execer, inp, exp):
|
||||||
|
obs = isexpression(inp)
|
||||||
|
assert exp is obs
|
||||||
|
|
|
@ -37,7 +37,7 @@ pytestmark = pytest.mark.skipif(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def shares_setup(tmpdir_factory):
|
def shares_setup(tmpdir_factory):
|
||||||
"""create some shares to play with on current machine.
|
"""create some shares to play with on current machine.
|
||||||
|
|
||||||
|
@ -218,8 +218,8 @@ def test_uncpushd_push_base_push_rempath(xonsh_builtins):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# really? Need to cut-and-paste 2 flavors of this? yield_fixture requires yield in defined function body, not callee
|
# really? Need to cut-and-paste 2 flavors of this? fixture requires yield in defined function body, not callee
|
||||||
@pytest.yield_fixture()
|
@pytest.fixture()
|
||||||
def with_unc_check_enabled():
|
def with_unc_check_enabled():
|
||||||
if not ON_WINDOWS:
|
if not ON_WINDOWS:
|
||||||
return
|
return
|
||||||
|
@ -251,7 +251,7 @@ def with_unc_check_enabled():
|
||||||
winreg.CloseKey(key)
|
winreg.CloseKey(key)
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture()
|
@pytest.fixture()
|
||||||
def with_unc_check_disabled(): # just like the above, but value is 1 to *disable* unc check
|
def with_unc_check_disabled(): # just like the above, but value is 1 to *disable* unc check
|
||||||
if not ON_WINDOWS:
|
if not ON_WINDOWS:
|
||||||
return
|
return
|
||||||
|
|
|
@ -64,7 +64,7 @@ def test_parse_aliases():
|
||||||
"__XONSH_ALIAS_END__\n"
|
"__XONSH_ALIAS_END__\n"
|
||||||
"more filth"
|
"more filth"
|
||||||
)
|
)
|
||||||
obs = parse_aliases(s)
|
obs = parse_aliases(s, 'bash')
|
||||||
assert exp == obs
|
assert exp == obs
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ from xonsh.history.main import history_main, _xh_parse_args, construct_history
|
||||||
CMDS = ["ls", "cat hello kitty", "abc", "def", "touch me", "grep from me"]
|
CMDS = ["ls", "cat hello kitty", "abc", "def", "touch me", "grep from me"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture
|
@pytest.fixture
|
||||||
def hist():
|
def hist():
|
||||||
h = JsonHistory(
|
h = JsonHistory(
|
||||||
filename="xonsh-HISTORY-TEST.json", here="yup", sessionid="SESSIONID", gc=False
|
filename="xonsh-HISTORY-TEST.json", here="yup", sessionid="SESSIONID", gc=False
|
||||||
|
|
|
@ -10,7 +10,7 @@ from xonsh.history.main import history_main
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture
|
@pytest.fixture
|
||||||
def hist():
|
def hist():
|
||||||
h = SqliteHistory(
|
h = SqliteHistory(
|
||||||
filename="xonsh-HISTORY-TEST.sqlite", sessionid="SESSIONID", gc=False
|
filename="xonsh-HISTORY-TEST.sqlite", sessionid="SESSIONID", gc=False
|
||||||
|
|
|
@ -13,8 +13,8 @@ from xonsh.built_ins import unload_builtins
|
||||||
imphooks.install_import_hooks()
|
imphooks.install_import_hooks()
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def imp_env():
|
def imp_env(xonsh_builtins):
|
||||||
execer = Execer(unload=False)
|
execer = Execer(unload=False)
|
||||||
builtins.__xonsh__.env = Env({"PATH": [], "PATHEXT": []})
|
builtins.__xonsh__.env = Env({"PATH": [], "PATHEXT": []})
|
||||||
yield
|
yield
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from xonsh.lib.os import indir, rmtree
|
from xonsh.lib.os import indir, rmtree
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from tools import ON_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
def test_indir():
|
def test_indir():
|
||||||
|
if ON_WINDOWS:
|
||||||
|
pytest.skip("On Windows")
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
assert ![pwd].output.strip() != tmpdir
|
assert ![pwd].output.strip() != tmpdir
|
||||||
with indir(tmpdir):
|
with indir(tmpdir):
|
||||||
|
|
|
@ -4,10 +4,14 @@ import tempfile
|
||||||
from xonsh.lib.os import indir
|
from xonsh.lib.os import indir
|
||||||
from xonsh.lib.subprocess import run, check_call, check_output, CalledProcessError
|
from xonsh.lib.subprocess import run, check_call, check_output, CalledProcessError
|
||||||
|
|
||||||
from tools import skip_if_on_windows
|
import pytest
|
||||||
|
|
||||||
|
from tools import ON_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
def test_run():
|
def test_run():
|
||||||
|
if ON_WINDOWS:
|
||||||
|
pytest.skip("On Windows")
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
with indir(tmpdir):
|
with indir(tmpdir):
|
||||||
run(['touch', 'hello.txt'])
|
run(['touch', 'hello.txt'])
|
||||||
|
@ -19,6 +23,8 @@ def test_run():
|
||||||
|
|
||||||
|
|
||||||
def test_check_call():
|
def test_check_call():
|
||||||
|
if ON_WINDOWS:
|
||||||
|
pytest.skip("On Windows")
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
with indir(tmpdir):
|
with indir(tmpdir):
|
||||||
check_call(['touch', 'hello.txt'])
|
check_call(['touch', 'hello.txt'])
|
||||||
|
@ -29,8 +35,9 @@ def test_check_call():
|
||||||
assert 'tst_dir/hello.txt' in g`tst_dir/*.txt`
|
assert 'tst_dir/hello.txt' in g`tst_dir/*.txt`
|
||||||
|
|
||||||
|
|
||||||
@skip_if_on_windows
|
|
||||||
def test_check_call_raises():
|
def test_check_call_raises():
|
||||||
|
if ON_WINDOWS:
|
||||||
|
pytest.skip("On Windows")
|
||||||
try:
|
try:
|
||||||
check_call('false')
|
check_call('false')
|
||||||
got_raise = False
|
got_raise = False
|
||||||
|
@ -40,6 +47,8 @@ def test_check_call_raises():
|
||||||
|
|
||||||
|
|
||||||
def test_check_output():
|
def test_check_output():
|
||||||
|
if ON_WINDOWS:
|
||||||
|
pytest.skip("On Windows")
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
with indir(tmpdir):
|
with indir(tmpdir):
|
||||||
check_call(['touch', 'hello.txt'])
|
check_call(['touch', 'hello.txt'])
|
||||||
|
@ -49,4 +58,3 @@ def test_check_output():
|
||||||
p = check_output(['touch', 'hello.txt'], cwd='tst_dir')
|
p = check_output(['touch', 'hello.txt'], cwd='tst_dir')
|
||||||
assert p.decode('utf-8') == ''
|
assert p.decode('utf-8') == ''
|
||||||
assert 'tst_dir/hello.txt' in g`tst_dir/*.txt`
|
assert 'tst_dir/hello.txt' in g`tst_dir/*.txt`
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,12 @@ from tools import skip_if_on_windows
|
||||||
|
|
||||||
from xonsh.platform import ON_WINDOWS
|
from xonsh.platform import ON_WINDOWS
|
||||||
from xonsh.built_ins import load_builtins, unload_builtins
|
from xonsh.built_ins import load_builtins, unload_builtins
|
||||||
|
from xonsh.execer import Execer
|
||||||
from xonsh.pyghooks import XonshLexer
|
from xonsh.pyghooks import XonshLexer
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def load_command_cache():
|
def load_command_cache(xonsh_builtins):
|
||||||
load_builtins()
|
load_builtins()
|
||||||
if ON_WINDOWS:
|
if ON_WINDOWS:
|
||||||
for key in ("cd", "bash"):
|
for key in ("cd", "bash"):
|
||||||
|
@ -58,10 +59,12 @@ def test_bin_ls():
|
||||||
check_token("/bin/ls -al", [(Name.Builtin, "/bin/ls")])
|
check_token("/bin/ls -al", [(Name.Builtin, "/bin/ls")])
|
||||||
|
|
||||||
|
|
||||||
|
@skip_if_on_windows
|
||||||
def test_py_print():
|
def test_py_print():
|
||||||
check_token('print("hello")', [(Keyword, "print"), (String.Double, "hello")])
|
check_token('print("hello")', [(Keyword, "print"), (String.Double, "hello")])
|
||||||
|
|
||||||
|
|
||||||
|
@skip_if_on_windows
|
||||||
def test_invalid_cmd():
|
def test_invalid_cmd():
|
||||||
check_token("non-existance-cmd -al", [(Name, "non")]) # parse as python
|
check_token("non-existance-cmd -al", [(Name, "non")]) # parse as python
|
||||||
check_token(
|
check_token(
|
||||||
|
@ -71,6 +74,7 @@ def test_invalid_cmd():
|
||||||
check_token("(1, )", [(Punctuation, "("), (Number.Integer, "1")])
|
check_token("(1, )", [(Punctuation, "("), (Number.Integer, "1")])
|
||||||
|
|
||||||
|
|
||||||
|
@skip_if_on_windows
|
||||||
def test_multi_cmd():
|
def test_multi_cmd():
|
||||||
check_token(
|
check_token(
|
||||||
"cd && cd", [(Name.Builtin, "cd"), (Operator, "&&"), (Name.Builtin, "cd")]
|
"cd && cd", [(Name.Builtin, "cd"), (Operator, "&&"), (Name.Builtin, "cd")]
|
||||||
|
@ -81,6 +85,7 @@ def test_multi_cmd():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@skip_if_on_windows
|
||||||
def test_nested():
|
def test_nested():
|
||||||
check_token(
|
check_token(
|
||||||
'echo @("hello")',
|
'echo @("hello")',
|
||||||
|
@ -117,6 +122,7 @@ def test_nested():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@skip_if_on_windows
|
||||||
def test_path(tmpdir):
|
def test_path(tmpdir):
|
||||||
test_dir = str(tmpdir.mkdir("xonsh-test-highlight-path"))
|
test_dir = str(tmpdir.mkdir("xonsh-test-highlight-path"))
|
||||||
check_token(
|
check_token(
|
||||||
|
@ -132,10 +138,12 @@ def test_path(tmpdir):
|
||||||
check_token(test_dir, [(Name.Constant, test_dir)])
|
check_token(test_dir, [(Name.Constant, test_dir)])
|
||||||
|
|
||||||
|
|
||||||
|
@skip_if_on_windows
|
||||||
def test_subproc_args():
|
def test_subproc_args():
|
||||||
check_token("cd 192.168.0.1", [(Text, "192.168.0.1")])
|
check_token("cd 192.168.0.1", [(Text, "192.168.0.1")])
|
||||||
|
|
||||||
|
|
||||||
|
@skip_if_on_windows
|
||||||
def test_backtick():
|
def test_backtick():
|
||||||
check_token(
|
check_token(
|
||||||
r"echo g`.*\w+`",
|
r"echo g`.*\w+`",
|
||||||
|
@ -149,6 +157,7 @@ def test_backtick():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@skip_if_on_windows
|
||||||
def test_macro():
|
def test_macro():
|
||||||
check_token(
|
check_token(
|
||||||
r"g!(42, *, 65)",
|
r"g!(42, *, 65)",
|
||||||
|
|
|
@ -18,7 +18,7 @@ from tools import DummyEnv, skip_if_lt_ptk2
|
||||||
Context = namedtuple("Context", ["indent", "buffer", "accept", "cli", "cr"])
|
Context = namedtuple("Context", ["indent", "buffer", "accept", "cli", "cr"])
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def ctx():
|
def ctx():
|
||||||
"""Context in which the ptk multiline functionality will be tested."""
|
"""Context in which the ptk multiline functionality will be tested."""
|
||||||
builtins.__xonsh__ = XonshSession()
|
builtins.__xonsh__ = XonshSession()
|
||||||
|
|
|
@ -15,7 +15,7 @@ from tools import skip_if_on_darwin
|
||||||
HISTDIR = os.path.join(os.path.dirname(__file__), "histories")
|
HISTDIR = os.path.join(os.path.dirname(__file__), "histories")
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(scope="module", autouse=True)
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
def ctx():
|
def ctx():
|
||||||
"""Create a global Shell instance to use in all the test."""
|
"""Create a global Shell instance to use in all the test."""
|
||||||
ctx = {"PATH": []}
|
ctx = {"PATH": []}
|
||||||
|
|
|
@ -64,6 +64,7 @@ from xonsh.tools import (
|
||||||
is_balanced,
|
is_balanced,
|
||||||
subexpr_before_unbalanced,
|
subexpr_before_unbalanced,
|
||||||
swap_values,
|
swap_values,
|
||||||
|
get_line_continuation,
|
||||||
get_logical_line,
|
get_logical_line,
|
||||||
replace_logical_line,
|
replace_logical_line,
|
||||||
check_quotes,
|
check_quotes,
|
||||||
|
@ -521,7 +522,8 @@ def test_replace_logical_line(src, idx, exp_line, exp_n):
|
||||||
idx -= 1
|
idx -= 1
|
||||||
replace_logical_line(lines, logical, idx, exp_n)
|
replace_logical_line(lines, logical, idx, exp_n)
|
||||||
exp = src.replace("\\\n", "").strip()
|
exp = src.replace("\\\n", "").strip()
|
||||||
obs = "\n".join(lines).replace("\\\n", "").strip()
|
lc = get_line_continuation() + "\n"
|
||||||
|
obs = "\n".join(lines).replace(lc, "").strip()
|
||||||
assert exp == obs
|
assert exp == obs
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ def test_load_xontrib_metadata():
|
||||||
xontrib_metadata()
|
xontrib_metadata()
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture
|
@pytest.fixture
|
||||||
def tmpmod(tmpdir):
|
def tmpmod(tmpdir):
|
||||||
"""
|
"""
|
||||||
Same as tmpdir but also adds/removes it to the front of sys.path.
|
Same as tmpdir but also adds/removes it to the front of sys.path.
|
||||||
|
|
|
@ -30,6 +30,9 @@ ON_CONDA = True in [
|
||||||
conda in pytest.__file__.lower() for conda in ["conda", "anaconda", "miniconda"]
|
conda in pytest.__file__.lower() for conda in ["conda", "anaconda", "miniconda"]
|
||||||
]
|
]
|
||||||
ON_TRAVIS = "TRAVIS" in os.environ and "CI" in os.environ
|
ON_TRAVIS = "TRAVIS" in os.environ and "CI" in os.environ
|
||||||
|
ON_AZURE_PIPELINES = os.environ.get("TF_BUILD", "") == "True"
|
||||||
|
print("ON_AZURE_PIPELINES", repr(ON_AZURE_PIPELINES))
|
||||||
|
print("os.environ['TF_BUILD']", repr(os.environ.get("TF_BUILD", "")))
|
||||||
TEST_DIR = os.path.dirname(__file__)
|
TEST_DIR = os.path.dirname(__file__)
|
||||||
|
|
||||||
# pytest skip decorators
|
# pytest skip decorators
|
||||||
|
@ -48,6 +51,8 @@ skip_if_on_msys = pytest.mark.skipif(
|
||||||
|
|
||||||
skip_if_on_windows = pytest.mark.skipif(ON_WINDOWS, reason="Unix stuff")
|
skip_if_on_windows = pytest.mark.skipif(ON_WINDOWS, reason="Unix stuff")
|
||||||
|
|
||||||
|
skip_if_on_azure_pipelines = pytest.mark.skipif(ON_AZURE_PIPELINES, reason="not suitable for azure")
|
||||||
|
|
||||||
skip_if_on_unix = pytest.mark.skipif(not ON_WINDOWS, reason="Windows stuff")
|
skip_if_on_unix = pytest.mark.skipif(not ON_WINDOWS, reason="Windows stuff")
|
||||||
|
|
||||||
skip_if_on_darwin = pytest.mark.skipif(ON_DARWIN, reason="not Mac friendly")
|
skip_if_on_darwin = pytest.mark.skipif(ON_DARWIN, reason="not Mac friendly")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
__version__ = "0.8.3"
|
__version__ = "0.8.5"
|
||||||
|
|
||||||
|
|
||||||
# amalgamate exclude jupyter_kernel parser_table parser_test_table pyghooks
|
# amalgamate exclude jupyter_kernel parser_table parser_test_table pyghooks
|
||||||
|
@ -86,6 +86,8 @@ else:
|
||||||
_sys.modules["xonsh.tracer"] = __amalgam__
|
_sys.modules["xonsh.tracer"] = __amalgam__
|
||||||
aliases = __amalgam__
|
aliases = __amalgam__
|
||||||
_sys.modules["xonsh.aliases"] = __amalgam__
|
_sys.modules["xonsh.aliases"] = __amalgam__
|
||||||
|
dumb_shell = __amalgam__
|
||||||
|
_sys.modules["xonsh.dumb_shell"] = __amalgam__
|
||||||
built_ins = __amalgam__
|
built_ins = __amalgam__
|
||||||
_sys.modules["xonsh.built_ins"] = __amalgam__
|
_sys.modules["xonsh.built_ins"] = __amalgam__
|
||||||
execer = __amalgam__
|
execer = __amalgam__
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Aliases for the xonsh shell."""
|
"""Aliases for the xonsh shell."""
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import shlex
|
|
||||||
import inspect
|
import inspect
|
||||||
import argparse
|
import argparse
|
||||||
import builtins
|
import builtins
|
||||||
|
@ -24,14 +24,26 @@ from xonsh.platform import (
|
||||||
from xonsh.tools import unthreadable, print_color
|
from xonsh.tools import unthreadable, print_color
|
||||||
from xonsh.replay import replay_main
|
from xonsh.replay import replay_main
|
||||||
from xonsh.timings import timeit_alias
|
from xonsh.timings import timeit_alias
|
||||||
from xonsh.tools import argvquote, escape_windows_cmd_string, to_bool, swap_values
|
from xonsh.tools import (
|
||||||
|
argvquote,
|
||||||
|
escape_windows_cmd_string,
|
||||||
|
to_bool,
|
||||||
|
swap_values,
|
||||||
|
strip_simple_quotes,
|
||||||
|
)
|
||||||
from xonsh.xontribs import xontribs_main
|
from xonsh.xontribs import xontribs_main
|
||||||
|
from xonsh.ast import isexpression
|
||||||
|
|
||||||
import xonsh.completers._aliases as xca
|
import xonsh.completers._aliases as xca
|
||||||
import xonsh.history.main as xhm
|
import xonsh.history.main as xhm
|
||||||
import xonsh.xoreutils.which as xxw
|
import xonsh.xoreutils.which as xxw
|
||||||
|
|
||||||
|
|
||||||
|
@lazyobject
|
||||||
|
def SUB_EXEC_ALIAS_RE():
|
||||||
|
return re.compile(r"@\(|\$\(|!\(|\$\[|!\[")
|
||||||
|
|
||||||
|
|
||||||
class Aliases(cabc.MutableMapping):
|
class Aliases(cabc.MutableMapping):
|
||||||
"""Represents a location to hold and look up aliases."""
|
"""Represents a location to hold and look up aliases."""
|
||||||
|
|
||||||
|
@ -115,7 +127,17 @@ class Aliases(cabc.MutableMapping):
|
||||||
|
|
||||||
def __setitem__(self, key, val):
|
def __setitem__(self, key, val):
|
||||||
if isinstance(val, str):
|
if isinstance(val, str):
|
||||||
self._raw[key] = shlex.split(val)
|
f = "<exec-alias:" + key + ">"
|
||||||
|
if SUB_EXEC_ALIAS_RE.search(val) is not None:
|
||||||
|
# We have a sub-command, e.g. $(cmd), to evaluate
|
||||||
|
self._raw[key] = ExecAlias(val, filename=f)
|
||||||
|
elif isexpression(val):
|
||||||
|
# expansion substitution
|
||||||
|
lexer = builtins.__xonsh__.execer.parser.lexer
|
||||||
|
self._raw[key] = list(map(strip_simple_quotes, lexer.split(val)))
|
||||||
|
else:
|
||||||
|
# need to exec alias
|
||||||
|
self._raw[key] = ExecAlias(val, filename=f)
|
||||||
else:
|
else:
|
||||||
self._raw[key] = val
|
self._raw[key] = val
|
||||||
|
|
||||||
|
@ -150,6 +172,37 @@ class Aliases(cabc.MutableMapping):
|
||||||
p.pretty(dict(self))
|
p.pretty(dict(self))
|
||||||
|
|
||||||
|
|
||||||
|
class ExecAlias:
|
||||||
|
"""Provides a callable alias for xonsh source code."""
|
||||||
|
|
||||||
|
def __init__(self, src, filename="<exec-alias>"):
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
src : str
|
||||||
|
Source code that will be
|
||||||
|
"""
|
||||||
|
self.src = src if src.endswith("\n") else src + "\n"
|
||||||
|
self.filename = filename
|
||||||
|
|
||||||
|
def __call__(
|
||||||
|
self, args, stdin=None, stdout=None, stderr=None, spec=None, stack=None
|
||||||
|
):
|
||||||
|
execer = builtins.__xonsh__.execer
|
||||||
|
frame = stack[0][0] # execute as though we are at the call site
|
||||||
|
execer.exec(
|
||||||
|
self.src, glbs=frame.f_globals, locs=frame.f_locals, filename=self.filename
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "ExecAlias({0!r}, filename={1!r})".format(self.src, self.filename)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Actual aliases below
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
def xonsh_exit(args, stdin=None):
|
def xonsh_exit(args, stdin=None):
|
||||||
"""Sends signal to exit shell."""
|
"""Sends signal to exit shell."""
|
||||||
if not clean_jobs():
|
if not clean_jobs():
|
||||||
|
|
21
xonsh/ast.py
21
xonsh/ast.py
|
@ -3,6 +3,7 @@
|
||||||
# These are imported into our module namespace for the benefit of parser.py.
|
# These are imported into our module namespace for the benefit of parser.py.
|
||||||
# pylint: disable=unused-import
|
# pylint: disable=unused-import
|
||||||
import sys
|
import sys
|
||||||
|
import builtins
|
||||||
from ast import (
|
from ast import (
|
||||||
Module,
|
Module,
|
||||||
Num,
|
Num,
|
||||||
|
@ -302,6 +303,26 @@ def isdescendable(node):
|
||||||
return isinstance(node, (UnaryOp, BoolOp))
|
return isinstance(node, (UnaryOp, BoolOp))
|
||||||
|
|
||||||
|
|
||||||
|
def isexpression(node, ctx=None, *args, **kwargs):
|
||||||
|
"""Determines whether a node (or code string) is an expression, and
|
||||||
|
does not contain any statements. The execution context (ctx) and
|
||||||
|
other args and kwargs are passed down to the parser, as needed.
|
||||||
|
"""
|
||||||
|
# parse string to AST
|
||||||
|
if isinstance(node, str):
|
||||||
|
node = node if node.endswith("\n") else node + "\n"
|
||||||
|
ctx = builtins.__xonsh__.ctx if ctx is None else ctx
|
||||||
|
node = builtins.__xonsh__.execer.parse(node, ctx, *args, **kwargs)
|
||||||
|
# determin if expresission-like enough
|
||||||
|
if isinstance(node, (Expr, Expression)):
|
||||||
|
isexpr = True
|
||||||
|
elif isinstance(node, Module) and len(node.body) == 1:
|
||||||
|
isexpr = isinstance(node.body[0], (Expr, Expression))
|
||||||
|
else:
|
||||||
|
isexpr = False
|
||||||
|
return isexpr
|
||||||
|
|
||||||
|
|
||||||
class CtxAwareTransformer(NodeTransformer):
|
class CtxAwareTransformer(NodeTransformer):
|
||||||
"""Transforms a xonsh AST based to use subprocess calls when
|
"""Transforms a xonsh AST based to use subprocess calls when
|
||||||
the first name in an expression statement is not known in the context.
|
the first name in an expression statement is not known in the context.
|
||||||
|
|
12
xonsh/dumb_shell.py
Normal file
12
xonsh/dumb_shell.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
"""A dumb shell for when $TERM == 'dumb', which usually happens in emacs."""
|
||||||
|
import builtins
|
||||||
|
|
||||||
|
from xonsh.readline_shell import ReadlineShell
|
||||||
|
|
||||||
|
|
||||||
|
class DumbShell(ReadlineShell):
|
||||||
|
"""A dumb shell for when $TERM == 'dumb', which usually happens in emacs."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
builtins.__xonsh__.env["XONSH_COLOR_STYLE"] = "emacs"
|
||||||
|
super().__init__(*args, **kwargs)
|
|
@ -298,7 +298,7 @@ def foreign_shell_data(
|
||||||
if use_tmpfile:
|
if use_tmpfile:
|
||||||
os.remove(tmpfile.name)
|
os.remove(tmpfile.name)
|
||||||
env = parse_env(s)
|
env = parse_env(s)
|
||||||
aliases = parse_aliases(s)
|
aliases = parse_aliases(s, shell=shell, sourcer=sourcer, extra_args=extra_args)
|
||||||
funcs = parse_funcs(s, shell=shell, sourcer=sourcer, extra_args=extra_args)
|
funcs = parse_funcs(s, shell=shell, sourcer=sourcer, extra_args=extra_args)
|
||||||
aliases.update(funcs)
|
aliases.update(funcs)
|
||||||
return env, aliases
|
return env, aliases
|
||||||
|
@ -332,7 +332,12 @@ def ALIAS_RE():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def parse_aliases(s):
|
@lazyobject
|
||||||
|
def FS_EXEC_ALIAS_RE():
|
||||||
|
return re.compile(r";|`|\$\(")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_aliases(s, shell, sourcer=None, extra_args=()):
|
||||||
"""Parses the aliases portion of string into a dict."""
|
"""Parses the aliases portion of string into a dict."""
|
||||||
m = ALIAS_RE.search(s)
|
m = ALIAS_RE.search(s)
|
||||||
if m is None:
|
if m is None:
|
||||||
|
@ -352,7 +357,20 @@ def parse_aliases(s):
|
||||||
# strip one single quote at the start and end of value
|
# strip one single quote at the start and end of value
|
||||||
if value[0] == "'" and value[-1] == "'":
|
if value[0] == "'" and value[-1] == "'":
|
||||||
value = value[1:-1]
|
value = value[1:-1]
|
||||||
value = shlex.split(value)
|
# now compute actual alias
|
||||||
|
if FS_EXEC_ALIAS_RE.search(value) is None:
|
||||||
|
# simple list of args alias
|
||||||
|
value = shlex.split(value)
|
||||||
|
else:
|
||||||
|
# alias is more complex, use ExecAlias, but via shell
|
||||||
|
filename = "<foreign-shell-exec-alias:" + key + ">"
|
||||||
|
value = ForeignShellExecAlias(
|
||||||
|
src=value,
|
||||||
|
shell=shell,
|
||||||
|
filename=filename,
|
||||||
|
sourcer=sourcer,
|
||||||
|
extra_args=extra_args,
|
||||||
|
)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
'could not parse alias "{0}": {1!r}'.format(key, exc), RuntimeWarning
|
'could not parse alias "{0}": {1!r}'.format(key, exc), RuntimeWarning
|
||||||
|
@ -400,7 +418,7 @@ def parse_funcs(s, shell, sourcer=None, extra_args=()):
|
||||||
if not os.path.isabs(filename):
|
if not os.path.isabs(filename):
|
||||||
filename = os.path.abspath(filename)
|
filename = os.path.abspath(filename)
|
||||||
wrapper = ForeignShellFunctionAlias(
|
wrapper = ForeignShellFunctionAlias(
|
||||||
name=funcname,
|
funcname=funcname,
|
||||||
shell=shell,
|
shell=shell,
|
||||||
sourcer=sourcer,
|
sourcer=sourcer,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
|
@ -410,19 +428,17 @@ def parse_funcs(s, shell, sourcer=None, extra_args=()):
|
||||||
return funcs
|
return funcs
|
||||||
|
|
||||||
|
|
||||||
class ForeignShellFunctionAlias(object):
|
class ForeignShellBaseAlias(object):
|
||||||
"""This class is responsible for calling foreign shell functions as if
|
"""This class is responsible for calling foreign shell functions as if
|
||||||
they were aliases. This does not currently support taking stdin.
|
they were aliases. This does not currently support taking stdin.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
INPUT = '{sourcer} "{filename}"\n' "{funcname} {args}\n"
|
INPUT = "echo ForeignShellBaseAlias {shell} {filename} {args}\n"
|
||||||
|
|
||||||
def __init__(self, name, shell, filename, sourcer=None, extra_args=()):
|
def __init__(self, shell, filename, sourcer=None, extra_args=()):
|
||||||
"""
|
"""
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
name : str
|
|
||||||
function name
|
|
||||||
shell : str
|
shell : str
|
||||||
Name or path to shell
|
Name or path to shell
|
||||||
filename : str
|
filename : str
|
||||||
|
@ -433,36 +449,29 @@ class ForeignShellFunctionAlias(object):
|
||||||
Additional command line options to pass into the shell.
|
Additional command line options to pass into the shell.
|
||||||
"""
|
"""
|
||||||
sourcer = DEFAULT_SOURCERS.get(shell, "source") if sourcer is None else sourcer
|
sourcer = DEFAULT_SOURCERS.get(shell, "source") if sourcer is None else sourcer
|
||||||
self.name = name
|
|
||||||
self.shell = shell
|
self.shell = shell
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.sourcer = sourcer
|
self.sourcer = sourcer
|
||||||
self.extra_args = extra_args
|
self.extra_args = extra_args
|
||||||
|
|
||||||
def __eq__(self, other):
|
def _input_kwargs(self):
|
||||||
if (
|
return {
|
||||||
not hasattr(other, "name")
|
"shell": self.shell,
|
||||||
or not hasattr(other, "filename")
|
"filename": self.filename,
|
||||||
or not hasattr(other, "sourcer")
|
"sourcer": self.sourcer,
|
||||||
or not hasattr(other, "exta_args")
|
"extra_args": self.extra_args,
|
||||||
):
|
}
|
||||||
return NotImplemented
|
|
||||||
return (
|
|
||||||
(self.name == other.name)
|
|
||||||
and (self.shell == other.shell)
|
|
||||||
and (self.filename == other.filename)
|
|
||||||
and (self.sourcer == other.sourcer)
|
|
||||||
and (self.extra_args == other.extra_args)
|
|
||||||
)
|
|
||||||
|
|
||||||
def __call__(self, args, stdin=None):
|
def __eq__(self, other):
|
||||||
|
if not hasattr(other, "_input_kwargs") or not callable(other._input_kwargs):
|
||||||
|
return NotImplemented
|
||||||
|
return self._input_kwargs() == other._input_kwargs()
|
||||||
|
|
||||||
|
def __call__(
|
||||||
|
self, args, stdin=None, stdout=None, stderr=None, spec=None, stack=None
|
||||||
|
):
|
||||||
args, streaming = self._is_streaming(args)
|
args, streaming = self._is_streaming(args)
|
||||||
input = self.INPUT.format(
|
input = self.INPUT.format(args=" ".join(args), **self._input_kwargs())
|
||||||
sourcer=self.sourcer,
|
|
||||||
filename=self.filename,
|
|
||||||
funcname=self.name,
|
|
||||||
args=" ".join(args),
|
|
||||||
)
|
|
||||||
cmd = [self.shell] + list(self.extra_args) + ["-c", input]
|
cmd = [self.shell] + list(self.extra_args) + ["-c", input]
|
||||||
env = builtins.__xonsh__.env
|
env = builtins.__xonsh__.env
|
||||||
denv = env.detype()
|
denv = env.detype()
|
||||||
|
@ -478,7 +487,21 @@ class ForeignShellFunctionAlias(object):
|
||||||
out = out.replace("\r\n", "\n")
|
out = out.replace("\r\n", "\n")
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def _is_streaming(self, args):
|
def __repr__(self):
|
||||||
|
return (
|
||||||
|
self.__class__.__name__
|
||||||
|
+ "("
|
||||||
|
+ ", ".join(
|
||||||
|
[
|
||||||
|
"{k}={v!r}".format(k=k, v=v)
|
||||||
|
for k, v in sorted(self._input_kwargs().items())
|
||||||
|
]
|
||||||
|
)
|
||||||
|
+ ")"
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_streaming(args):
|
||||||
"""Test and modify args if --xonsh-stream is present."""
|
"""Test and modify args if --xonsh-stream is present."""
|
||||||
if "--xonsh-stream" not in args:
|
if "--xonsh-stream" not in args:
|
||||||
return args, False
|
return args, False
|
||||||
|
@ -487,6 +510,77 @@ class ForeignShellFunctionAlias(object):
|
||||||
return args, True
|
return args, True
|
||||||
|
|
||||||
|
|
||||||
|
class ForeignShellFunctionAlias(ForeignShellBaseAlias):
|
||||||
|
"""This class is responsible for calling foreign shell functions as if
|
||||||
|
they were aliases. This does not currently support taking stdin.
|
||||||
|
"""
|
||||||
|
|
||||||
|
INPUT = '{sourcer} "{filename}"\n' "{funcname} {args}\n"
|
||||||
|
|
||||||
|
def __init__(self, funcname, shell, filename, sourcer=None, extra_args=()):
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
funcname : str
|
||||||
|
function name
|
||||||
|
shell : str
|
||||||
|
Name or path to shell
|
||||||
|
filename : str
|
||||||
|
Where the function is defined, path to source.
|
||||||
|
sourcer : str or None, optional
|
||||||
|
Command to source foreign files with.
|
||||||
|
extra_args : tuple of str, optional
|
||||||
|
Additional command line options to pass into the shell.
|
||||||
|
"""
|
||||||
|
super().__init__(
|
||||||
|
shell=shell, filename=filename, sourcer=sourcer, extra_args=extra_args
|
||||||
|
)
|
||||||
|
self.funcname = funcname
|
||||||
|
|
||||||
|
def _input_kwargs(self):
|
||||||
|
inp = super()._input_kwargs()
|
||||||
|
inp["funcname"] = self.funcname
|
||||||
|
return inp
|
||||||
|
|
||||||
|
|
||||||
|
class ForeignShellExecAlias(ForeignShellBaseAlias):
|
||||||
|
"""Provides a callable alias for source code in a foreign shell."""
|
||||||
|
|
||||||
|
INPUT = "{src} {args}\n"
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
src,
|
||||||
|
shell,
|
||||||
|
filename="<foreign-shell-exec-alias>",
|
||||||
|
sourcer=None,
|
||||||
|
extra_args=(),
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
src : str
|
||||||
|
Source code in the shell language
|
||||||
|
shell : str
|
||||||
|
Name or path to shell
|
||||||
|
filename : str
|
||||||
|
Where the function is defined, path to source.
|
||||||
|
sourcer : str or None, optional
|
||||||
|
Command to source foreign files with.
|
||||||
|
extra_args : tuple of str, optional
|
||||||
|
Additional command line options to pass into the shell.
|
||||||
|
"""
|
||||||
|
super().__init__(
|
||||||
|
shell=shell, filename=filename, sourcer=sourcer, extra_args=extra_args
|
||||||
|
)
|
||||||
|
self.src = src.strip()
|
||||||
|
|
||||||
|
def _input_kwargs(self):
|
||||||
|
inp = super()._input_kwargs()
|
||||||
|
inp["src"] = self.src
|
||||||
|
return inp
|
||||||
|
|
||||||
|
|
||||||
@lazyobject
|
@lazyobject
|
||||||
def VALID_SHELL_PARAMS():
|
def VALID_SHELL_PARAMS():
|
||||||
return frozenset(
|
return frozenset(
|
||||||
|
|
|
@ -257,7 +257,8 @@ def _pprint_displayhook(value):
|
||||||
printed_val = repr(value)
|
printed_val = repr(value)
|
||||||
if HAS_PYGMENTS and env.get("COLOR_RESULTS"):
|
if HAS_PYGMENTS and env.get("COLOR_RESULTS"):
|
||||||
tokens = list(pygments.lex(printed_val, lexer=pyghooks.XonshLexer()))
|
tokens = list(pygments.lex(printed_val, lexer=pyghooks.XonshLexer()))
|
||||||
print_color(tokens)
|
end = "" if env.get("SHELL_TYPE") == "prompt_toolkit2" else "\n"
|
||||||
|
print_color(tokens, end=end)
|
||||||
else:
|
else:
|
||||||
print(printed_val) # black & white case
|
print(printed_val) # black & white case
|
||||||
builtins._ = value
|
builtins._ = value
|
||||||
|
|
|
@ -194,7 +194,9 @@ def ptk_below_max_supported():
|
||||||
|
|
||||||
@functools.lru_cache(1)
|
@functools.lru_cache(1)
|
||||||
def best_shell_type():
|
def best_shell_type():
|
||||||
if ON_WINDOWS or has_prompt_toolkit():
|
if builtins.__xonsh__.env.get("TERM", "") == "dumb":
|
||||||
|
return "dumb"
|
||||||
|
elif ON_WINDOWS or has_prompt_toolkit():
|
||||||
return "prompt_toolkit"
|
return "prompt_toolkit"
|
||||||
else:
|
else:
|
||||||
return "readline"
|
return "readline"
|
||||||
|
|
|
@ -148,7 +148,7 @@ def ctrl_d_condition():
|
||||||
empty.
|
empty.
|
||||||
"""
|
"""
|
||||||
if builtins.__xonsh__.env.get("IGNOREEOF"):
|
if builtins.__xonsh__.env.get("IGNOREEOF"):
|
||||||
raise EOFError
|
return False
|
||||||
else:
|
else:
|
||||||
app = get_app()
|
app = get_app()
|
||||||
buffer_name = app.current_buffer.name
|
buffer_name = app.current_buffer.name
|
||||||
|
|
|
@ -1431,7 +1431,7 @@ def XonshTerminal256Formatter():
|
||||||
ptk_version_info()
|
ptk_version_info()
|
||||||
and ptk_version_info() > (2, 0)
|
and ptk_version_info() > (2, 0)
|
||||||
and pygments_version_info()
|
and pygments_version_info()
|
||||||
and (2, 2) <= pygments_version_info() < (2, 3)
|
and (2, 2, 0) <= pygments_version_info() <= (2, 3, 0)
|
||||||
):
|
):
|
||||||
# Monky patch pygments' dict of console codes
|
# Monky patch pygments' dict of console codes
|
||||||
# with the new color names used by PTK2
|
# with the new color names used by PTK2
|
||||||
|
|
|
@ -119,6 +119,8 @@ class Shell(object):
|
||||||
shell_type_aliases = {
|
shell_type_aliases = {
|
||||||
"b": "best",
|
"b": "best",
|
||||||
"best": "best",
|
"best": "best",
|
||||||
|
"d": "dumb",
|
||||||
|
"dumb": "dumb",
|
||||||
"ptk": "prompt_toolkit",
|
"ptk": "prompt_toolkit",
|
||||||
"ptk1": "prompt_toolkit1",
|
"ptk1": "prompt_toolkit1",
|
||||||
"ptk2": "prompt_toolkit2",
|
"ptk2": "prompt_toolkit2",
|
||||||
|
@ -166,6 +168,8 @@ class Shell(object):
|
||||||
shell_type = self.shell_type_aliases.get(shell_type, shell_type)
|
shell_type = self.shell_type_aliases.get(shell_type, shell_type)
|
||||||
if shell_type == "best" or shell_type is None:
|
if shell_type == "best" or shell_type is None:
|
||||||
shell_type = best_shell_type()
|
shell_type = best_shell_type()
|
||||||
|
elif env.get("TERM", "") == "dumb":
|
||||||
|
shell_type = "dumb"
|
||||||
elif shell_type == "random":
|
elif shell_type == "random":
|
||||||
shell_type = random.choice(("readline", "prompt_toolkit"))
|
shell_type = random.choice(("readline", "prompt_toolkit"))
|
||||||
if shell_type == "prompt_toolkit":
|
if shell_type == "prompt_toolkit":
|
||||||
|
@ -195,6 +199,8 @@ class Shell(object):
|
||||||
from xonsh.readline_shell import ReadlineShell as shell_class
|
from xonsh.readline_shell import ReadlineShell as shell_class
|
||||||
elif shell_type == "jupyter":
|
elif shell_type == "jupyter":
|
||||||
from xonsh.jupyter_shell import JupyterShell as shell_class
|
from xonsh.jupyter_shell import JupyterShell as shell_class
|
||||||
|
elif shell_type == "dumb":
|
||||||
|
from xonsh.dumb_shell import DumbShell as shell_class
|
||||||
else:
|
else:
|
||||||
raise XonshError("{} is not recognized as a shell type".format(shell_type))
|
raise XonshError("{} is not recognized as a shell type".format(shell_type))
|
||||||
self.shell = shell_class(execer=self.execer, ctx=self.ctx, **kwargs)
|
self.shell = shell_class(execer=self.execer, ctx=self.ctx, **kwargs)
|
||||||
|
|
|
@ -1979,6 +1979,38 @@ def RE_COMPLETE_STRING():
|
||||||
return re.compile(ptrn, re.DOTALL)
|
return re.compile(ptrn, re.DOTALL)
|
||||||
|
|
||||||
|
|
||||||
|
def strip_simple_quotes(s):
|
||||||
|
"""Gets rid of single quotes, double quotes, single triple quotes, and
|
||||||
|
single double quotes from a string, if present front and back of a string.
|
||||||
|
Otherwiswe, does nothing.
|
||||||
|
"""
|
||||||
|
starts_single = s.startswith("'")
|
||||||
|
starts_double = s.startswith('"')
|
||||||
|
if not starts_single and not starts_double:
|
||||||
|
return s
|
||||||
|
elif starts_single:
|
||||||
|
ends_single = s.endswith("'")
|
||||||
|
if not ends_single:
|
||||||
|
return s
|
||||||
|
elif s.startswith("'''") and s.endswith("'''") and len(s) >= 6:
|
||||||
|
return s[3:-3]
|
||||||
|
elif len(s) >= 2:
|
||||||
|
return s[1:-1]
|
||||||
|
else:
|
||||||
|
return s
|
||||||
|
else:
|
||||||
|
# starts double
|
||||||
|
ends_double = s.endswith('"')
|
||||||
|
if not ends_double:
|
||||||
|
return s
|
||||||
|
elif s.startswith('"""') and s.endswith('"""') and len(s) >= 6:
|
||||||
|
return s[3:-3]
|
||||||
|
elif len(s) >= 2:
|
||||||
|
return s[1:-1]
|
||||||
|
else:
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
def check_for_partial_string(x):
|
def check_for_partial_string(x):
|
||||||
"""Returns the starting index (inclusive), ending index (exclusive), and
|
"""Returns the starting index (inclusive), ending index (exclusive), and
|
||||||
starting quote string of the most recent Python string found in the input.
|
starting quote string of the most recent Python string found in the input.
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
"its behavior. To see the modifications as they are applied (in unified diff",
|
"its behavior. To see the modifications as they are applied (in unified diff",
|
||||||
"format), please set ``$XONSH_DEBUG`` to ``2`` or higher."]
|
"format), please set ``$XONSH_DEBUG`` to ``2`` or higher."]
|
||||||
},
|
},
|
||||||
|
{"name": "base16_shell",
|
||||||
|
"package": "xontrib-base16-shell",
|
||||||
|
"url": "https://github.com/ErickTucto/xontrib-base16-shell",
|
||||||
|
"description": ["Change base16 shell themes"]
|
||||||
|
},
|
||||||
{"name": "coreutils",
|
{"name": "coreutils",
|
||||||
"package": "xonsh",
|
"package": "xonsh",
|
||||||
"url": "http://xon.sh",
|
"url": "http://xon.sh",
|
||||||
|
|
|
@ -50,18 +50,18 @@ class VoxHandler:
|
||||||
help='Activate virtual environment'
|
help='Activate virtual environment'
|
||||||
)
|
)
|
||||||
activate.add_argument('name', metavar='ENV',
|
activate.add_argument('name', metavar='ENV',
|
||||||
help='The environment to activate. ENV can be '+
|
help=('The environment to activate. ENV can be '
|
||||||
'either a name from the venvs shown by '+
|
'either a name from the venvs shown by vox'
|
||||||
'vox list or the path to an arbitrary venv')
|
'list or the path to an arbitrary venv'))
|
||||||
subparsers.add_parser('deactivate', aliases=['exit'], help='Deactivate current virtual environment')
|
subparsers.add_parser('deactivate', aliases=['exit'], help='Deactivate current virtual environment')
|
||||||
subparsers.add_parser('list', aliases=['ls'],
|
subparsers.add_parser('list', aliases=['ls'],
|
||||||
help='List environments available in '+
|
help=('List environments available in '
|
||||||
'$VIRTUALENV_HOME')
|
'$VIRTUALENV_HOME'))
|
||||||
remove = subparsers.add_parser('remove', aliases=['rm', 'delete', 'del'], help='Remove virtual environment')
|
remove = subparsers.add_parser('remove', aliases=['rm', 'delete', 'del'], help='Remove virtual environment')
|
||||||
remove.add_argument('names', metavar='ENV', nargs='+',
|
remove.add_argument('names', metavar='ENV', nargs='+',
|
||||||
help='The environments to remove. ENV can be '+
|
help=('The environments to remove. ENV can be '
|
||||||
'either a name from the venvs shown by '+
|
'either a name from the venvs shown by vox'
|
||||||
'vox list or the path to an arbitrary venv')
|
'list or the path to an arbitrary venv'))
|
||||||
subparsers.add_parser('help', help='Show this help message')
|
subparsers.add_parser('help', help='Show this help message')
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue