Merge remote-tracking branch 'master' into dev_warning

This commit is contained in:
6syun9 2019-06-15 11:00:03 +09:00
commit f325baae9c
81 changed files with 1953 additions and 1154 deletions

View file

@ -1,11 +1,11 @@
version: 0.8.10.{build}
version: 0.9.6.{build}
os: Windows Server 2012 R2
environment:
matrix:
# http://www.appveyor.com/docs/installed-software#python
- PYTHON: "C:\\Python34"
- PYTHON: "C:\\Python34-x64"
- PYTHON: "C:\\Python35"
- PYTHON: "C:\\Python35-x64"
DISTUTILS_USE_SDK: "1"
- XONSH_TEST_ENV: "MSYS2"
MSYS2_PATH: "C:\\msys64"

View file

@ -57,12 +57,12 @@
- gforsyth@users.noreply.github.com
- Gilbert.Forsyth@capitalone.com
- gforsyth@gwu.edu
num_commits: 501
num_commits: 505
first_commit: 2015-10-19 16:04:32
github: gforsyth
- name: Morten Enemark Lund
email: melund@gmail.com
num_commits: 453
num_commits: 464
first_commit: 2015-07-10 07:54:10
github: melund
- name: Ned Letcher
@ -137,7 +137,7 @@
github: pelson
- name: Samuel Dion-Girardeau
email: samuel.diongirardeau@gmail.com
num_commits: 1
num_commits: 3
first_commit: 2018-01-13 14:24:46
github: samueldg
- name: Burak Yiğit Kaya
@ -344,7 +344,7 @@
github: JakeHedman
- name: Alexander Sosedkin
email: monk@unboiled.info
num_commits: 5
num_commits: 6
first_commit: 2016-09-24 02:35:09
github: t184256
- name: Klaus Alexander Seistrup
@ -378,7 +378,7 @@
email: lalochcz@gmail.com
aliases:
- laloch
num_commits: 32
num_commits: 42
first_commit: 2018-07-26 13:51:50
github: laloch
- name: Nico Lehmann
@ -395,7 +395,7 @@
alternate_emails:
- jbleger@gertrude
- jbleger@hds.utc.fr
num_commits: 18
num_commits: 53
first_commit: 2017-01-01 19:27:34
- name: Nigel Tea
email: nigelbtea@gmail.com
@ -428,7 +428,7 @@
github: funkyfuture
- name: Anthony Scopatz
email: scopatz@gmail.com
num_commits: 2389
num_commits: 2472
first_commit: 2015-01-21 17:04:13
github: scopatz
- name: anatoly techtonik
@ -957,3 +957,52 @@
num_commits: 1
first_commit: 2019-02-05 19:03:06
github: ntdef
- name: virus
email: virusbb001a@gmail.com
num_commits: 30
first_commit: 2019-03-06 10:36:26
github: virusbb001
- name: Steven Kryskalla
email: skryskalla@gmail.com
num_commits: 2
first_commit: 2019-03-24 11:00:24
- name: Kale Kundert
email: kale@thekunderts.net
num_commits: 4
first_commit: 2019-03-16 01:36:28
github: kalekundert
- name: Rodrigo Oliveira
email: rodrigo.oliveira@byne.com.br
num_commits: 1
first_commit: 2019-05-06 14:48:58
github: rodrigogolive
- name: Carmen Bianca Bakker
email: carmen@carmenbianca.eu
num_commits: 13
first_commit: 2019-04-07 16:33:01
github: carmenbianca
- name: Andrés García García
email: a.garcia230395@gmail.com
aliases:
- Ad115
num_commits: 4
github: Ad115
first_commit: 2019-05-06 14:17:57
- name: con-f-use
email: con-f-use@users.noreply.github.com
num_commits: 3
first_commit: 2019-05-15 04:53:37
- name: cclauss
email: cclauss@me.com
num_commits: 2
first_commit: 2019-05-02 07:35:11
github: cclauss
- name: Eddie Peters
email: edward.paul.peters@gmail.com
num_commits: 2
first_commit: 2019-05-10 06:18:40
github: eppeters
- name: shadow-light
email: 42055707+shadow-light@users.noreply.github.com
num_commits: 3
first_commit: 2018-09-16 22:50:24

View file

@ -1,51 +1,6 @@
version: 2
jobs:
build_34:
machine: true
environment:
PYTHON: "3.4"
ENV_NAME: "py34-xonsh-test"
steps:
- checkout
- restore_cache:
keys:
- miniconda-v1-{{ checksum "ci/environment-3.4.yml" }}
- run:
name: install miniconda
command: |
if [ ! -d "/home/circleci/miniconda" ]; then
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
bash miniconda.sh -b -p $HOME/miniconda
export PATH="$HOME/miniconda/bin:$PATH"
conda config --set always_yes yes --set changeps1 no
fi
sudo chown -R $USER.$USER $HOME
- run:
name: configure conda
command: |
export PATH="$HOME/miniconda/bin:$PATH"
if [ ! -d "/home/circleci/miniconda/envs/py34-xonsh-test" ]; then
conda update -q conda
conda env create -f ci/environment-${PYTHON}.yml --name=${ENV_NAME}
source activate ${ENV_NAME}
fi
conda env list
conda list ${ENV_NAME}
- save_cache:
key: miniconda-v1-{{ checksum "ci/environment-3.4.yml" }}
paths:
- "/home/circleci/miniconda"
- run:
command: |
export PATH="$HOME/miniconda/bin:$PATH"
source activate ${ENV_NAME}
pip install . --no-deps
- run:
command: |
export PATH="$HOME/miniconda/bin:$PATH"
source activate ${ENV_NAME}
xonsh run-tests.xsh --timeout=10
build_35:
machine: true
environment:
@ -63,7 +18,7 @@ jobs:
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
bash miniconda.sh -b -p $HOME/miniconda
export PATH="$HOME/miniconda/bin:$PATH"
conda config --set always_yes yes --set changeps1 no
conda config --set always_yes yes --set changeps1 no --set channel_priority strict
fi
sudo chown -R $USER.$USER $HOME
- run:
@ -109,7 +64,7 @@ jobs:
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
bash miniconda.sh -b -p $HOME/miniconda
export PATH="$HOME/miniconda/bin:$PATH"
conda config --set always_yes yes --set changeps1 no
conda config --set always_yes yes --set changeps1 no --set channel_priority strict
fi
sudo chown -R $USER.$USER $HOME
- run:
@ -155,7 +110,7 @@ jobs:
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
bash miniconda.sh -b -p $HOME/miniconda
export PATH="$HOME/miniconda/bin:$PATH"
conda config --set always_yes yes --set changeps1 no
conda config --set always_yes yes --set changeps1 no --set channel_priority strict
fi
sudo chown -R $USER.$USER $HOME
- run:
@ -184,6 +139,52 @@ jobs:
export PATH="$HOME/miniconda/bin:$PATH"
source activate ${ENV_NAME}
xonsh run-tests.xsh --timeout=10 --flake8 --cov=./xonsh
build_38:
machine: true
environment:
PYTHON: "3.8"
ENV_NAME: "py38-xonsh-test"
steps:
- checkout
- restore_cache:
keys:
- miniconda-v1-{{ checksum "ci/environment-3.8.yml" }}
- run:
name: install miniconda
command: |
if [ ! -d "/home/circleci/miniconda" ]; then
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
bash miniconda.sh -b -p $HOME/miniconda
export PATH="$HOME/miniconda/bin:$PATH"
conda config --set always_yes yes --set changeps1 no --set channel_priority strict
fi
sudo chown -R $USER.$USER $HOME
- run:
name: configure conda
command: |
export PATH="$HOME/miniconda/bin:$PATH"
export ENV_NAME="py38-xonsh-test"
if [ ! -d "/home/circleci/miniconda/envs/py38-xonsh-test" ]; then
conda update -q conda
conda env create -f ci/environment-${PYTHON}.yml --name=${ENV_NAME}
source activate ${ENV_NAME}
fi
conda env list
conda list ${ENV_NAME}
- save_cache:
key: miniconda-v1-{{ checksum "ci/environment-3.8.yml" }}
paths:
- "/home/circleci/miniconda"
- run:
command: |
export PATH="$HOME/miniconda/bin:$PATH"
source activate ${ENV_NAME}
pip install . --no-deps
- run:
command: |
export PATH="$HOME/miniconda/bin:$PATH"
source activate ${ENV_NAME}
xonsh run-tests.xsh --timeout=10 --flake8 --cov=./xonsh
build_black:
machine: true
steps:
@ -198,7 +199,7 @@ jobs:
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
bash miniconda.sh -b -p $HOME/miniconda
export PATH="$HOME/miniconda/bin:$PATH"
conda config --set always_yes yes --set changeps1 no
conda config --set always_yes yes --set changeps1 no --set channel_priority strict
fi
sudo chown -R $USER.$USER $HOME
- run:
@ -213,17 +214,17 @@ jobs:
- run:
command: |
export PATH="$HOME/miniconda/bin:$PATH"
cd xonsh/
black --exclude ply *.py --check
black --check --exclude=xonsh/ply/ xonsh/ xontrib/
workflows:
version: 2
run_all_pythons:
jobs:
- build_34
- build_35
- build_36
- build_37
- build_black
# conda-foge does not yet have all Python 3.7 packages available
# conda-foge does not yet have all Python 3.8 packages available
# uncomment when it does
#- build_37
#- build_38

View file

@ -20,16 +20,19 @@ Jamie Bliss <astronouth7303@gmail.com> James Bliss <jamie.bliss@ilq.com>
Jamie Bliss <astronouth7303@gmail.com> James Bliss <jbliss@nextgenerationenrollment.com>
Hugo Wang <w@mitnk.com>
BlahGeek <i@BlahGeek.com>
Jean-Benoist Leger <jb@leger.tf> Jean-Benoist Leger <jbleger@gertrude>
Jean-Benoist Leger <jb@leger.tf> Jean-Benoist Leger <jbleger@hds.utc.fr>
Klaus Alexander Seistrup <klaus@seistrup.dk> Klaus Alexander Seistrup <kseistrup@users.noreply.github.com>
Leonardo Santagada <santagada@gmail.com>
Bob Hyman <bob.hyman@bobssoftwareworks.com>
David Strobach <lalochcz@gmail.com> laloch <lalochcz@gmail.com>
christopher <cjwright4242@gmail.com>
Aaron Griffin <aig787@gmail.com>
Rob Brewer <rwb123@gmail.com> Robert W. Brewer <rwb123@gmail.com>
Burak Yiğit Kaya <ben@byk.im> Burak Yigit Kaya <ben@byk.im>
Sagar Tewari <sagartewari01@gmail.com> Sagar Tewari <sagartewariym@yahoo.com>
Matthias Bussonnier <bussonniermatthias@gmail.com>
David Strobach <lalochcz@gmail.com> laloch <lalochcz@gmail.com>
virus <virusbb001a@gmail.com>
Konstantin Molchanov <kmolchanov@machinezone.com> Konstantin Molchanov <moigagoo@live.com>
Guillaume Leclerc <guillaume.leclerc@epfl.ch> Guillaume Leclerc <guillaume.leclerc.work@gmail.com>
Gordon Ball <gordon@chronitis.net>
@ -38,8 +41,6 @@ Joel Gerber <joel@grrbrr.ca>
Bernardas Ališauskas <bernardas.alisauskas@gmail.com> Bernardas <bernardas.alisauskas@gmail.com>
Derek Thomas <derekathomas@gmail.com>
VHarisop <the.machine.headed@gmail.com>
Jean-Benoist Leger <jb@leger.tf> Jean-Benoist Leger <jbleger@gertrude>
Jean-Benoist Leger <jb@leger.tf> Jean-Benoist Leger <jbleger@hds.utc.fr>
JohnLunzer <lunzer@gmail.com> jlunz <lunz8748@usroc1miniwaas.corp.exelisinc.com>
Paul Goelz <s8pagoel@stud.uni-saarland.de>
David Dotson <dotsdl@gmail.com>
@ -47,6 +48,7 @@ Frank Sachsenheim <funkyfuture@riseup.net> Frank Sachsenheim <funkyfuture@users.
Kurtis Rader <krader@skepticism.us>
cryzed <cryzed@googlemail.com>
Brian Visel <eode@eptitude.net>
Carmen Bianca Bakker <carmen@carmenbianca.eu>
Andrew Hundt <ATHundt@gmail.com>
Jonathan Slenders <jonathan@slenders.be>
Justin Moen <jamoen7@gmail.com>
@ -64,6 +66,7 @@ Yohei Tamura <tamuhey@gmail.com>
Maximilian Köhl <mail@koehlma.de>
Cody Scott <cody.j.b.scott@gmail.com>
Jake Hedman <jake@hedman.email>
Alexander Sosedkin <monk@unboiled.info>
traverseda <traverse.da@gmail.com>
Andre Weltsch <andre.t.weltsch@campus.tu-berlin.de> Andre Weltsch <andre@weltsch.de>
Jeremy Donahue <jeremydonahue@gmail.com>
@ -74,7 +77,6 @@ Jared Crawford <jmcrawford45@gmail.com>
JuanPablo <jpabloaj@gmail.com>
K.-Michael Aye <kmichael.aye@gmail.com> K.-Michael Aye <michaelaye@users.noreply.github.com>
Ollie Terrance <ollie.terrance@live.co.uk>
Alexander Sosedkin <monk@unboiled.info>
Marcel Bollmann <bollmann@linguistics.rub.de>
mdraw <mdraw.gh@gmail.com>
Mattias Ugelvik <uglemat@gmail.com>
@ -107,8 +109,11 @@ Sardorbek Imomaliev <sardorbek.imomaliev@gmail.com>
Jakub Nowak <jakub.jakub.nowak@gmail.com>
selepo <po.lenhoff@gmail.com>
Fabien Dubosson <fabien.dubosson@gmail.com>
Kale Kundert <kale@thekunderts.net>
Andrés García García <a.garcia230395@gmail.com> Ad115 <a.garcia230395@gmail.com>
Jan Schulz <jasc@gmx.net>
Nickolay Bukreyev <buknik95@yandex.ru>
Samuel Dion-Girardeau <samuel.diongirardeau@gmail.com>
Michael Droettboom <mdboom@gmail.com>
guillearch <gcastellano@protonmail.com>
javValverde <jav.valve@gmail.com>
@ -122,6 +127,8 @@ David <auscompgeek@users.noreply.github.com>
Danmou <dmrtzn@gmail.com>
Niklas Hambüchen <mail@nh2.me>
Sébastien Pierre <sebastien.pierre@gmail.com>
con-f-use <con-f-use@users.noreply.github.com>
shadow-light <42055707+shadow-light@users.noreply.github.com>
Mark Wiebe <mwwiebe@gmail.com>
Nathan Hoad <nathan@getoffmalawn.com>
Eric Dill <edill@bnl.gov>
@ -141,6 +148,9 @@ Michał Zając <emzajac@gmail.com> zajaczajac <michal.zajac@swmansion.com>
Emre Ates <ates@bu.edu>
Romain Bignon <romain@symlink.me>
Owen Campbell <owen.campbell@tanti.org.uk>
Steven Kryskalla <skryskalla@gmail.com>
cclauss <cclauss@me.com>
Eddie Peters <edward.paul.peters@gmail.com>
Dan Allan <dallan@bnl.gov>
adam j hartz <adam@smatz.net>
Ned Letcher <nletcher@gmail.com>
@ -148,7 +158,6 @@ Zach Crownover <zachary.crownover@gmail.com>
Miguel de Val-Borro <miguel@archlinux.net>
Hirotomo Moriwaki <hirotomo.moriwaki@gmail.com>
Phil Elson <pelson.pub@gmail.com>
Samuel Dion-Girardeau <samuel.diongirardeau@gmail.com>
Erin Call <erincall@github.com>
Trevor Bekolay <tbekolay@gmail.com>
Tzu-ping Chung <uranusjr@gmail.com>
@ -198,5 +207,6 @@ Chad Kennedy <chadkennedyonline@users.noreply.github.com>
stonebig <stonebig34@gmail.com>
Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
Troy de Freitas <9503857+ntdef@users.noreply.github.com>
Rodrigo Oliveira <rodrigo.oliveira@byne.com.br>
goodboy <tgoodlet@users.noreply.github.com>
Atsushi Morimoto <atsushi.morimoto@dena.com>

View file

@ -4,14 +4,12 @@ env:
- secure: "pvQHCsdcIRjwNvsBrZxP8cZWEwug0+PLg1T8841ZLkMdCaO3YheqmxF1xGjAqty6hLppz6vX1LFEKmPjKurLL0/i+be6MhT8/ZikFpSan7TdNUqISxeFx31ls+QpuFKzCV7ZEx7C1ms8LPWEGmzMMN6bCtOBVtGznD9KKWZmLlA="
matrix:
include:
# Travis does not yet support Python 3.7 on Linux
# uncomment the following when it does
#- os: linux
# python: 3.7
# env:
# - MINICONDA_OS="Linux"
# - CI=true
# - TRAVIS=true
- os: linux
dist: xenial # required for Python >= 3.7
python: 3.7
env:
- MINICONDA_OS="Linux"
- BUILD_DOCS=false
- os: linux
python: 3.6
env:
@ -19,6 +17,7 @@ matrix:
- BUILD_DOCS=true
- os: linux
python: "nightly"
dist: xenial # required for Python >= 3.7
- os: linux
python: "pypy3"
env:
@ -29,6 +28,9 @@ matrix:
- os: osx
language: generic
env: PYTHON="3.7" MINICONDA_OS="MacOSX"
- os: osx
language: generic
env: PYTHON="3.8" MINICONDA_OS="MacOSX"
allow_failures:
- python: "nightly"
- python: "pypy3"
@ -74,4 +76,3 @@ script:
else
xonsh run-tests.xsh --timeout=10;
fi

View file

@ -9,16 +9,18 @@ Authors are sorted by number of commits.
* Jamie Bliss
* Hugo Wang
* BlahGeek
* Jean-Benoist Leger
* Klaus Alexander Seistrup
* Leonardo Santagada
* Bob Hyman
* David Strobach
* christopher
* Aaron Griffin
* Rob Brewer
* Burak Yiğit Kaya
* Sagar Tewari
* Matthias Bussonnier
* David Strobach
* virus
* Konstantin Molchanov
* Guillaume Leclerc
* Gordon Ball
@ -27,7 +29,6 @@ Authors are sorted by number of commits.
* Bernardas Ališauskas
* Derek Thomas
* VHarisop
* Jean-Benoist Leger
* JohnLunzer
* Paul Goelz
* David Dotson
@ -35,6 +36,7 @@ Authors are sorted by number of commits.
* Kurtis Rader
* cryzed
* Brian Visel
* Carmen Bianca Bakker
* Andrew Hundt
* Jonathan Slenders
* Justin Moen
@ -52,6 +54,7 @@ Authors are sorted by number of commits.
* Maximilian Köhl
* Cody Scott
* Jake Hedman
* Alexander Sosedkin
* traverseda
* Andre Weltsch
* Jeremy Donahue
@ -62,7 +65,6 @@ Authors are sorted by number of commits.
* JuanPablo
* K.-Michael Aye
* Ollie Terrance
* Alexander Sosedkin
* Marcel Bollmann
* mdraw
* Mattias Ugelvik
@ -95,8 +97,11 @@ Authors are sorted by number of commits.
* Jakub Nowak
* selepo
* Fabien Dubosson
* Kale Kundert
* Andrés García García
* Jan Schulz
* Nickolay Bukreyev
* Samuel Dion-Girardeau
* Michael Droettboom
* guillearch
* javValverde
@ -110,6 +115,8 @@ Authors are sorted by number of commits.
* Danmou
* Niklas Hambüchen
* Sébastien Pierre
* con-f-use
* shadow-light
* Mark Wiebe
* Nathan Hoad
* Eric Dill
@ -129,6 +136,9 @@ Authors are sorted by number of commits.
* Emre Ates
* Romain Bignon
* Owen Campbell
* Steven Kryskalla
* cclauss
* Eddie Peters
* Dan Allan
* adam j hartz
* Ned Letcher
@ -136,7 +146,6 @@ Authors are sorted by number of commits.
* Miguel de Val-Borro
* Hirotomo Moriwaki
* Phil Elson
* Samuel Dion-Girardeau
* Erin Call
* Trevor Bekolay
* Tzu-ping Chung
@ -186,6 +195,7 @@ Authors are sorted by number of commits.
* stonebig
* Ronny Pfannschmidt
* Troy de Freitas
* Rodrigo Oliveira
* goodboy
* Atsushi Morimoto

View file

@ -4,6 +4,363 @@ Xonsh Change Log
.. current developments
v0.9.6
====================
**Fixed:**
* Fixed exception in help/version threadable predictor
* Fixed gitstatus prompt so that it also now reports deleted files
* Fixed issue where the prompt-toolkit2 shell could not display and
would end up in an infinite error loop if ``$MULTILINE_PROMPT``
was a suitably "false" value, such as ``None`` or an empty string.
* Fixed issue where setting ``$XONSH_STDERR_PREFIX`` and ``$XONSH_STDERR_POSTFIX``
and running a command in the ``xonshrc`` file would throw an error.
**Authors:**
* Anthony Scopatz
* David Strobach
* virus
* shadow-light
v0.9.5
====================
**Fixed:**
* Style 'bw'. Background colors was added in the style description.
* Fix causing error in ``get_predictor_threadable`` on windows when try to run not exist command
* ``pip`` completer no longer fires when ``pip`` happens to appear within a word
like ``bagpipes``
* Fixed issue with ``history gc`` command not running properly.
**Authors:**
* Anthony Scopatz
* Gil Forsyth
* Jean-Benoist Leger
* virus
* con-f-use
v0.9.4
====================
**Added:**
* Add processing ``%d`` for avoid overwriting in ``run-tests.xsh``
**Changed:**
* Xonsh now does not attempt to expand raw strings, so now::
$ echo "$HOME"
/home/user
$ echo r"$HOME"
$HOME
* sudoedit now runs unthreaded
**Fixed:**
* threadable predictor for 'env' command based on predictor from the executed
command. Fixes #2759 and #3103.
* An error in the 'xon.sh' executable that only popped up during testing has
been fixed. Specifically: It now directly calls 'python3' without invoking
'env'.
* bashisms extension can be used again with prompt_toolkit v1
* Fix a crash when setting ``$INTENSIFY_COLORS_ON_WIN`` in certain situations.
* Fix issue with bashsisms xontrib causing syntax errors for some Python statements
* portable trick to pass args which replace '/usr/bin/env' is removed and
'/usr/bin/env' is used. Fixes bug when a python3 used is outside the default
'PATH'.
**Authors:**
* Anthony Scopatz
* Morten Enemark Lund
* Jean-Benoist Leger
* David Strobach
* virus
* Carmen Bianca Bakker
* con-f-use
* cclauss
* Eddie Peters
v0.9.3
====================
**Deprecated:**
* Python v3.4 has been fully, completely, and (hopefully) correctly
deprecated. Please migrate to an officially supported version of Python.
**Authors:**
* Anthony Scopatz
v0.9.2
====================
**Changed:**
* For aliases, predictor is build with the predictor of original command, in
place of default predictor.
**Fixed:**
* Updated setup.py to require Python 3.4 using the ``python_requires`` keyword.
This rectifies issues with pip installing xonsh. Python 3.4 support will
be removed on the following release.
**Authors:**
* Anthony Scopatz
* Jean-Benoist Leger
v0.9.1
====================
**Changed:**
* We no longer manually check the Python version in ``setup.py``,
but instead use the setuptools ``python_requires`` feature.
**Fixed:**
* Updates for integrating with new colors styles in Pygments v2.4.0.
**Authors:**
* Anthony Scopatz
v0.9.0
====================
**Added:**
* Implemented the following "bang command" bashisms: ``!$``, ``$*``, ``!^``,
and ``!<str>``. These are in addition to ``!!``, which was already
implemented.
* asciinema (terminal recorder) added in not threadable commands.
* tput added in not threadable commands.
* New ``color_tools.KNOWN_XONSH_COLORS`` frozenset.
* New ``pyghooks.PYGMENTS_MODIFIERS`` mapping from color modifier names to
pygments colors.
* New ``pyghooks.color_name_to_pygments_code()`` function for converting
color names into pygments color codes.
**Changed:**
* Circle now runs ``black`` checks on contents of bundled xontribs
* The ``black`` checks no longer skip some files buried deeper in the directory
tree.
* Errors while formatting the prompt are highlighted for easier debugging.
* Pygments styles only define the standard set of colors, by default.
Additional colors are computed as needed.
* PTYs created for running threadable command have now size set to same size
than main terminal.
* Update documentation pointing to the minimal required version of
Python (3.5).
**Deprecated:**
* Drop support for Python 3.4.
**Removed:**
* ``pyghooks.KNOWN_COLORS`` is no longer needed or useful as pygments colors
are computed automatically.
* ``style_tools.KNOWN_COLORS`` was never used, redundant with
``pyghooks.KNOWN_COLORS`` and has thus been removed.
**Fixed:**
* Fixed a DeprecationWarning that would show up during an import of MutableSet.
* Fixed error with aliases composed of functions wrapped in functools.partial.
* ``black`` formatted all xontribs
* deleting a non existing environement variable with default value do nothing
instead of raising a exception trying to deleting it in existing values dict.
* Fixed crash while converting ANSI color codes with leading zeroes
* Fixed crash while parsing invalid ANSI color code
* fix causing infinite loop when doing ``cat`` empty file
* Fixed issue which occurs when user doesn't have access to parent directory and
xonsh scan all parents directory to find if we are in a Hg repository.
* Fixed issue with pygments-cache not properly generating a cache the first
time when using prompt-toolkit when using ``ptk2``.
This was due to a lingering lazy import of ``pkg_resources``
that has been removed.
* Minor update for Python v3.8.
* Fixed a "'NoneType' object is not iterable" bug when looking up ``stty``
in command cache.
* The release tarball now includes all test files.
* Arguments passed to python in 'scripts/xonsh' and in 'scripts/xonsh-cat' are
now passed by a portable hack in sh, not anymore by /usr/bin/env.
**Authors:**
* Anthony Scopatz
* Gil Forsyth
* Jean-Benoist Leger
* David Strobach
* virus
* Carmen Bianca Bakker
* Alexander Sosedkin
* Kale Kundert
* Andrés García García
* Samuel Dion-Girardeau
* Steven Kryskalla
* Rodrigo Oliveira
v0.8.12
====================
**Added:**
* Support for more ANSI escape sequence modifers allowed in color names.
The current modifiers now allowed are: BOLD, FAINT, ITALIC, UNDERLINE,
SLOWBLINK, FASTBLINK, INVERT, CONCEAL, and STRIKETHROUGH.
* New ``ansi_tools.ansi_color_name_to_escape_code()`` function for
converting a color name to an ANSI escape code.
* ``color_tools.RE_XONSH_COLOR`` is a regular expression for matching
xonsh color names.
* ``color_tools.iscolor()`` is a simple function for testing whether a
string is a valid color name or not.
* The ``tools.all_permutations()`` function yields all possible permutations
of an iterable, including removals.
**Changed:**
* change url of xontrib-autojump
* ANSI color styles may now be defined simply by their plain and intense colors.
* ``SET_FOREGROUND_3INTS_`` renamed to ``SET_FOREGROUND_FAINT_``,
``SET_BACKGROUND_3INTS_`` renamed to ``SET_BACKGROUND_FAINT_``,
``SET_FOREGROUND_SHORT_`` renamed to ``SET_FOREGROUND_SLOWBLINK_``, and
``SET_BACKGROUND_SHORT_`` renamed to ``SET_BACKGROUND_SLOWBLINK_``.
**Removed:**
* ``ansi_tools.ANSI_REVERSE_COLOR_NAME_TRANSLATIONS`` removed, as it is
no longer needed.
**Fixed:**
* Fixed issues where ``$LS_COLORS`` could not convert valid ANSI colors.
**Authors:**
* Anthony Scopatz
* virus
v0.8.11
====================
**Added:**
* New ``xonsh.color_tools.short_to_ints()`` function for directly
converting a short (0 - 256) color into a 3-tuple of ints
representing its RGB value.
* New ``xonsh.ansi_colors.ansi_reverse_style()`` function for
converting a mapping of color names to ANSI escape codes into
a mapping from escape codes into color names. This is not a
round-trippable operation.
* New ``xonsh.ansi_colors.ansi_color_escape_code_to_name()`` function
for converting an ANSI color escape code into the closest xonsh
color name for a given style.
* New ``xonsh.events.EventManager.exists()`` method enables checking
whether events actually exist without making the event if it
doesn't exist.
* New command-specific event categories called ``on_pre_spec_run_<cmd-name>``
and ``on_post_spec_run_<cmd-name>`` will be fired before and after
``SubpocSpec.run()`` is called. This allows for command specific
events to be executed. For example, ``on_pre_spec_run_ls`` would
be run prior to an invocation of ``ls``.
* New ``xonsh.environ.LsColors`` class for managing the ``$LS_COLORS``
environment variable. This ensures that the ``ls`` command respects the
``$XONSH_COLOR_STYLE`` setting. An instance of this class is added to the
environment when either the ``$LS_COLORS`` class is first accessed or
the ``ls`` command is executed.
* The ``on_pre_spec_run_ls`` event is initialized with a default handler
that ensures that ``$LS_COLORS`` is set in the actual environment prior
to running an ``ls`` command.
* New ``xonsh.tools.detype()`` function that simply calls an object's own
``detype()`` method in order to detype it.
* New ``xonsh.tools.always_none()`` function that simply returns ``None``.
* New ``Env.set_ensurer()`` method for setting an ensurer on an environment.
**Changed:**
* The black and white style ``bw`` now uses actual black and white
ANSI colore codes for its colors, rather than just empty color
sequences.
* An environment variable ``detype`` operation no longer needs to be a
function, but may also be ``None``. If ``None``, this variable is
considered not detypeable, and will not be exported to subprocess
environments via the ``Env.detype()`` function.
* An environment variable ``detype`` function no longer needs to return
a string, but may also return ``None``. If ``None`` is returned, this
variable is considered not detypeable, and will not be exported to
subprocess environments via the ``Env.detype()`` function.
* The ``Env.detype()`` method has been updated to respect the new
``None`` types when detyping.
* The ``xonsh.tools.expandvars()`` function has been updated to respect
the new ``None`` types when detyping.
* The ``xonsh.xonfig.make_xonfig_wizard()`` function has been updated to respect
the new ``None`` types when detyping.
* Event handlers may now be added and discarded during event firing for
normal events. Such modifications will not be applied until the
current firing operation is concluded. Thus you won't see newly added
events fired.
* xonsh now uses its own vendored version of ply. Any installed versions will no longer be used. This reflects that ply is no
longer distributed as an installable package.
* Updated to use ply version 3.11.
* Reverted change in ``give_to_terminal`` to restore working version of
``cmake``, ``rm -i``, etc. This breaks ``pv | head``.
**Deprecated:**
* The ``xonsh.color_tools.make_pallete()`` function is no
longer deprecated, as it is actually needed in other parts of
xonsh still, such as ``pyghooks``.
**Removed:**
* All code references to ``$FORMATTER_DICT`` have been removed.
**Fixed:**
* Resolved issues where macro functions were not able to properly
accept single-line statements in ``exec`` and ``single`` mode.
* Minor fixes to ``xonsh.events.debug_level()``.
* Fixed a regression where some interactive commands were not waited for
properly for long enough.
* Fixed environments not showing in the prompt when using Anaconda Python.
* Fixed regression with anaconda activate/deactivate scripts not working on Windows.
**Authors:**
* Anthony Scopatz
* Morten Enemark Lund
v0.8.10
====================
@ -18,7 +375,7 @@ v0.8.10
* Subprocesses will no longer close file descriptors automatically.
This was causing issues with other commands that expected file
descriptors to remain open, such as ``make``.
* The ``xonsh.Aliases.eval_alaises()`` method updated to use
* The ``xonsh.Aliases.eval_alias()`` method updated to use
``xonsh.aliases.partial_eval_alias()``.
**Fixed:**
@ -31,12 +388,12 @@ v0.8.10
* Resolved issue where setting empty signal masks was causing the
terminal to close. This was problematic for certain command
pipelines. For example, ``pv /dev/urandom | head`` now works.
* Prevents recurssive errors from being raised when there is no child process
* Prevents recursive errors from being raised when there is no child process
in ``xonsh.jobs.wait_for_active_job()``.
* Tweaked ``xonsh.completers.commands.complete_skipper()`` to insert a space following
certain tokens (``&&``, ``||``, ``|``, ``and``, ``or``) to avoid overwriting existing tokens
with completer output.
* Fixed bug with evaluating recurssive aliases that did not implement
* Fixed bug with evaluating recursive aliases that did not implement
the full callable alias signature.
**Authors:**
@ -75,7 +432,7 @@ v0.8.9
* Made ``$PATH`` searching more robust to broken symlinks on Windows.
* undesirable SIGSTOP by putting in a SIGCONT
* Fixed issue with recursive aliases not being passes all keyword arguments
* Fixed issue with recursive aliases not being passed all keyword arguments
that are part of the callable alias spec. This allows commands like
``aliases['hsa'] = "history show all"; hsa | head`` to no longer fail
with strange errors.
@ -97,7 +454,7 @@ v0.8.8
**Added:**
* ``vox new`` has an added ``-p --interpreter`` flag for choosing the python interpreter to use for virtualenv creation
* ``vox new`` has an added ``-p --interpreter`` flag for choosing the Python interpreter to use for virtualenv creation
* The default Python intrepreter vox uses to create virtual environments can be set using the ``$VOX_DEFAULT_INTERPRETER`` environment variable.
@ -171,24 +528,25 @@ v0.8.5
* Installation / Usage
1. To install use pip
.. code-block:: bash
.. code-block:: bash
python3 -m pip install xontrib-base16-shell
python3 -m pip install xontrib-base16-shell
2. Add on ``~/.xonshrc``
.. code:: python
:number-lines:
.. code:: python
:number-lines:
$BASE16_SHELL = $HOME + "/.config/base16-shell/"
xontrib load base16_shell
$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
.. 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
@ -365,7 +723,7 @@ v0.8.1
* Builtin dynamic proxies and deprecation warning proxies were not deleting
attributes and items properly.
* Fixed stdout/sdterr writing infinite recurssion error that would occur in
* Fixed stdout/sdterr writing infinite recursion error that would occur in
long pipelines of callable aliases.
* Fixed a bug which under very rare conditions could cause the shell
to die with PermissionError exception while sending SIGSTOP signal
@ -500,7 +858,7 @@ v0.7.10
**Added:**
* 'off' can be passed as falsy value to all flags accepting boolean argument.
- DragonFly BSD support
* DragonFly BSD support
* Format strings (f-strings) now allow environment variables to be looked up.
For example, ``f"{$HOME}"`` will yield ``"/home/user"``. Note that this will
look up and fill in the ``detype()``-ed version of the environment variable,

View file

@ -327,7 +327,7 @@ Building the website/documentation requires the following dependencies:
#. `Sphinx <http://sphinx-doc.org/>`_
#. `Cloud Sphinx Theme <https://cloud-sptheme.readthedocs.io/>`_
#. `numpydoc <https://numpydoc.readthedocs.io/>`_
#. `numpydoc <https://numpydoc.readthedocs.io/>`__
Note that xonsh itself needs to be installed too.
@ -427,4 +427,4 @@ Portions of this page have been forked from the PyNE documentation,
Copyright 2011-2015, the PyNE Development Team. All rights reserved.
.. _PEP8: https://www.python.org/dev/peps/pep-0008/
.. _numpydoc: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
.. _numpydoc: https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard

View file

@ -1,9 +1,11 @@
include logo.txt
include scripts/*
include tests/*
include license
include CHANGELOG.rst
include README.rst
include run-tests.xsh
recursive-include tests *
exclude tests/test_news.py
recursive-include xonsh/ply/example *
recursive-include xonsh/ply/doc *
recursive-include xonsh/ply/test *

View file

@ -22,7 +22,7 @@ xonsh
:target: https://codecov.io/gh/xonsh/xonsh
xonsh is a Python-powered, cross-platform, Unix-gazing shell language and command prompt.
The language is a superset of Python 3.4+ with additional shell primitives.
The language is a superset of Python 3.5+ with additional shell primitives.
xonsh (pronounced *conch*) is meant for the daily use of experts and novices alike.
Please visit https://xon.sh for more information.

View file

@ -11,6 +11,9 @@ jobs:
python.version: '3.6'
Python37:
python.version: '3.7'
# Uncomment when Python 3.8 is supported
#Python38:
# python.version: '3.8'
maxParallel: 4
steps:
@ -21,29 +24,22 @@ jobs:
# Conda Environment
# Create and activate a Conda environment.
- task: CondaEnvironment@1
inputs:
packageSpecs: 'python=$(python.version) conda=4.5.11 pygments prompt_toolkit pytest pytest-timeout numpy psutil matplotlib flake8 coverage pyflakes pytest-cov pytest-flake8 codecov'
installOptions: '-c conda-forge/label/cf201901'
updateConda: false
condition: eq(variables['python.version'], '3.5')
- powershell: Write-Host "##vso[task.prependpath]$env:CONDA\Scripts"
displayName: Add conda to PATH
- script: 'conda create --yes --quiet --name conda-test-$(python.version) -c conda-forge/label/cf201901 python=$(python.version) conda=4.5.11 pygments prompt_toolkit pytest pytest-timeout numpy psutil matplotlib flake8 coverage pyflakes pytest-cov pytest-flake8 codecov'
displayName: 'Conda Environment (conda-forge/label/cf201901)'
- task: CondaEnvironment@1
inputs:
packageSpecs: 'python=$(python.version) pygments prompt_toolkit pytest pytest-timeout numpy psutil matplotlib flake8 coverage pyflakes pytest-cov pytest-flake8 codecov'
installOptions: '-c conda-forge/label/cf201901'
updateConda: false
condition: eq(variables['python.version'], '3.5')
- task: CondaEnvironment@1
inputs:
packageSpecs: 'python=$(python.version) pygments prompt_toolkit pytest pytest-timeout numpy psutil matplotlib flake8 coverage pyflakes pytest-cov pytest-flake8 codecov'
installOptions: '-c conda-forge'
updateConda: false
- script: |
call activate conda-test-$(python.version)
conda install --yes --quiet -c conda-forge/label/cf201901 python=$(python.version) pygments prompt_toolkit pytest pytest-timeout numpy psutil matplotlib flake8 coverage pyflakes pytest-cov pytest-flake8 codecov
condition: eq(variables['python.version'], '3.5')
- script: 'conda create --yes --quiet --name conda-test-$(python.version) -c conda-forge python=$(python.version) pygments prompt_toolkit pytest pytest-timeout numpy psutil matplotlib flake8 coverage pyflakes pytest-cov pytest-flake8 codecov'
condition: ne(variables['python.version'], '3.5')
displayName: 'Conda Environment (conda-forge)'
- script: |
call activate conda-test-$(python.version)
pip install .
xonsh run-tests.xsh --timeout=10 --junitxml=junit/test-results.xml
xonsh run-tests.xsh --timeout=10 --junitxml=junit/test-results.%%d.xml
displayName: 'Tests'
# Publish build results

View file

@ -10,7 +10,6 @@ dependencies:
- pytest-timeout
- numpy
- psutil
- matplotlib
- flake8
- coverage
- pyflakes

View file

@ -1,9 +1,9 @@
name: py34-xonsh-test
name: py38-xonsh-test
channels:
- conda-forge
- defaults
dependencies:
- python=3.4
- python=3.8
- pygments
- prompt_toolkit
- pytest
@ -15,7 +15,5 @@ dependencies:
- coverage
- pyflakes
- pytest-cov
- pytest-flake8
- codecov
# conda forge doesn't have the following for Python v3.4
- pip:
- pytest-flake8

View file

@ -3,3 +3,8 @@
table.docutils th.field-name {
white-space: nowrap;
}
p code.literal {
white-space: normal;
word-wrap: break-word;
}

View file

@ -55,7 +55,7 @@ the xonsh shell
</p>
Xonsh is a Python-powered, cross-platform, Unix-gazing shell language and
command prompt. The language is a superset of Python 3.4+ with additional
command prompt. The language is a superset of Python 3.5+ with additional
shell primitives that you are used to from Bash and IPython. It works on
all major systems including Linux, Mac OSX, and Windows. Xonsh is meant
for the daily use of experts and novices alike.

View file

@ -1347,7 +1347,7 @@ To make an alias uncapturable, decorate its
function with the ``xonsh.tools.uncapturable`` decorator. This is probably
best used in conjunction with the ``unthreadable`` decorator. For example:
.. code-block:: python
.. code-block:: xonshcon
from xonsh.tools import unthreadable, uncapturable
@ -1495,11 +1495,26 @@ or ``{BOLD_BLUE}``. Colors have the form shown below:
and ``BACKGROUND_#123456`` can both be used.
* ``bg#HEX`` or ``BG#HEX`` are shortcuts for setting a background hex color.
Thus you can set ``bg#0012ab`` or the uppercase version.
* ``BOLD_`` is a prefix qualifier that may be used with any foreground color.
* ``BOLD_`` is a prefix modifier that increases the intesnity of the font.
It may be used with any foreground color.
For example, ``BOLD_RED`` and ``BOLD_#112233`` are OK!
* ``FAINT_`` is a prefix modifier that decreases the intesnity of the font.
For example, ``FAINT_YELLOW``.
* ``ITALIC_`` is a prefix modifier that switches to an italic font.
For example, ``ITALIC_BLUE``.
* ``UNDERLINE_`` is a prefix qualifier that also may be used with any
foreground color. For example, ``UNDERLINE_GREEN``.
* Or any other combination of qualifiers, such as
* ``SLOWBLINK_`` is a prefix modifier makes the text blink, slowly.
For example, ``SLOWBLINK_PURPLE``.
* ``FASTBLINK_`` is a prefix modifier makes the text blink, quickly.
For example, ``FASTBLINK_CYAN``.
* ``INVERT_`` is a prefix modifier swaps the foreground and background colors.
For example, ``INVERT_WHITE``.
* ``CONCEAL_`` is a prefix modifier which hides the text. This may not be
widely supported. For example, ``CONCEAL_BLACK``.
* ``STRIKETHROUGH_`` is a prefix modifier which draws a line through the text.
For example, ``STRIKETHROUGH_RED``.
* Or any other combination of modifiers, such as
``BOLD_UNDERLINE_INTENSE_BLACK``, which is the most metal color you
can use!

View file

@ -465,7 +465,9 @@ Sqlite History Backend
Xonsh has a second built-in history backend powered by sqlite (other than
the JSON version mentioned all above in this tutorial). It shares the same
functionality as the JSON version in most ways, except it currently doesn't
support ``history diff`` and ``history replay`` actions.
support ``history diff`` and ``history replay`` actions and does not store
the output of commands, as the json-backend does. E.g.
`__xonsh__.history[-1].out` will always be `None`.
The Sqlite history backend can provide a speed advantage in loading history
into a just-started xonsh session. The JSON history backend may need to read

View file

@ -16,8 +16,7 @@
**Fixed:**
* Resolved issues where macro functions were not able to properly
accept single-line statements in ``exec`` and ``single`` mode.
* Removed obsolte "Alt+." keybinding in xontrib-bashisms that was causing built-in binding to malfunction.
**Security:**

23
news/dev_syun.rst Normal file
View file

@ -0,0 +1,23 @@
**Added:**
* <news item>
**Changed:**
* <news item>
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* Fixed that occurs when type a command before rendering.
**Security:**
* <news item>

View file

@ -1,74 +0,0 @@
**Added:**
* New ``xonsh.color_tools.short_to_ints()`` function for directly
converting a short (0 - 256) color into a 3-tuple of ints
represeting its RGB value.
* New ``xonsh.ansi_colors.ansi_reverse_style()`` function for
converting a mapping of color names to ANSI escape codes into
a mapping from escape codes into color names. This is not a
round-trippable operation.
* New ``xonsh.ansi_colors.ansi_color_escape_code_to_name()`` function
for converting an ANSI color escape code into the closest xonsh
color name for a given style.
* New ``xonsh.events.EventManager.exists()`` method enables the checking
of whether events actually exist with out making the event if it
doesn't exist.
* New command-specific event categories called ``on_pre_spec_run_<cmd-name>``
and ``on_post_spec_run_<cmd-name>`` will be fired before and after
``SubpocSpec.run()`` is called. This allows for command specific
events to be executed. For example, ``on_pre_spec_run_ls`` would
be run prior to an invocation of ``ls``.
* New ``xonsh.environ.LsColors`` class for managing the ``$LS_COLORS``
environment variable. This ensures that the ``ls`` command respects the
``$XONSH_COLOR_STYLE`` setting. An instance of this class is added to the
environment when either the ``$LS_COLORS`` class is first accessed or
the ``ls`` command is executed.
* The ``on_pre_spec_run_ls`` event is initialized with a default handler
that ensures that ``$LS_COLORS`` is set in the actual environment prior
to running an ``ls`` command.
* New ``xonsh.tools.detype()`` function that simply calls an objects own
``detype()`` method in order to detype it.
* New ``xonsh.tools.always_none()`` function that simply returns None.
* New ``Env.set_ensurer()`` method for setting an ensurer on an environment.
**Changed:**
* The black and white style ``bw`` now uses actual black and white
ANSI colore codes for its colors, rather than just empty color
sequences.
* An environment variable ``detype`` operation no longer needs to be
function, but may also be ``None``. If ``None``, this variable is
considered not detypeable, and will not be exported to subprocess
environments via the ``Env.detype()`` function.
* An environment variable ``detype`` function no longer needs to return
a string, but may also return ``None``. If ``None`` is returned, this
variable is considered not detypeable, and will not be exported to
subprocess environments via the ``Env.detype()`` function.
* The ``Env.detype()`` method has been updated to respect the new
``None`` types when detyping.
* The ``xonsh.tools.expandvars()`` function has been updated to respect
the new ``None`` types when detyping.
* The ``xonsh.xonfig.make_xonfig_wizard()`` function has been updated to respect
the new ``None`` types when detyping.
* Event handlers may now be added and discarded during event firing for
normal events. Such modifications will not be applied to until the
current firing operation is concluded. Thus you won't see newly added
events fired.
**Deprecated:**
* The ``xonsh.color_tools.make_pallete()`` function is no
longer deprecated, as it is actually needed in other parts of
xonsh still, such as ``pyghooks``.
**Removed:**
* All code references to ``$FORMATTER_DICT`` have been removed.
**Fixed:**
* Minor fixes to ``xonsh.events.debug_level()``.
**Security:**
* <news item>

View file

@ -1,25 +0,0 @@
**Added:**
* <news item>
**Changed:**
* <news item>
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* Fixed environments not showing in the prompt when using Anaconda Python.
* Fixed regression with anaconda activate/deactivate scripts not wokring on Windows.
**Security:**
* <news item>

View file

@ -1,26 +0,0 @@
**Added:**
* <news item>
**Changed:**
* xonsh now uses its own vended version of ply. Any installed versions will no longer be used. This reflects that ply is no
longer distributed as an installable packages.
* Updated to used ply version 3.11.
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* <news item>
**Security:**
* <news item>

View file

@ -1,10 +1,28 @@
#!/usr/bin/env xonsh
import sys
args = sys.argv[1:]
def replace_args(num):
"""
Replace %d to num for avoid overwrite files
Example of args: --junitxml=junit/test-results.%d.xml
"""
return [
(arg % num) if "%d" in arg else arg
for arg in args]
$RAISE_SUBPROC_ERROR = True
run_separately = [
'tests/test_main.py',
'tests/test_ptk_highlight.py',
]
![pytest @($ARGS[1:]) --ignore @(run_separately)]
ignores = []
for fname in run_separately:
![pytest @($ARGS[1:]) @(fname)]
ignores.append('--ignore')
ignores.append(fname)
![pytest @(replace_args(0)) @(ignores)]
for index, fname in enumerate(run_separately):
![pytest @(replace_args(index+1)) @(fname)]

View file

@ -7,4 +7,4 @@ if [ -z "${LC_ALL+x}" ] && [ -z "${LC_CTYPE+x}" ] && \
fi
# run python
exec /usr/bin/env PYTHONUNBUFFERED=1 python3 -u -m xonsh "$@"
exec python3 -u -m xonsh "$@"

View file

@ -1,3 +1,4 @@
#!/usr/bin/env python3 -u
from xonsh.main import main
main()

View file

@ -1,3 +1,4 @@
#!/usr/bin/env python3 -u
from xonsh.xoreutils.cat import cat_main as main
main()

View file

@ -325,8 +325,6 @@ if HAVE_SETUPTOOLS:
def main():
"""The main entry point."""
if sys.version_info[:2] < (3, 4):
sys.exit("xonsh currently requires Python 3.4+")
try:
if "--name" not in sys.argv:
logo_fname = os.path.join(os.path.dirname(__file__), "logo.txt")
@ -405,6 +403,7 @@ def main():
"linux": ["distro"],
"proctitle": ["setproctitle"],
}
skw["python_requires"] = ">=3.5"
setup(**skw)

View file

@ -0,0 +1,39 @@
import pytest
from xonsh.completers.pip import PIP_RE, PIP_LIST_RE
@pytest.mark.parametrize(
"line", ["pip", "xpip search", "$(pip", "![pip", "$[pip", "!(xpip"]
)
def test_pip_re(line):
assert PIP_RE.search(line)
@pytest.mark.parametrize(
"line",
[
"pip show",
"xpip uninstall",
"$(pip show",
"![pip uninstall",
"$[pip show",
"!(xpip uninstall",
],
)
def test_pip_list_re(line):
assert PIP_LIST_RE.search(line)
@pytest.mark.parametrize(
"line",
[
"bagpipes show",
"toxbagpip uninstall",
"$(tompippery show",
"![thewholepipandpaboodle uninstall",
"$[littlebopip show",
"!(boxpip uninstall",
],
)
def test_pip_list_re(line):
assert PIP_RE.search(line) is None

View file

@ -1,7 +1,72 @@
"""Tests ANSI color tools."""
import pytest
from xonsh.ansi_colors import ansi_color_escape_code_to_name, ansi_reverse_style
from xonsh.ansi_colors import (
ansi_color_escape_code_to_name,
ansi_reverse_style,
ansi_color_name_to_escape_code,
ansi_color_style_names,
)
DEFAULT_CMAP = {
# Reset
"NO_COLOR": "0", # Text Reset
# Regular Colors
"BLACK": "0;30", # BLACK
"RED": "0;31", # RED
"GREEN": "0;32", # GREEN
"YELLOW": "0;33", # YELLOW
"BLUE": "0;34", # BLUE
"PURPLE": "0;35", # PURPLE
"CYAN": "0;36", # CYAN
"WHITE": "0;37", # WHITE
# Background
"BACKGROUND_BLACK": "40", # BLACK
"BACKGROUND_RED": "41", # RED
"BACKGROUND_GREEN": "42", # GREEN
"BACKGROUND_YELLOW": "43", # YELLOW
"BACKGROUND_BLUE": "44", # BLUE
"BACKGROUND_PURPLE": "45", # PURPLE
"BACKGROUND_CYAN": "46", # CYAN
"BACKGROUND_WHITE": "47", # WHITE
# High Intensity
"INTENSE_BLACK": "90", # BLACK
"INTENSE_RED": "91", # RED
"INTENSE_GREEN": "92", # GREEN
"INTENSE_YELLOW": "93", # YELLOW
"INTENSE_BLUE": "94", # BLUE
"INTENSE_PURPLE": "95", # PURPLE
"INTENSE_CYAN": "96", # CYAN
"INTENSE_WHITE": "97", # WHITE
}
@pytest.mark.parametrize(
"name, exp",
[
("NO_COLOR", "0"),
("RED", "0;31"),
("BACKGROUND_RED", "41"),
("BACKGROUND_INTENSE_RED", "101"),
("BOLD_RED", "1;0;31"),
("UNDERLINE_RED", "4;0;31"),
("BOLD_UNDERLINE_RED", "1;4;0;31"),
("UNDERLINE_BOLD_RED", "4;1;0;31"),
# The hex code #000 can map to ANSI-256 0 or 16
("#000", {"38;5;0", "38;5;16"}),
("#000000", {"38;5;0", "38;5;16"}),
("BACKGROUND_#000", {"48;5;0", "48;5;16"}),
("BACKGROUND_#000000", {"48;5;0", "48;5;16"}),
("BG#000", {"48;5;0", "48;5;16"}),
("bg#000000", {"48;5;0", "48;5;16"}),
],
)
def test_ansi_color_name_to_escape_code_default(name, exp):
cmap = DEFAULT_CMAP.copy()
obs = ansi_color_name_to_escape_code(name, cmap=cmap)
assert obs in exp
RS = ansi_reverse_style(style="default")
@ -16,6 +81,7 @@ def test_ansi_reverse_style(key, value):
"inp, exp",
[
("0", ("NO_COLOR",)),
("1", ("BOLD_WHITE",)),
("\0010\002", ("NO_COLOR",)),
("\033[0m", ("NO_COLOR",)),
("\001\033[0m\002", ("NO_COLOR",)),
@ -23,7 +89,7 @@ def test_ansi_reverse_style(key, value):
("01;31", ("BOLD_RED",)),
("04;31", ("UNDERLINE_RED",)),
("1;4;31", ("BOLD_UNDERLINE_RED",)),
("4;1;31", ("BOLD_UNDERLINE_RED",)),
("4;1;31", ("UNDERLINE_BOLD_RED",)),
("31;42", ("RED", "BACKGROUND_GREEN")),
("42;31", ("BACKGROUND_GREEN", "RED")),
("40", ("BACKGROUND_BLACK",)),
@ -32,11 +98,38 @@ def test_ansi_reverse_style(key, value):
("38;2;170;0;0", ("RED",)),
("48;2;170;0;0", ("BACKGROUND_RED",)),
("1;38;5;124", ("BOLD_RED",)),
("4;1;38;2;170;0;0", ("BOLD_UNDERLINE_RED",)),
("4;1;38;2;170;0;0", ("UNDERLINE_BOLD_RED",)),
("1;38;5;40", ("BOLD_GREEN",)),
("48;5;16;38;5;184", ("BACKGROUND_BLACK", "INTENSE_YELLOW")),
("01;05;37;41", ("BOLD_SLOWBLINK_WHITE", "BACKGROUND_RED")),
("38;5;113;1", ("BOLD_INTENSE_GREEN",)),
("48;5;196;38;5;232;1", ("BACKGROUND_RED", "BOLD_BLACK")),
("48;5;3;38;5;0", ("BACKGROUND_YELLOW", "BLACK")),
(
"38;5;220;1;3;100",
("BOLD_ITALIC_INTENSE_YELLOW", "BACKGROUND_INTENSE_BLACK"),
),
(
"38;5;220;1;3;100;1",
("BOLD_ITALIC_BOLD_INTENSE_YELLOW", "BACKGROUND_INTENSE_BLACK"),
),
("48;5;235;38;5;139;3", ("BACKGROUND_BLACK", "ITALIC_WHITE")),
("38;5;111;4", ("UNDERLINE_WHITE",)),
],
)
def test_ansi_color_escape_code_to_name(inp, exp):
obs = ansi_color_escape_code_to_name(inp, "default", reversed_style=RS)
assert obs == exp
@pytest.mark.parametrize(
"color, style",
[
(color, style)
for color in DEFAULT_CMAP.keys()
for style in ansi_color_style_names()
],
)
def test_ansi_color_name_to_escape_code_for_all_styles(color, style):
escape_code = ansi_color_name_to_escape_code(color, style)
assert len(escape_code) > 0

View file

@ -2,11 +2,43 @@
import pytest
@pytest.mark.parametrize("inp, exp", [("x = 42", "x = 42"), ("!!", "ls")])
def test_preproc(inp, exp, xonsh_builtins):
@pytest.mark.parametrize(
"history, inp, exp", [
# No history:
([], '!!', ''),
([], '!$', ''),
([], '!^', ''),
([], '!*', ''),
([], '!echo', ''),
# No substitution:
(['aa 1 2', 'ab 3 4'], "ls", "ls"),
(['aa 1 2', 'ab 3 4'], "x = 42", "x = 42"),
(['aa 1 2', 'ab 3 4'], '!', '!'),
# Bang command only:
(['aa 1 2', 'ab 3 4'], "!!", "ab 3 4"),
(['aa 1 2', 'ab 3 4'], "!$", "4"),
(['aa 1 2', 'ab 3 4'], "!^", "ab"),
(['aa 1 2', 'ab 3 4'], "!*", "3 4"),
(['aa 1 2', 'ab 3 4'], "!a", "ab 3 4"),
(['aa 1 2', 'ab 3 4'], "!aa", "aa 1 2"),
(['aa 1 2', 'ab 3 4'], "!ab", "ab 3 4"),
# Bang command with others:
(['aa 1 2', 'ab 3 4'], "echo !! >log", "echo ab 3 4 >log"),
(['aa 1 2', 'ab 3 4'], "echo !$ >log", "echo 4 >log"),
(['aa 1 2', 'ab 3 4'], "echo !^ >log", "echo ab >log"),
(['aa 1 2', 'ab 3 4'], "echo !* >log", "echo 3 4 >log"),
(['aa 1 2', 'ab 3 4'], "echo !a >log", "echo ab 3 4 >log"),
(['aa 1 2', 'ab 3 4'], "echo !aa >log", "echo aa 1 2 >log"),
(['aa 1 2', 'ab 3 4'], "echo !ab >log", "echo ab 3 4 >log"),
]
)
def test_preproc(history, inp, exp, xonsh_builtins):
"""Test the bash preprocessor."""
from xontrib.bashisms import bash_preproc
xonsh_builtins.__xonsh__.history.inps = ["ls\n"]
xonsh_builtins.__xonsh__.history.inps = history
obs = bash_preproc(inp)
assert exp == obs

45
tests/test_color_tools.py Normal file
View file

@ -0,0 +1,45 @@
"""Tests color tools."""
import pytest
from xonsh.color_tools import iscolor
@pytest.mark.parametrize(
"inp, exp",
[
("NO_COLOR", True),
("CYAN", True),
("PURPLE", True),
("INTENSE_YELLOW", True),
("#fff", True),
("#FFF", True),
("#fafad2", True),
("#FAFAD2", True),
("BOLD_RED", True),
("BOLD_GREEN", True),
("UNDERLINE_RED", True),
("BOLD_UNDERLINE_RED", True),
("UNDERLINE_BOLD_RED", True),
("BACKGROUND_RED", True),
("BACKGROUND_GREEN", True),
("BACKGROUND_BLACK", True),
("BACKGROUND_PURPLE", True),
("BACKGROUND_INTENSE_RED", True),
("BACKGROUND_#123456", True),
("bg#fff", True),
("bg#fafad2", True),
("BG#fff", True),
("BG#fafad2", True),
("WAKKA", False),
("#F", False),
("#FAFAD", False),
("UNDERLINE_BACKGROUND_RED", False),
("BACKGROUND_BOLD_RED", False),
],
)
def test_iscolor(inp, exp):
obs = iscolor(inp)
if exp:
assert obs
else:
assert not obs

View file

@ -20,6 +20,12 @@ def test_commands_cache_lazy(xonsh_builtins):
assert 0 == cc.lazylen()
def test_predict_threadable_unknown_command(xonsh_builtins):
cc = CommandsCache()
result = cc.predict_threadable(["command_should_not_found"])
assert isinstance(result, bool)
TRUE_SHELL_ARGS = [
["-c", "yo"],
["-c=yo"],

View file

@ -68,7 +68,7 @@ def test_env_detype_mutable_access_clear(path1, path2):
def test_env_detype_no_dict():
env = Env(YO={"hey": 42})
env.set_ensurer('YO', Ensurer(always_true, None, None))
env.set_ensurer("YO", Ensurer(always_true, None, None))
det = env.detype()
assert "YO" not in det
@ -273,3 +273,22 @@ def test_make_args_env():
"ARG3": "3",
}
assert exp == obs
def test_delitem():
env = Env(VAR="a value")
assert env["VAR"] == "a value"
del env["VAR"]
with pytest.raises(Exception):
a = env["VAR"]
def test_delitem_default():
env = Env()
a_key, a_value = next(
(k, v) for (k, v) in env._defaults.items() if isinstance(v, str)
)
del env[a_key]
assert env[a_key] == a_value
del env[a_key]
assert env[a_key] == a_value

View file

@ -33,7 +33,7 @@ def test_rmtree():
git config user.name "Code Monkey"
touch thing.txt
git add thing.txt
git commit -am "add thing"
git commit -a --no-gpg-sign -m "add thing"
popd
assert os.path.exists('rmtree_test')
assert os.path.exists('rmtree_test/thing.txt')

View file

@ -4,6 +4,7 @@ from __future__ import unicode_literals, print_function
from contextlib import contextmanager
import builtins
import gc
import os
import os.path
import sys
@ -22,7 +23,13 @@ def Shell(*args, **kwargs):
@pytest.fixture
def shell(xonsh_builtins, monkeypatch):
"""Xonsh Shell Mock"""
del builtins.__xonsh__
if hasattr(builtins, "__xonsh__"):
builtins.__xonsh__.unlink_builtins()
del builtins.__xonsh__
for xarg in dir(builtins):
if "__xonsh_" in xarg:
delattr(builtins, xarg)
gc.collect()
Shell.shell_type_aliases = {"rl": "readline"}
monkeypatch.setattr(xonsh.main, "Shell", Shell)

View file

@ -7,11 +7,11 @@ import itertools
import pytest
from xonsh.ast import AST, With, Pass, pdump
from xonsh.ast import AST, With, Pass, pdump, Str, Call
from xonsh.parser import Parser
from xonsh.parsers.base import eval_fstr_fields
from tools import VER_FULL, skip_if_py34, skip_if_lt_py36, nodes_equal
from tools import VER_FULL, skip_if_lt_py36, nodes_equal
# a lot of col_offset data changed from Py v3.5.0 -> v3.5.1
INC_ATTRS = (3, 5, 1) <= VER_FULL
@ -186,7 +186,6 @@ def test_binop_times():
check_ast("42 * 65")
@skip_if_py34
def test_binop_matmult():
check_ast("x @ y", False)
@ -682,57 +681,46 @@ def test_dict_three():
check_ast("{42: 65, 6: 28, 1: 2}")
@skip_if_py34
def test_dict_from_dict_two_xy():
check_ast('{"x": 1, **{"y": 2}}')
@skip_if_py34
def test_dict_from_dict_two_x_first():
check_ast('{"x": 1, **{"x": 2}}')
@skip_if_py34
def test_dict_from_dict_two_x_second():
check_ast('{**{"x": 2}, "x": 1}')
@skip_if_py34
def test_unpack_range_tuple():
check_stmts("*range(4),")
@skip_if_py34
def test_unpack_range_tuple_4():
check_stmts("*range(4), 4")
@skip_if_py34
def test_unpack_range_tuple_parens():
check_ast("(*range(4),)")
@skip_if_py34
def test_unpack_range_tuple_parens_4():
check_ast("(*range(4), 4)")
@skip_if_py34
def test_unpack_range_list():
check_ast("[*range(4)]")
@skip_if_py34
def test_unpack_range_list_4():
check_ast("[*range(4), 4]")
@skip_if_py34
def test_unpack_range_set():
check_ast("{*range(4)}")
@skip_if_py34
def test_unpack_range_set_4():
check_ast("{*range(4), 4}")
@ -1097,17 +1085,14 @@ def test_call_dict_kwargs():
check_ast('dict(**{"base": 8})')
@skip_if_py34
def test_call_list_many_star_args():
check_ast("min(*[1, 2], 3, *[4, 5])")
@skip_if_py34
def test_call_list_many_starstar_args():
check_ast('dict(**{"a": 2}, v=3, **{"c": 5})')
@skip_if_py34
def test_call_list_many_star_and_starstar_args():
check_ast('x(*[("a", 2)], *[("v", 3)], **{"c": 5})', False)
@ -1253,7 +1238,6 @@ def test_times_eq():
check_stmts("x = 42; x *= 2")
@skip_if_py34
def test_matmult_eq():
check_stmts("x @= y", False)
@ -1649,7 +1633,6 @@ def test_for_else():
check_stmts("for x in range(6):\n pass\nelse: pass")
@skip_if_py34
def test_async_for():
check_stmts("async def f():\n async for x in y:\n pass\n", False)
@ -1678,7 +1661,6 @@ def test_with_in_func():
check_stmts("def f():\n with x:\n pass\n")
@skip_if_py34
def test_async_with():
check_stmts("async def f():\n async with x as y:\n pass\n", False)
@ -2014,17 +1996,14 @@ def test_function_blank_line():
check_stmts(code, False)
@skip_if_py34
def test_async_func():
check_stmts("async def f():\n pass\n")
@skip_if_py34
def test_async_decorator():
check_stmts("@g\nasync def f():\n pass", False)
@skip_if_py34
def test_async_await():
check_stmts("async def f():\n await fut\n", False)
@ -2889,6 +2868,20 @@ def test_withbang_as_many_suite(body):
assert s == body
def test_subproc_raw_str_literal():
tree = check_xonsh_ast({}, "!(echo '$foo')", run=False, return_obs=True)
assert isinstance(tree, AST)
subproc = tree.body
assert isinstance(subproc.args[0].elts[1], Call)
assert subproc.args[0].elts[1].func.attr == "expand_path"
tree = check_xonsh_ast({}, "!(echo r'$foo')", run=False, return_obs=True)
assert isinstance(tree, AST)
subproc = tree.body
assert isinstance(subproc.args[0].elts[1], Str)
assert subproc.args[0].elts[1].s == "$foo"
# test invalid expressions

View file

@ -9,7 +9,7 @@ from xonsh.environ import Env
from xonsh.prompt.base import PromptFormatter, PROMPT_FIELDS
from xonsh.prompt import vc
from tools import skip_if_py34, DummyEnv
from tools import DummyEnv
@pytest.fixture
@ -94,7 +94,7 @@ def test_format_prompt_with_invalid_func(formatter, xonsh_builtins):
def test_format_prompt_with_func_that_raises(formatter, capsys, xonsh_builtins):
xonsh_builtins.__xonsh__.env = Env()
template = "tt {zerodiv} tt"
exp = "tt (ERROR:zerodiv) tt"
exp = "tt {BACKGROUND_RED}{ERROR:zerodiv}{NO_COLOR} tt"
fields = {"zerodiv": lambda: 1 / 0}
obs = formatter(template, fields)
assert exp == obs
@ -209,7 +209,7 @@ def test_repo(request):
with open("test-file", "w"):
pass
sp.call(["git", "add", "test-file"])
sp.call(["git", "commit", "-m", "test commit"])
sp.call(["git", "commit", "--no-gpg-sign", "-m", "test commit"])
return {"name": vc, "dir": temp_dir}

View file

@ -2,6 +2,7 @@
"""Test XonshLexer for pygments"""
import os
import gc
import builtins
import pytest
@ -25,12 +26,12 @@ from xonsh.pyghooks import XonshLexer
@pytest.fixture(autouse=True)
def load_command_cache(xonsh_builtins):
gc.collect()
unload_builtins()
load_builtins()
if ON_WINDOWS:
for key in ("cd", "bash"):
builtins.aliases[key] = lambda *args, **kwargs: None
yield
unload_builtins()
def check_token(code, tokens):

93
tests/test_pyghooks.py Normal file
View file

@ -0,0 +1,93 @@
"""Tests pygments hooks."""
import pytest
from xonsh.pyghooks import Color, color_name_to_pygments_code, code_by_name
DEFAULT_STYLES = {
# Reset
Color.NO_COLOR: "noinherit", # Text Reset
# Regular Colors
Color.BLACK: "ansiblack",
Color.BLUE: "ansiblue",
Color.CYAN: "ansicyan",
Color.GREEN: "ansigreen",
Color.PURPLE: "ansimagenta",
Color.RED: "ansired",
Color.WHITE: "ansigray",
Color.YELLOW: "ansiyellow",
Color.INTENSE_BLACK: "ansibrightblack",
Color.INTENSE_BLUE: "ansibrightblue",
Color.INTENSE_CYAN: "ansibrightcyan",
Color.INTENSE_GREEN: "ansibrightgreen",
Color.INTENSE_PURPLE: "ansibrightmagenta",
Color.INTENSE_RED: "ansibrightred",
Color.INTENSE_WHITE: "ansiwhite",
Color.INTENSE_YELLOW: "ansibrightyellow",
}
@pytest.mark.parametrize(
"name, exp",
[
("NO_COLOR", "noinherit"),
("RED", "ansired"),
("BACKGROUND_RED", "bg:ansired"),
("BACKGROUND_INTENSE_RED", "bg:ansibrightred"),
("BOLD_RED", "bold ansired"),
("UNDERLINE_RED", "underline ansired"),
("BOLD_UNDERLINE_RED", "bold underline ansired"),
("UNDERLINE_BOLD_RED", "underline bold ansired"),
# test unsupported modifiers
("BOLD_FAINT_RED", "bold ansired"),
("BOLD_SLOWBLINK_RED", "bold ansired"),
("BOLD_FASTBLINK_RED", "bold ansired"),
("BOLD_INVERT_RED", "bold ansired"),
("BOLD_CONCEAL_RED", "bold ansired"),
("BOLD_STRIKETHROUGH_RED", "bold ansired"),
# test hexes
("#000", "#000"),
("#000000", "#000000"),
("BACKGROUND_#000", "bg:#000"),
("BACKGROUND_#000000", "bg:#000000"),
("BG#000", "bg:#000"),
("bg#000000", "bg:#000000"),
],
)
def test_color_name_to_pygments_code(name, exp):
styles = DEFAULT_STYLES.copy()
obs = color_name_to_pygments_code(name, styles)
assert obs == exp
@pytest.mark.parametrize(
"name, exp",
[
("NO_COLOR", "noinherit"),
("RED", "ansired"),
("BACKGROUND_RED", "bg:ansired"),
("BACKGROUND_INTENSE_RED", "bg:ansibrightred"),
("BOLD_RED", "bold ansired"),
("UNDERLINE_RED", "underline ansired"),
("BOLD_UNDERLINE_RED", "bold underline ansired"),
("UNDERLINE_BOLD_RED", "underline bold ansired"),
# test unsupported modifiers
("BOLD_FAINT_RED", "bold ansired"),
("BOLD_SLOWBLINK_RED", "bold ansired"),
("BOLD_FASTBLINK_RED", "bold ansired"),
("BOLD_INVERT_RED", "bold ansired"),
("BOLD_CONCEAL_RED", "bold ansired"),
("BOLD_STRIKETHROUGH_RED", "bold ansired"),
# test hexes
("#000", "#000"),
("#000000", "#000000"),
("BACKGROUND_#000", "bg:#000"),
("BACKGROUND_#000000", "bg:#000000"),
("BG#000", "bg:#000"),
("bg#000000", "bg:#000000"),
],
)
def test_code_by_name(name, exp):
styles = DEFAULT_STYLES.copy()
obs = code_by_name(name, styles)
assert obs == exp

View file

@ -72,10 +72,11 @@ from xonsh.tools import (
is_writable_file,
balanced_parens,
iglobpath,
all_permutations,
)
from xonsh.environ import Env
from tools import skip_if_on_windows, skip_if_on_unix, skip_if_py34
from tools import skip_if_on_windows, skip_if_on_unix
LEXER = Lexer()
LEXER.build()
@ -1652,7 +1653,6 @@ def test_iglobpath_no_dotfiles_recursive(xonsh_builtins):
assert d + "/bin/.someotherdotfile" not in files
@skip_if_py34
@skip_if_on_windows
def test_iglobpath_dotfiles_recursive(xonsh_builtins):
d = os.path.dirname(__file__)
@ -1676,3 +1676,25 @@ def test_iglobpath_empty_str(monkeypatch, xonsh_builtins):
monkeypatch.setattr(os, "listdir", mocklistdir)
paths = list(iglobpath("some/path"))
assert len(paths) == 0
def test_all_permutations():
obs = {"".join(p) for p in all_permutations("ABC")}
exp = {
"A",
"B",
"C",
"AB",
"AC",
"BA",
"BC",
"CA",
"CB",
"ACB",
"CBA",
"BAC",
"CAB",
"BCA",
"ABC",
}
assert obs == exp

View file

@ -1,9 +1,13 @@
import io
import os
import tempfile
import pytest
from xonsh.xoreutils import _which
from xonsh.xoreutils import uptime
from xonsh.xoreutils import cat
from xonsh.tools import ON_WINDOWS
from xonsh.platform import DEFAULT_ENCODING
class TestWhich:
@ -100,3 +104,122 @@ def test_boottime():
assert bt > 0.0
assert uptime._BOOTTIME is not None
assert uptime._BOOTTIME > 0.0
@pytest.fixture
def cat_env_fixture(xonsh_builtins):
with xonsh_builtins.__xonsh__.env.swap(
XONSH_ENCODING=DEFAULT_ENCODING,
XONSH_ENCODING_ERRORS="surrogateescape"):
yield xonsh_builtins
class CatLimitedBuffer(io.BytesIO):
"""
This object cause KeyboardInterrupt when reached expected buffer size
"""
def __init__(self, limit=500, *args, **kwargs):
super().__init__(*args, **kwargs)
self.limited_size = limit
self.already_raised = False
def write(self, *args, **kwargs):
super().write(*args, **kwargs)
if not self.already_raised and self.tell() >= self.limited_size:
self.already_raised = True
raise KeyboardInterrupt()
class TestCatLimitedBuffer:
def test_write_buffer_correctly(self):
buf = CatLimitedBuffer(limit=500)
buf.write(b'0' * 499)
assert buf.getvalue() == b'0' * 499
def test_raise_keyboardinterrupt_when_reached(self):
buf = CatLimitedBuffer(limit=500)
buf.write(b'0' * 499)
with pytest.raises(KeyboardInterrupt):
buf.write(b'1')
def test_raise_allow_write_over_limit(self):
buf = CatLimitedBuffer(limit=500)
buf.write(b'0' * 400)
with pytest.raises(KeyboardInterrupt):
buf.write(b'1' * 200)
assert buf.getvalue() == (b'0' * 400 + b'1' * 200)
def test_not_raise_twice_time(self):
buf = CatLimitedBuffer(limit=500)
with pytest.raises(KeyboardInterrupt):
buf.write(b'1' * 1000)
try:
buf.write(b'2')
except KeyboardInterrupt:
pytest.fail("Unexpected KeyboardInterrupt")
class TestCat:
tempfile = None
def setup_method(self, _method):
import tempfile
tmpfile = tempfile.mkstemp()
self.tempfile = tmpfile[1]
os.close(tmpfile[0])
def teardown_method(self, _method):
os.remove(self.tempfile)
def test_cat_single_file_work_exist_content(self, cat_env_fixture):
content = "this is a content\nfor testing xoreutil's cat"
with open(self.tempfile, "w") as f:
f.write(content)
expected_content = content.replace("\n", os.linesep)
stdin = io.StringIO()
stdout_buf = io.BytesIO()
stderr_buf = io.BytesIO()
stdout = io.TextIOWrapper(stdout_buf)
stderr = io.TextIOWrapper(stderr_buf)
opts = cat._cat_parse_args([])
cat._cat_single_file(opts, self.tempfile, stdin, stdout, stderr)
stdout.flush()
stderr.flush()
assert stdout_buf.getvalue() == bytes(expected_content, "utf-8")
assert stderr_buf.getvalue() == b''
def test_cat_empty_file(self, cat_env_fixture):
with open(self.tempfile, "w") as f:
f.write("")
stdin = io.StringIO()
stdout_buf = io.BytesIO()
stderr_buf = io.BytesIO()
stdout = io.TextIOWrapper(stdout_buf)
stderr = io.TextIOWrapper(stderr_buf)
opts = cat._cat_parse_args([])
cat._cat_single_file(opts, self.tempfile, stdin, stdout, stderr)
stdout.flush()
stderr.flush()
assert stdout_buf.getvalue() == b''
assert stderr_buf.getvalue() == b''
@pytest.mark.skipif(not os.path.exists("/dev/urandom"),
reason="/dev/urandom doesn't exists")
def test_cat_dev_urandom(self, cat_env_fixture):
"""
test of cat (pseudo) device.
"""
stdin = io.StringIO()
stdout_buf = CatLimitedBuffer(limit=500)
stderr_buf = io.BytesIO()
stdout = io.TextIOWrapper(stdout_buf)
stderr = io.TextIOWrapper(stderr_buf)
opts = cat._cat_parse_args([])
cat._cat_single_file(opts, "/dev/urandom", stdin, stdout, stderr)
stdout.flush()
stderr.flush()
assert len(stdout_buf.getvalue()) >= 500

View file

@ -18,7 +18,6 @@ from xonsh.base_shell import BaseShell
from xonsh.platform import ptk_version_info
VER_3_4 = (3, 4)
VER_3_5 = (3, 5)
VER_3_6 = (3, 6)
VER_MAJOR_MINOR = sys.version_info[:2]
@ -36,7 +35,6 @@ print("os.environ['TF_BUILD']", repr(os.environ.get("TF_BUILD", "")))
TEST_DIR = os.path.dirname(__file__)
# pytest skip decorators
skip_if_py34 = pytest.mark.skipif(VER_MAJOR_MINOR < VER_3_5, reason="Py3.5+ only test")
skip_if_lt_py36 = pytest.mark.skipif(
VER_MAJOR_MINOR < VER_3_6, reason="Py3.6+ only test"
)

View file

@ -9,7 +9,7 @@ program_description = """Build and run Xonsh in a fresh, controlled
parser = argparse.ArgumentParser(description=program_description)
parser.add_argument("env", nargs="*", default=[], metavar="ENV=value")
parser.add_argument("--python", "-p", default="3.4", metavar="python_version")
parser.add_argument("--python", "-p", default="3.5", metavar="python_version")
parser.add_argument("--pypy", default=None, metavar="pypy_version")
parser.add_argument("--ptk", "-t", default="2.0.4", metavar="ptk_version")
parser.add_argument("--keep", action="store_true")

View file

@ -1,4 +1,4 @@
__version__ = "0.8.10"
__version__ = "0.9.6"
# amalgamate exclude jupyter_kernel parser_table parser_test_table pyghooks

View file

@ -208,6 +208,7 @@ class PartialEvalAliasBase:
"""
self.f = f
self.acc_args = acc_args
self.__name__ = getattr(f, "__name__", self.__class__.__name__)
def __call__(
self, args, stdin=None, stdout=None, stderr=None, spec=None, stack=None

View file

@ -7,17 +7,97 @@ import builtins
from xonsh.platform import HAS_PYGMENTS
from xonsh.lazyasd import LazyDict, lazyobject
from xonsh.color_tools import (
RE_BACKGROUND,
RE_XONSH_COLOR,
BASE_XONSH_COLORS,
make_palette,
find_closest_color,
rgb2short,
rgb_to_256,
short_to_ints,
iscolor,
)
from xonsh.tools import FORMATTER
def _ensure_color_map(style="default", cmap=None):
if cmap is not None:
pass
elif style in ANSI_STYLES:
cmap = ANSI_STYLES[style]
else:
try: # dynamically loading the style
cmap = ansi_style_by_name(style)
except Exception:
msg = "Could not find color style {0!r}, using default."
print(msg.format(style), file=sys.stderr)
builtins.__xonsh__.env["XONSH_COLOR_STYLE"] = "default"
cmap = ANSI_STYLES["default"]
return cmap
@lazyobject
def ANSI_ESCAPE_MODIFIERS():
return {
"BOLD": "1",
"FAINT": "2",
"ITALIC": "3",
"UNDERLINE": "4",
"SLOWBLINK": "5",
"FASTBLINK": "6",
"INVERT": "7",
"CONCEAL": "8",
"STRIKETHROUGH": "9",
}
def ansi_color_name_to_escape_code(name, style="default", cmap=None):
"""Converts a color name to the inner part of an ANSI escape code"""
cmap = _ensure_color_map(style=style, cmap=cmap)
if name in cmap:
return cmap[name]
m = RE_XONSH_COLOR.match(name)
if m is None:
raise ValueError("{!r} is not a color!".format(name))
parts = m.groupdict()
# convert regex match into actual ANSI colors
if parts["nocolor"] is not None:
res = "0"
elif parts["bghex"] is not None:
res = "48;5;" + rgb_to_256(parts["bghex"][3:])[0]
elif parts["background"] is not None:
color = parts["color"]
if "#" in color:
res = "48;5;" + rgb_to_256(color[1:])[0]
else:
fgcolor = cmap[color]
if fgcolor.isdecimal():
res = str(int(fgcolor) + 10)
elif fgcolor.startswith("38;"):
res = "4" + fgcolor[1:]
else:
msg = (
"when converting {!r}, did not recognize {!r} within "
"the following color map as a valid color:\n\n{!r}"
)
raise ValueError(msg.format(name, fgcolor, cmap))
else:
# have regular, non-background color
mods = parts["modifiers"]
if mods is None:
mods = []
else:
mods = mods.strip("_").split("_")
mods = [ANSI_ESCAPE_MODIFIERS[mod] for mod in mods]
color = parts["color"]
if "#" in color:
mods.append("38;5;" + rgb_to_256(color[1:])[0])
else:
mods.append(cmap[color])
res = ";".join(mods)
cmap[name] = res
return res
def ansi_partial_color_format(template, style="default", cmap=None, hide=False):
"""Formats a template string but only with respect to the colors.
Another template string is returned, with the color values filled in.
@ -49,18 +129,7 @@ def ansi_partial_color_format(template, style="default", cmap=None, hide=False):
def _ansi_partial_color_format_main(template, style="default", cmap=None, hide=False):
if cmap is not None:
pass
elif style in ANSI_STYLES:
cmap = ANSI_STYLES[style]
else:
try: # dynamically loading the style
cmap = ansi_style_by_name(style)
except Exception:
msg = "Could not find color style {0!r}, using default."
print(msg.format(style), file=sys.stderr)
builtins.__xonsh__.env["XONSH_COLOR_STYLE"] = "default"
cmap = ANSI_STYLES["default"]
cmap = _ensure_color_map(style=style, cmap=cmap)
esc = ("\001" if hide else "") + "\033["
m = "m" + ("\002" if hide else "")
bopen = "{"
@ -74,18 +143,9 @@ def _ansi_partial_color_format_main(template, style="default", cmap=None, hide=F
pass
elif field in cmap:
toks.extend([esc, cmap[field], m])
elif "#" in field:
field = field.lower()
pre, _, post = field.partition("#")
f_or_b = "38" if RE_BACKGROUND.search(pre) is None else "48"
rgb, _, post = post.partition("_")
c256, _ = rgb_to_256(rgb)
color = f_or_b + ";5;" + c256
mods = pre + "_" + post
if "underline" in mods:
color = "4;" + color
if "bold" in mods:
color = "1;" + color
elif iscolor(field):
color = ansi_color_name_to_escape_code(field, cmap=cmap)
cmap[field] = color
toks.extend([esc, color, m])
elif field is not None:
toks.append(bopen)
@ -127,16 +187,19 @@ def ansi_reverse_style(style="default", return_style=False):
updates = {
"1": "BOLD_",
"2": "FAINT_",
"3": "ITALIC_",
"4": "UNDERLINE_",
"5": "SLOWBLINK_",
"1;4": "BOLD_UNDERLINE_",
"4;1": "BOLD_UNDERLINE_",
"6": "FASTBLINK_",
"7": "INVERT_",
"8": "CONCEAL_",
"9": "STRIKETHROUGH_",
"38": "SET_FOREGROUND_",
"48": "SET_BACKGROUND_",
"38;2": "SET_FOREGROUND_3INTS_",
"48;2": "SET_BACKGROUND_3INTS_",
"38;5": "SET_FOREGROUND_SHORT_",
"48;5": "SET_BACKGROUND_SHORT_",
"38;2": "SET_FOREGROUND_FAINT_",
"48;2": "SET_BACKGROUND_FAINT_",
"38;5": "SET_FOREGROUND_SLOWBLINK_",
"48;5": "SET_BACKGROUND_SLOWBLINK_",
}
for ec, name in reversed_style.items():
no_left_zero = ec.lstrip("0")
@ -157,31 +220,14 @@ def ANSI_ESCAPE_CODE_RE():
return re.compile(r"\001?(\033\[)?([0-9;]+)m?\002?")
@lazyobject
def ANSI_REVERSE_COLOR_NAME_TRANSLATIONS():
base = {
"SET_FOREGROUND_FAINT_": "SET_FOREGROUND_3INTS_",
"SET_BACKGROUND_FAINT_": "SET_BACKGROUND_3INTS_",
"SET_FOREGROUND_SLOWBLINK_": "SET_FOREGROUND_SHORT_",
"SET_BACKGROUND_SLOWBLINK_": "SET_BACKGROUND_SHORT_",
}
data = {"UNDERLINE_BOLD_": "BOLD_UNDERLINE_"}
data.update(base)
data.update({"BOLD_" + k: "BOLD_" + v for k, v in base.items()})
data.update({"UNDERLINE_" + k: "UNDERLINE_" + v for k, v in base.items()})
data.update({"BOLD_UNDERLINE_" + k: "BOLD_UNDERLINE_" + v for k, v in base.items()})
data.update({"UNDERLINE_BOLD_" + k: "BOLD_UNDERLINE_" + v for k, v in base.items()})
return data
@lazyobject
def ANSI_COLOR_NAME_SET_3INTS_RE():
return re.compile(r"(\w+_)?SET_(FORE|BACK)GROUND_3INTS_(\d+)_(\d+)_(\d+)")
return re.compile(r"(\w+_)?SET_(FORE|BACK)GROUND_FAINT_(\d+)_(\d+)_(\d+)")
@lazyobject
def ANSI_COLOR_NAME_SET_SHORT_RE():
return re.compile(r"(\w+_)?SET_(FORE|BACK)GROUND_SHORT_(\d+)")
return re.compile(r"(\w+_)?SET_(FORE|BACK)GROUND_SLOWBLINK_(\d+)")
def _color_name_from_ints(ints, background=False, prefix=None):
@ -210,7 +256,14 @@ def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
if reversed_style is None:
style, reversed_style = ansi_reverse_style(style, return_style=True)
# strip some actual escape codes, if needed.
ec = ANSI_ESCAPE_CODE_RE.match(escape_code).group(2)
match = ANSI_ESCAPE_CODE_RE.match(escape_code)
if not match:
msg = 'Invalid ANSI color sequence "{0}", using "NO_COLOR" instead.'.format(
escape_code
)
warnings.warn(msg, RuntimeWarning)
return ("NO_COLOR",)
ec = match.group(2)
names = []
n_ints = 0
seen_set_foreback = False
@ -234,13 +287,15 @@ def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
# normalize names
n = ""
norm_names = []
colors = set(reversed_style.values())
prefixes = ""
for name in names:
if name == "NO_COLOR":
# skip most '0' entries
continue
elif "BACKGROUND_" in name and n:
prefixes += n
n = ""
n = n + name if n else name
n = ANSI_REVERSE_COLOR_NAME_TRANSLATIONS.get(n, n)
if n.endswith("_"):
continue
elif ANSI_COLOR_NAME_SET_SHORT_RE.match(n) is not None:
@ -253,12 +308,12 @@ def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
n = _color_name_from_ints(
(int(r), int(g), int(b)), background=(fore_back == "BACK"), prefix=pre
)
elif "GROUND_3INTS_" in n:
elif "GROUND_FAINT_" in n:
# have 1 or 2, but not 3 ints
n += "_"
continue
# error check
if n not in colors:
if not iscolor(n):
msg = (
"Could not translate ANSI color code {escape_code!r} "
"into a known color in the palette. Specifically, the {n!r} "
@ -269,6 +324,16 @@ def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
)
norm_names.append(n)
n = ""
# check if we have pre- & post-fixes to apply to the last, non-background element
prefixes += n
if prefixes.endswith("_"):
for i in range(-1, -len(norm_names) - 1, -1):
if "BACKGROUND_" not in norm_names[i]:
norm_names[i] = prefixes + norm_names[i]
break
else:
# only have background colors, so select WHITE as default color
norm_names.append(prefixes + "WHITE")
# return
if len(norm_names) == 0:
return ("NO_COLOR",)
@ -276,29 +341,25 @@ def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
return tuple(norm_names)
def _ansi_expand_style(cmap):
"""Expands a style in order to more quickly make color map changes."""
for key, val in list(cmap.items()):
if key == "NO_COLOR":
continue
elif len(val) == 0:
cmap["BOLD_" + key] = "1"
cmap["UNDERLINE_" + key] = "4"
cmap["BOLD_UNDERLINE_" + key] = "1;4"
cmap["BACKGROUND_" + key] = val
else:
cmap["BOLD_" + key] = "1;" + val
cmap["UNDERLINE_" + key] = "4;" + val
cmap["BOLD_UNDERLINE_" + key] = "1;4;" + val
cmap["BACKGROUND_" + key] = val.replace("38", "48", 1)
def _bw_style():
style = {
"NO_COLOR": "0",
"BLACK": "0;30",
"BLUE": "0;37",
"CYAN": "0;37",
"GREEN": "0;37",
"PURPLE": "0;37",
"RED": "0;37",
"WHITE": "0;37",
"YELLOW": "0;37",
"BACKGROUND_BLACK": "40",
"BACKGROUND_RED": "47",
"BACKGROUND_GREEN": "47",
"BACKGROUND_YELLOW": "47",
"BACKGROUND_BLUE": "47",
"BACKGROUND_PURPLE": "47",
"BACKGROUND_CYAN": "47",
"BACKGROUND_WHITE": "47",
"INTENSE_BLACK": "0;90",
"INTENSE_BLUE": "0;97",
"INTENSE_CYAN": "0;97",
@ -307,13 +368,7 @@ def _bw_style():
"INTENSE_RED": "0;97",
"INTENSE_WHITE": "0;97",
"INTENSE_YELLOW": "0;97",
"NO_COLOR": "0",
"PURPLE": "0;37",
"RED": "0;37",
"WHITE": "0;37",
"YELLOW": "0;37",
}
_ansi_expand_style(style)
return style
@ -330,33 +385,6 @@ def _default_style():
"PURPLE": "0;35", # PURPLE
"CYAN": "0;36", # CYAN
"WHITE": "0;37", # WHITE
# Bold
"BOLD_BLACK": "1;30", # BLACK
"BOLD_RED": "1;31", # RED
"BOLD_GREEN": "1;32", # GREEN
"BOLD_YELLOW": "1;33", # YELLOW
"BOLD_BLUE": "1;34", # BLUE
"BOLD_PURPLE": "1;35", # PURPLE
"BOLD_CYAN": "1;36", # CYAN
"BOLD_WHITE": "1;37", # WHITE
# Underline
"UNDERLINE_BLACK": "4;30", # BLACK
"UNDERLINE_RED": "4;31", # RED
"UNDERLINE_GREEN": "4;32", # GREEN
"UNDERLINE_YELLOW": "4;33", # YELLOW
"UNDERLINE_BLUE": "4;34", # BLUE
"UNDERLINE_PURPLE": "4;35", # PURPLE
"UNDERLINE_CYAN": "4;36", # CYAN
"UNDERLINE_WHITE": "4;37", # WHITE
# Bold, Underline
"BOLD_UNDERLINE_BLACK": "1;4;30", # BLACK
"BOLD_UNDERLINE_RED": "1;4;31", # RED
"BOLD_UNDERLINE_GREEN": "1;4;32", # GREEN
"BOLD_UNDERLINE_YELLOW": "1;4;33", # YELLOW
"BOLD_UNDERLINE_BLUE": "1;4;34", # BLUE
"BOLD_UNDERLINE_PURPLE": "1;4;35", # PURPLE
"BOLD_UNDERLINE_CYAN": "1;4;36", # CYAN
"BOLD_UNDERLINE_WHITE": "1;4;37", # WHITE
# Background
"BACKGROUND_BLACK": "40", # BLACK
"BACKGROUND_RED": "41", # RED
@ -375,33 +403,6 @@ def _default_style():
"INTENSE_PURPLE": "0;95", # PURPLE
"INTENSE_CYAN": "0;96", # CYAN
"INTENSE_WHITE": "0;97", # WHITE
# Bold High Intensity
"BOLD_INTENSE_BLACK": "1;90", # BLACK
"BOLD_INTENSE_RED": "1;91", # RED
"BOLD_INTENSE_GREEN": "1;92", # GREEN
"BOLD_INTENSE_YELLOW": "1;93", # YELLOW
"BOLD_INTENSE_BLUE": "1;94", # BLUE
"BOLD_INTENSE_PURPLE": "1;95", # PURPLE
"BOLD_INTENSE_CYAN": "1;96", # CYAN
"BOLD_INTENSE_WHITE": "1;97", # WHITE
# Underline High Intensity
"UNDERLINE_INTENSE_BLACK": "4;90", # BLACK
"UNDERLINE_INTENSE_RED": "4;91", # RED
"UNDERLINE_INTENSE_GREEN": "4;92", # GREEN
"UNDERLINE_INTENSE_YELLOW": "4;93", # YELLOW
"UNDERLINE_INTENSE_BLUE": "4;94", # BLUE
"UNDERLINE_INTENSE_PURPLE": "4;95", # PURPLE
"UNDERLINE_INTENSE_CYAN": "4;96", # CYAN
"UNDERLINE_INTENSE_WHITE": "4;97", # WHITE
# Bold Underline High Intensity
"BOLD_UNDERLINE_INTENSE_BLACK": "1;4;90", # BLACK
"BOLD_UNDERLINE_INTENSE_RED": "1;4;91", # RED
"BOLD_UNDERLINE_INTENSE_GREEN": "1;4;92", # GREEN
"BOLD_UNDERLINE_INTENSE_YELLOW": "1;4;93", # YELLOW
"BOLD_UNDERLINE_INTENSE_BLUE": "1;4;94", # BLUE
"BOLD_UNDERLINE_INTENSE_PURPLE": "1;4;95", # PURPLE
"BOLD_UNDERLINE_INTENSE_CYAN": "1;4;96", # CYAN
"BOLD_UNDERLINE_INTENSE_WHITE": "1;4;97", # WHITE
# High Intensity backgrounds
"BACKGROUND_INTENSE_BLACK": "0;100", # BLACK
"BACKGROUND_INTENSE_RED": "0;101", # RED
@ -435,7 +436,6 @@ def _monokai_style():
"INTENSE_WHITE": "38;5;15",
"INTENSE_YELLOW": "38;5;186",
}
_ansi_expand_style(style)
return style
@ -464,7 +464,6 @@ def _algol_style():
"WHITE": "38;5;102",
"YELLOW": "38;5;09",
}
_ansi_expand_style(style)
return style
@ -488,7 +487,6 @@ def _algol_nu_style():
"WHITE": "38;5;102",
"YELLOW": "38;5;09",
}
_ansi_expand_style(style)
return style
@ -512,7 +510,6 @@ def _autumn_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;130",
}
_ansi_expand_style(style)
return style
@ -536,7 +533,6 @@ def _borland_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;124",
}
_ansi_expand_style(style)
return style
@ -560,7 +556,6 @@ def _colorful_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;130",
}
_ansi_expand_style(style)
return style
@ -584,7 +579,6 @@ def _emacs_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;130",
}
_ansi_expand_style(style)
return style
@ -608,7 +602,6 @@ def _friendly_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;166",
}
_ansi_expand_style(style)
return style
@ -632,7 +625,6 @@ def _fruity_style():
"WHITE": "38;5;187",
"YELLOW": "38;5;202",
}
_ansi_expand_style(style)
return style
@ -656,7 +648,6 @@ def _igor_style():
"WHITE": "38;5;163",
"YELLOW": "38;5;166",
}
_ansi_expand_style(style)
return style
@ -680,7 +671,6 @@ def _lovelace_style():
"WHITE": "38;5;102",
"YELLOW": "38;5;130",
}
_ansi_expand_style(style)
return style
@ -704,7 +694,6 @@ def _manni_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;166",
}
_ansi_expand_style(style)
return style
@ -728,7 +717,6 @@ def _murphy_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;166",
}
_ansi_expand_style(style)
return style
@ -752,7 +740,6 @@ def _native_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;124",
}
_ansi_expand_style(style)
return style
@ -776,7 +763,6 @@ def _paraiso_dark_style():
"WHITE": "38;5;79",
"YELLOW": "38;5;214",
}
_ansi_expand_style(style)
return style
@ -800,7 +786,6 @@ def _paraiso_light_style():
"WHITE": "38;5;102",
"YELLOW": "38;5;214",
}
_ansi_expand_style(style)
return style
@ -824,7 +809,6 @@ def _pastie_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;130",
}
_ansi_expand_style(style)
return style
@ -848,7 +832,6 @@ def _perldoc_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;166",
}
_ansi_expand_style(style)
return style
@ -872,7 +855,6 @@ def _rrt_style():
"WHITE": "38;5;117",
"YELLOW": "38;5;09",
}
_ansi_expand_style(style)
return style
@ -896,7 +878,6 @@ def _tango_style():
"WHITE": "38;5;15",
"YELLOW": "38;5;94",
}
_ansi_expand_style(style)
return style
@ -920,7 +901,6 @@ def _trac_style():
"WHITE": "38;5;145",
"YELLOW": "38;5;100",
}
_ansi_expand_style(style)
return style
@ -944,7 +924,6 @@ def _vim_style():
"WHITE": "38;5;188",
"YELLOW": "38;5;160",
}
_ansi_expand_style(style)
return style
@ -968,7 +947,6 @@ def _vs_style():
"WHITE": "38;5;31",
"YELLOW": "38;5;124",
}
_ansi_expand_style(style)
return style
@ -992,7 +970,6 @@ def _xcode_style():
"WHITE": "38;5;60",
"YELLOW": "38;5;94",
}
_ansi_expand_style(style)
return style
@ -1071,10 +1048,6 @@ def make_ansi_style(palette):
closest = "".join([a * 2 for a in closest])
short = rgb2short(closest)[0]
style[name] = "38;5;" + short
style["BOLD_" + name] = "1;38;5;" + short
style["UNDERLINE_" + name] = "4;38;5;" + short
style["BOLD_UNDERLINE_" + name] = "1;4;38;5;" + short
style["BACKGROUND_" + name] = "48;5;" + short
return style

View file

@ -45,7 +45,7 @@ from xonsh.tools import (
XonshError,
XonshCalledProcessError,
)
from xonsh.lazyimps import pty, termios
from xonsh.lazyimps import pty, termios, fcntl
from xonsh.commands_cache import CommandsCache
from xonsh.events import events
@ -609,7 +609,7 @@ class SubprocSpec:
def _cmd_event_name(self):
if callable(self.alias):
return self.alias.__name__
return getattr(self.alias, "__name__", repr(self.alias))
elif self.binary_loc is None:
return "<not-found>"
else:
@ -771,6 +771,17 @@ def _safe_pipe_properties(fd, use_tty=False):
props = termios.tcgetattr(fd)
props[1] = props[1] & (~termios.ONLCR) | termios.ONLRET
termios.tcsetattr(fd, termios.TCSANOW, props)
# newly created PTYs have a stardard size (24x80), set size to the same size
# than the current terminal
winsize = None
if sys.stdin.isatty():
winsize = fcntl.ioctl(sys.stdin.fileno(), termios.TIOCGWINSZ, b"0000")
elif sys.stdout.isatty():
winsize = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, b"0000")
elif sys.stderr.isatty():
winsize = fcntl.ioctl(sys.stderr.fileno(), termios.TIOCGWINSZ, b"0000")
if winsize is not None:
fcntl.ioctl(fd, termios.TIOCSWINSZ, winsize)
def _update_last_spec(last):
@ -1324,7 +1335,7 @@ class XonshSession:
def __init__(self, execer=None, ctx=None):
"""
Parameters
---------
----------
execer : Execer, optional
Xonsh execution object, may be None to start
ctx : Mapping, optional
@ -1337,7 +1348,7 @@ class XonshSession:
"""Loads the session with default values.
Parameters
---------
----------
execer : Execer, optional
Xonsh execution object, may be None to start
ctx : Mapping, optional

View file

@ -16,6 +16,34 @@ RE_BACKGROUND = LazyObject(
)
@lazyobject
def KNOWN_XONSH_COLORS():
"""These are the minimum number of colors that need to be implemented by
any style.
"""
return frozenset(
[
"NO_COLOR",
"BLACK",
"RED",
"GREEN",
"YELLOW",
"BLUE",
"PURPLE",
"CYAN",
"WHITE",
"INTENSE_BLACK",
"INTENSE_RED",
"INTENSE_GREEN",
"INTENSE_YELLOW",
"INTENSE_BLUE",
"INTENSE_PURPLE",
"INTENSE_CYAN",
"INTENSE_WHITE",
]
)
@lazyobject
def BASE_XONSH_COLORS():
return {
@ -38,23 +66,52 @@ def BASE_XONSH_COLORS():
}
@lazyobject
def RE_XONSH_COLOR():
hex = "[0-9a-fA-F]"
s = (
# background
r"((?P<background>BACKGROUND_)|(?P<modifiers>("
# modifiers, only apply to foreground
r"BOLD_|FAINT_|ITALIC_|UNDERLINE_|SLOWBLINK_|FASTBLINK_|INVERT_|CONCEAL_|"
r"STRIKETHROUGH_)+))?"
# colors
r"(?P<color>BLACK|RED|GREEN|YELLOW|BLUE|PURPLE|CYAN|WHITE|INTENSE_BLACK|"
r"INTENSE_RED|INTENSE_GREEN|INTENSE_YELLOW|INTENSE_BLUE|INTENSE_PURPLE|"
r"INTENSE_CYAN|INTENSE_WHITE|#" + hex + "{3}|#" + hex + "{6})"
)
bghex = (
"bg#" + hex + "{3}|"
"bg#" + hex + "{6}|"
"BG#" + hex + "{3}|"
"BG#" + hex + "{6}"
)
s = "^((?P<nocolor>NO_COLOR)|(?P<bghex>" + bghex + ")|" + s + ")$"
return re.compile(s)
def iscolor(s):
"""Tests if a string is a valid color"""
return RE_XONSH_COLOR.match(s) is not None
@lazyobject
def CLUT():
"""color look-up table"""
return [
# 8-bit, RGB hex
# Primary 3-bit (8 colors). Unique representation!
("00", "000000"),
("01", "800000"),
("02", "008000"),
("03", "808000"),
("04", "000080"),
("05", "800080"),
("06", "008080"),
("07", "c0c0c0"),
("0", "000000"),
("1", "800000"),
("2", "008000"),
("3", "808000"),
("4", "000080"),
("5", "800080"),
("6", "008080"),
("7", "c0c0c0"),
# Equivalent "bright" versions of original 8 colors.
("08", "808080"),
("09", "ff0000"),
("8", "808080"),
("9", "ff0000"),
("10", "00ff00"),
("11", "ffff00"),
("12", "0000ff"),
@ -328,6 +385,9 @@ def RGB_TO_SHORT():
def short2rgb(short):
short = short.lstrip("0")
if short == "":
short = "0"
return SHORT_TO_RGB[short]
@ -347,7 +407,8 @@ def rgb_to_256(rgb):
Returns
-------
String between 0 and 255, compatible with xterm.
Tuple of String between 0 and 255 (compatible with xterm) and
hex code (length-6).
"""
rgb = rgb.lstrip("#")
if len(rgb) == 0:

View file

@ -151,8 +151,8 @@ class CommandsCache(cabc.Mapping):
def locate_binary(self, name, ignore_alias=False):
"""Locates an executable on the file system using the cache.
Arguments
---------
Parameters
----------
name : str
name of binary to search for
ignore_alias : bool, optional
@ -166,8 +166,8 @@ class CommandsCache(cabc.Mapping):
def lazy_locate_binary(self, name, ignore_alias=False):
"""Locates an executable in the cache, without checking its validity.
Arguments
---------
Parameters
----------
name : str
name of binary to search for
ignore_alias : bool, optional
@ -217,14 +217,21 @@ class CommandsCache(cabc.Mapping):
"""Predicts whether a command list is able to be run on a background
thread, rather than the main thread.
"""
name = self.cached_name(cmd[0])
predictor = self.get_predictor_threadable(cmd[0])
return predictor(cmd[1:])
def get_predictor_threadable(self, cmd0):
"""Return the predictor whether a command list is able to be run on a
background thread, rather than the main thread.
"""
name = self.cached_name(cmd0)
predictors = self.threadable_predictors
if ON_WINDOWS:
# On all names (keys) are stored in upper case so instead
# we get the original cmd or alias name
path, _ = self.lazyget(name, (None, None))
if path is None:
return True
return predict_true
else:
name = pathbasename(path)
if name not in predictors:
@ -232,15 +239,26 @@ class CommandsCache(cabc.Mapping):
if pre in predictors:
predictors[name] = predictors[pre]
if name not in predictors:
predictors[name] = self.default_predictor(name, cmd[0])
predictors[name] = self.default_predictor(name, cmd0)
predictor = predictors[name]
return predictor(cmd[1:])
return predictor
#
# Background Predictors (as methods)
#
def default_predictor(self, name, cmd0):
"""Default predictor, using predictor from original command if the
command is an alias, elseif build a predictor based on binary analysis
on POSIX, else return predict_true.
"""
# alias stuff
if not os.path.isabs(cmd0) and os.sep not in cmd0:
alss = getattr(builtins, "aliases", dict())
if cmd0 in alss:
return self.default_predictor_alias(cmd0)
# other default stuff
if ON_POSIX:
return self.default_predictor_readbin(
name, cmd0, timeout=0.1, failure=predict_true
@ -248,6 +266,30 @@ class CommandsCache(cabc.Mapping):
else:
return predict_true
def default_predictor_alias(self, cmd0):
alias_recursion_limit = (
10
) # this limit is se to handle infinite loops in aliases definition
first_args = [] # contains in reverse order args passed to the aliased command
alss = getattr(builtins, "aliases", dict())
while cmd0 in alss:
alias_name = alss[cmd0]
if isinstance(alias_name, (str, bytes)) or not isinstance(
alias_name, cabc.Sequence
):
return predict_true
for arg in alias_name[:0:-1]:
first_args.insert(0, arg)
if cmd0 == alias_name[0]:
# it is a self-alias stop recursion immediatly
return predict_true
cmd0 = alias_name[0]
alias_recursion_limit -= 1
if alias_recursion_limit == 0:
return predict_true
predictor_cmd0 = self.get_predictor_threadable(cmd0)
return lambda cmd1: predictor_cmd0(first_args[::-1] + cmd1)
def default_predictor_readbin(self, name, cmd0, timeout, failure):
"""Make a default predictor by
analyzing the content of the binary. Should only works on POSIX.
@ -338,9 +380,9 @@ def predict_shell(args):
@lazyobject
def HELP_VER_PREDICTOR_PARSER():
p = argparse.ArgumentParser("cmd", add_help=False)
p.add_argument("-h", "--help", dest="help", action="store_true", default=None)
p.add_argument("-h", "--help", dest="help", nargs="?", action="store", default=None)
p.add_argument(
"-v", "-V", "--version", dest="version", action="store_true", default=None
"-v", "-V", "--version", dest="version", nargs="?", action="store", default=None
)
return p
@ -380,6 +422,19 @@ def predict_hg(args):
return not ns.interactive
def predict_env(args):
"""Predict if env is launching a threadable command or not.
The launched command is extracted from env args, and the predictor of
lauched command is used."""
for i in range(len(args)):
if args[i] and args[i][0] != "-" and "=" not in args[i]:
# args[i] is the command and the following is its arguments
# so args[i:] is used to predict if the command is threadable
return builtins.__xonsh__.commands_cache.predict_threadable(args[i:])
return True
def default_threadable_predictors():
"""Generates a new defaultdict for known threadable predictors.
The default is to predict true.
@ -387,6 +442,7 @@ def default_threadable_predictors():
# alphabetical, for what it is worth.
predictors = {
"aurman": predict_false,
"asciinema": predict_help_ver,
"bash": predict_shell,
"csh": predict_shell,
"clear": predict_false,
@ -394,6 +450,7 @@ def default_threadable_predictors():
"cmd": predict_shell,
"cryptop": predict_false,
"curl": predict_true,
"env": predict_env,
"ex": predict_false,
"emacsclient": predict_false,
"fish": predict_shell,
@ -424,8 +481,10 @@ def default_threadable_predictors():
"ssh": predict_false,
"startx": predict_false,
"sudo": predict_help_ver,
"sudoedit": predict_help_ver,
"tcsh": predict_shell,
"telnet": predict_false,
"tput": predict_false,
"top": predict_help_ver,
"vi": predict_false,
"view": predict_false,

View file

@ -50,7 +50,7 @@ def complete_skipper(cmd, line, start, end, ctx):
# If there's no space following an END_PROC_TOKEN, insert one
if parts[-1] in END_PROC_TOKENS:
return(set(" "), 0)
return (set(" "), 0)
if len(parts) == skip_part_num + 1:
comp_func = complete_command

View file

@ -9,12 +9,12 @@ import xonsh.lazyasd as xl
@xl.lazyobject
def PIP_RE():
return re.compile(r"pip(?:\d|\.)*")
return re.compile(r"\bx?pip(?:\d|\.)*")
@xl.lazyobject
def PIP_LIST_RE():
return re.compile(r"pip(?:\d|\.)* (?:uninstall|show)")
return re.compile(r"\bx?pip(?:\d|\.)* (?:uninstall|show)")
@xl.lazyobject

View file

@ -82,6 +82,7 @@ from xonsh.tools import (
)
from xonsh.ansi_colors import (
ansi_color_escape_code_to_name,
ansi_color_name_to_escape_code,
ansi_reverse_style,
ansi_style_by_name,
)
@ -364,7 +365,11 @@ class LsColors(cabc.MutableMapping):
if self._detyped is None:
self._detyped = ":".join(
[
key + "=" + ";".join([style[v] or "0" for v in val])
key
+ "="
+ ";".join(
[ansi_color_name_to_escape_code(v, cmap=style) for v in val]
)
for key, val in sorted(self._d.items())
]
)
@ -970,7 +975,35 @@ def DEFAULT_DOCS():
configurable=ON_WINDOWS,
),
"LANG": VarDocs("Fallback locale setting for systems where it matters"),
"LS_COLORS": VarDocs("Color settings for ``ls`` command line utility"),
"LS_COLORS": VarDocs(
"Color settings for ``ls`` command line utility",
default="``*.7z=1;0;31:*.Z=1;0;31:*.aac=0;36:*.ace=1;0;31:"
"*.alz=1;0;31:*.arc=1;0;31:*.arj=1;0;31:*.asf=1;0;35:*.au=0;36:"
"*.avi=1;0;35:*.bmp=1;0;35:*.bz=1;0;31:*.bz2=1;0;31:*.cab=1;0;31:"
"*.cgm=1;0;35:*.cpio=1;0;31:*.deb=1;0;31:*.dl=1;0;35:*.dwm=1;0;31:"
"*.dz=1;0;31:*.ear=1;0;31:*.emf=1;0;35:*.esd=1;0;31:*.flac=0;36:"
"*.flc=1;0;35:*.fli=1;0;35:*.flv=1;0;35:*.gif=1;0;35:*.gl=1;0;35:"
"*.gz=1;0;31:*.jar=1;0;31:*.jpeg=1;0;35:*.jpg=1;0;35:*.lha=1;0;31:"
"*.lrz=1;0;31:*.lz=1;0;31:*.lz4=1;0;31:*.lzh=1;0;31:*.lzma=1;0;31"
":*.lzo=1;0;31:*.m2v=1;0;35:*.m4a=0;36:*.m4v=1;0;35:*.mid=0;36:"
"*.midi=0;36:*.mjpeg=1;0;35:*.mjpg=1;0;35:*.mka=0;36:*.mkv=1;0;35:"
"*.mng=1;0;35:*.mov=1;0;35:*.mp3=0;36:*.mp4=1;0;35:*.mp4v=1;0;35:"
"*.mpc=0;36:*.mpeg=1;0;35:*.mpg=1;0;35:*.nuv=1;0;35:*.oga=0;36:"
"*.ogg=0;36:*.ogm=1;0;35:*.ogv=1;0;35:*.ogx=1;0;35:*.opus=0;36:"
"*.pbm=1;0;35:*.pcx=1;0;35:*.pgm=1;0;35:*.png=1;0;35:*.ppm=1;0;35:"
"*.qt=1;0;35:*.ra=0;36:*.rar=1;0;31:*.rm=1;0;35:*.rmvb=1;0;35:"
"*.rpm=1;0;31:*.rz=1;0;31:*.sar=1;0;31:*.spx=0;36:*.svg=1;0;35:"
"*.svgz=1;0;35:*.swm=1;0;31:*.t7z=1;0;31:*.tar=1;0;31:*.taz=1;0;31:"
"*.tbz=1;0;31:*.tbz2=1;0;31:*.tga=1;0;35:*.tgz=1;0;31:*.tif=1;0;35:"
"*.tiff=1;0;35:*.tlz=1;0;31:*.txz=1;0;31:*.tz=1;0;31:*.tzo=1;0;31:"
"*.tzst=1;0;31:*.vob=1;0;35:*.war=1;0;31:*.wav=0;36:*.webm=1;0;35:"
"*.wim=1;0;31:*.wmv=1;0;35:*.xbm=1;0;35:*.xcf=1;0;35:*.xpm=1;0;35:"
"*.xspf=0;36:*.xwd=1;0;35:*.xz=1;0;31:*.yuv=1;0;35:*.z=1;0;31:"
"*.zip=1;0;31:*.zoo=1;0;31:*.zst=1;0;31:bd=40;0;33:ca=0;30;41:"
"cd=40;0;33:di=1;0;34:do=1;0;35:ex=1;0;32:ln=1;0;36:mh=0:mi=0:"
"or=40;0;31:ow=0;34;42:pi=40;0;33:rs=0:sg=0;30;43:so=1;0;35:"
"st=0;37;44:su=0;37;41:tw=0;30;42``",
),
"LOADED_RC_FILES": VarDocs(
"Whether or not any of the xonsh run control files were loaded at "
"startup. This is a sequence of bools in Python that is converted "
@ -993,7 +1026,19 @@ def DEFAULT_DOCS():
"Used to represent a previous present working directory.",
configurable=False,
),
"PATH": VarDocs("List of strings representing where to look for executables."),
"PATH": VarDocs(
"List of strings representing where to look for executables.",
default="On Windows: it is ``Path`` value of register's "
"``HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment``. "
"On Mac OSX: ``('/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin')`` "
"On Linux & on Cygwin & on MSYS, when detected that the distro "
"is like arch, the default PATH is "
"``('/usr/local/sbin', '/usr/local/bin', '/usr/bin', "
"'/usr/bin/site_perl', '/usr/bin/vendor_perl', '/usr/bin/core_perl')``"
" and otherwise is "
"``('~/bin', '/usr/local/sbin', '/usr/local/bin', '/usr/sbin',"
"'/usr/bin', '/sbin', '/bin', '/usr/games', '/usr/local/games')``",
),
"PATHEXT": VarDocs(
"Sequence of extension strings (eg, ``.EXE``) for "
"filtering valid executables by. Each element must be "
@ -1153,7 +1198,8 @@ def DEFAULT_DOCS():
),
),
"XONSH_APPEND_NEWLINE": VarDocs(
"Append new line when a partial line is preserved in output."
"Append new line when a partial line is preserved in output.",
default="``$XONSH_INTERACTIVE``",
),
"XONSH_AUTOPAIR": VarDocs(
"Whether Xonsh will auto-insert matching parentheses, brackets, and "
@ -1516,10 +1562,14 @@ class Env(cabc.MutableMapping):
events.on_envvar_change.fire(name=key, oldvalue=old_value, newvalue=val)
def __delitem__(self, key):
del self._d[key]
self._detyped = None
if self.get("UPDATE_OS_ENVIRON") and key in os_environ:
del os_environ[key]
if key in self._d:
del self._d[key]
self._detyped = None
if self.get("UPDATE_OS_ENVIRON") and key in os_environ:
del os_environ[key]
elif key not in self._defaults:
e = "Unknown environment variable: ${}"
raise KeyError(e.format(key))
def get(self, key, default=None):
"""The environment will look up default values from its own defaults if a

View file

@ -97,13 +97,13 @@ class JsonHistoryGC(threading.Thread):
self.daemon = True
self.size = size
self.wait_for_shell = wait_for_shell
self.start()
self.gc_units_to_rmfiles = {
"commands": _xhj_gc_commands_to_rmfiles,
"files": _xhj_gc_files_to_rmfiles,
"s": _xhj_gc_seconds_to_rmfiles,
"b": _xhj_gc_bytes_to_rmfiles,
}
self.start()
def run(self):
while self.wait_for_shell:

View file

@ -180,11 +180,9 @@ else:
else:
raise
finally:
if oldmask:
# only reset the mask if it is non-empty! See #2989
_pthread_sigmask(signal.SIG_SETMASK, oldmask)
_pthread_sigmask(signal.SIG_SETMASK, oldmask)
def wait_for_active_job(last_task=None, backgrounded=False, _nochild=False):
def wait_for_active_job(last_task=None, backgrounded=False, return_error=False):
"""
Wait for the active job to finish, to be killed by SIGINT, or to be
suspended by ctrl-z.
@ -198,12 +196,12 @@ else:
backgrounded = False
try:
_, wcode = os.waitpid(obj.pid, os.WUNTRACED)
except ChildProcessError: # No child processes
if _nochild:
return active_task
except ChildProcessError as e: # No child processes
if return_error:
return e
else:
return wait_for_active_job(
last_task=active_task, backgrounded=backgrounded, _nochild=True
return _safe_wait_for_active_job(
last_task=active_task, backgrounded=backgrounded
)
if os.WIFSTOPPED(wcode):
print("^Z")
@ -219,6 +217,20 @@ else:
return wait_for_active_job(last_task=active_task, backgrounded=backgrounded)
def _safe_wait_for_active_job(last_task=None, backgrounded=False):
"""Safely call wait_for_active_job()"""
have_error = True
while have_error:
try:
rtn = wait_for_active_job(
last_task=last_task, backgrounded=backgrounded, return_error=True
)
except ChildProcessError as e:
rtn = e
have_error = isinstance(rtn, ChildProcessError)
return rtn
def get_next_task():
""" Get the next active task and put it on top of the queue"""
selected_task = None

View file

@ -2,8 +2,8 @@
import itertools
from collections import ChainMap, MutableSet
from collections.abc import MutableMapping, MutableSequence
from collections import ChainMap
from collections.abc import MutableMapping, MutableSequence, MutableSet
class ChainDBDefaultType(object):
@ -37,8 +37,9 @@ class ChainDB(ChainMap):
res = ChainDB(result)
else:
res.maps.append(result)
elif all([isinstance(result, (MutableSequence,
MutableSet)) for result in results]):
elif all(
[isinstance(result, (MutableSequence, MutableSet)) for result in results]
):
results_chain = itertools.chain(*results)
# if all reults have the same type, cast into that type
if all([isinstance(result, type(results[0])) for result in results]):

View file

@ -10,6 +10,4 @@ def Parser():
from xonsh.parsers.v36 import Parser as p
elif PYTHON_VERSION_INFO > (3, 5):
from xonsh.parsers.v35 import Parser as p
else:
from xonsh.parsers.v34 import Parser as p
return p

View file

@ -711,7 +711,10 @@ class BaseParser(object):
def p_file_input(self, p):
"""file_input : file_stmts"""
p[0] = ast.Module(body=p[1])
if PYTHON_VERSION_INFO < (3, 8, 0):
p[0] = ast.Module(body=p[1])
else:
p[0] = ast.Module(body=p[1], type_ignores=[])
def p_file_stmts_nl(self, p):
"""file_stmts : newline_or_stmt"""
@ -2422,7 +2425,7 @@ class BaseParser(object):
prefix = RE_STRINGPREFIX.match(p1.value).group().lower()
if "p" in prefix and "f" in prefix:
new_pref = prefix.replace("p", "")
value_without_p = new_pref + p1.value[len(prefix):]
value_without_p = new_pref + p1.value[len(prefix) :]
s = eval_fstr_fields(value_without_p, new_pref, filename=self.lexer.fname)
s = pyparse(s).body[0].value
s = ast.increment_lineno(s, p1.lineno - 1)
@ -2448,8 +2451,9 @@ class BaseParser(object):
else:
s = ast.literal_eval(p1.value)
is_bytes = "b" in prefix
is_raw = "r" in prefix
cls = ast.Bytes if is_bytes else ast.Str
p[0] = cls(s=s, lineno=p1.lineno, col_offset=p1.lexpos)
p[0] = cls(s=s, lineno=p1.lineno, col_offset=p1.lexpos, is_raw=is_raw)
def p_string_literal_list(self, p):
"""string_literal_list : string_literal
@ -3164,9 +3168,12 @@ class BaseParser(object):
def p_subproc_atom_str(self, p):
"""subproc_atom : string_literal"""
p0 = xonsh_call(
"__xonsh__.expand_path", args=[p[1]], lineno=self.lineno, col=self.col
)
if hasattr(p[1], "is_raw") and p[1].is_raw:
p0 = p[1]
else:
p0 = xonsh_call(
"__xonsh__.expand_path", args=[p[1]], lineno=self.lineno, col=self.col
)
p0._cliarg_action = "append"
p[0] = p0

View file

@ -1,157 +0,0 @@
# -*- coding: utf-8 -*-
"""Implements the xonsh parser for Python v3.4."""
import xonsh.ast as ast
from xonsh.parsers.base import BaseParser
class Parser(BaseParser):
"""A Python v3.4 compliant parser for the xonsh language."""
def __init__(
self,
lexer_optimize=True,
lexer_table="xonsh.lexer_table",
yacc_optimize=True,
yacc_table="xonsh.parser_table",
yacc_debug=False,
outputdir=None,
):
"""Parameters
----------
lexer_optimize : bool, optional
Set to false when unstable and true when lexer is stable.
lexer_table : str, optional
Lexer module used when optimized.
yacc_optimize : bool, optional
Set to false when unstable and true when parser is stable.
yacc_table : str, optional
Parser module used when optimized.
yacc_debug : debug, optional
Dumps extra debug info.
outputdir : str or None, optional
The directory to place generated tables within.
"""
# Rule creation and modification *must* take place before super()
opt_rules = ["argument_comma_list", "comma_argument_list"]
for rule in opt_rules:
self._opt_rule(rule)
list_rules = ["argument_comma"]
for rule in list_rules:
self._list_rule(rule)
super().__init__(
lexer_optimize=lexer_optimize,
lexer_table=lexer_table,
yacc_optimize=yacc_optimize,
yacc_table=yacc_table,
yacc_debug=yacc_debug,
outputdir=outputdir,
)
def p_classdef_or_funcdef(self, p):
"""classdef_or_funcdef : classdef
| funcdef
"""
p[0] = p[1]
def p_item(self, p):
"""item : test COLON test"""
lenp = len(p)
if lenp == 4:
p0 = [p[1], p[3]]
elif lenp == 3:
p0 = [None, p[2]]
else:
assert False
p[0] = p0
def _set_arg(self, args, arg, ensure_kw=False):
if isinstance(arg, ast.keyword):
args["keywords"].append(arg)
elif ensure_kw:
args["kwargs"] = arg
else:
args["args"].append(arg)
def p_arglist(self, p):
"""arglist : argument comma_opt
| argument_comma_list argument comma_opt
| argument_comma_list_opt TIMES test comma_argument_list_opt
| argument_comma_list_opt TIMES test COMMA POW test
| argument_comma_list_opt TIMES test comma_argument_list COMMA POW test
| argument_comma_list_opt POW test
"""
lenp = len(p)
p1, p2 = p[1], p[2]
p0 = {"args": [], "keywords": [], "starargs": None, "kwargs": None}
if lenp == 3:
self._set_arg(p0, p1)
elif lenp == 4 and p2 != "**":
for arg in p1:
self._set_arg(p0, arg)
self._set_arg(p0, p2)
elif lenp == 4 and p2 == "**":
if p1 is not None:
for arg in p1:
self._set_arg(p0, arg)
self._set_arg(p0, p[3], ensure_kw=True)
elif lenp == 5:
p0["starargs"], p4 = p[3], p[4]
if p1 is not None:
for arg in p1:
self._set_arg(p0, arg)
if p4 is not None:
for arg in p4:
self._set_arg(p0, arg, ensure_kw=True)
elif lenp == 7:
p0["starargs"] = p[3]
if p1 is not None:
for arg in p1:
self._set_arg(p0, arg)
self._set_arg(p0, p[6], ensure_kw=True)
elif lenp == 8:
p0["starargs"], p4 = p[3], p[4]
if p1 is not None:
for arg in p1:
self._set_arg(p0, arg)
for arg in p4:
self._set_arg(p0, arg, ensure_kw=True)
self._set_arg(p0, p[7], ensure_kw=True)
else:
assert False
p[0] = p0
def p_argument_comma(self, p):
"""argument_comma : argument COMMA"""
p[0] = [p[1]]
def p_argument(self, p):
"""argument : test
| test comp_for
| test EQUALS test
"""
# Really [keyword '='] test
# The reason that keywords are test nodes instead of NAME is that using
# NAME results in an ambiguity.
p1 = p[1]
lenp = len(p)
if lenp == 2:
p0 = p1
elif lenp == 3:
if p1 == "**":
p0 = ast.keyword(arg=None, value=p[2])
elif p1 == "*":
p0 = ast.Starred(value=p[2])
else:
p0 = ast.GeneratorExp(
elt=p1,
generators=p[2]["comps"],
lineno=p1.lineno,
col_offset=p1.col_offset,
)
elif lenp == 4:
p0 = ast.keyword(arg=p1.id, value=p[3])
else:
assert False
p[0] = p0

View file

@ -83,7 +83,7 @@ class PromptFormatter:
except Exception:
print("prompt: error: on field {!r}" "".format(field), file=sys.stderr)
xt.print_exception()
value = "(ERROR:{})".format(field)
value = "{{BACKGROUND_RED}}{{ERROR:{}}}{{NO_COLOR}}".format(field)
return value

View file

@ -23,10 +23,7 @@ def env_name():
``{env_prefix}`` and ``{env_postfix}`` fields.
"""
env_name = find_env_name()
if (
builtins.__xonsh__.env.get("VIRTUAL_ENV_DISABLE_PROMPT")
or not env_name
):
if builtins.__xonsh__.env.get("VIRTUAL_ENV_DISABLE_PROMPT") or not env_name:
# env name prompt printing disabled, or no environment; just return
return

View file

@ -17,6 +17,7 @@ GitStatus = collections.namedtuple(
"num_behind",
"untracked",
"changed",
"deleted",
"conflicts",
"staged",
"stashed",
@ -70,6 +71,7 @@ def _DEFS():
"STAGED": "{RED}",
"CONFLICTS": "{RED}×",
"CHANGED": "{BLUE}+",
"DELETED": "{RED}-",
"UNTRACKED": "",
"STASHED": "",
"CLEAN": "{BOLD_GREEN}",
@ -114,12 +116,12 @@ def _gitoperation(gitdir):
def gitstatus():
"""Return namedtuple with fields:
branch name, number of ahead commit, number of behind commit,
untracked number, changed number, conflicts number,
untracked number, changed number, deleted number, conflicts number,
staged number, stashed number, operation."""
status = _check_output(["git", "status", "--porcelain", "--branch"])
branch = ""
num_ahead, num_behind = 0, 0
untracked, changed, conflicts, staged = 0, 0, 0, 0
untracked, changed, deleted, conflicts, staged = 0, 0, 0, 0, 0
for line in status.splitlines():
if line.startswith("##"):
line = line[2:].strip()
@ -142,9 +144,11 @@ def gitstatus():
elif line.startswith("??"):
untracked += 1
else:
if len(line) > 1 and line[1] == "M":
changed += 1
if len(line) > 1:
if line[1] == "M":
changed += 1
elif line[1] == "D":
deleted += 1
if len(line) > 0 and line[0] == "U":
conflicts += 1
elif len(line) > 0 and line[0] != " ":
@ -160,6 +164,7 @@ def gitstatus():
num_behind,
untracked,
changed,
deleted,
conflicts,
staged,
stashed,
@ -188,11 +193,13 @@ def gitstatus_prompt():
ret += _get_def("CONFLICTS") + str(s.conflicts) + "{NO_COLOR}"
if s.changed > 0:
ret += _get_def("CHANGED") + str(s.changed) + "{NO_COLOR}"
if s.deleted > 0:
ret += _get_def("DELETED") + str(s.deleted) + "{NO_COLOR}"
if s.untracked > 0:
ret += _get_def("UNTRACKED") + str(s.untracked) + "{NO_COLOR}"
if s.stashed > 0:
ret += _get_def("STASHED") + str(s.stashed) + "{NO_COLOR}"
if s.staged + s.conflicts + s.changed + s.untracked + s.stashed == 0:
if s.staged + s.conflicts + s.changed + s.deleted + s.untracked + s.stashed == 0:
ret += _get_def("CLEAN") + "{NO_COLOR}"
ret += "{NO_COLOR}"

View file

@ -60,7 +60,11 @@ def _get_hg_root(q):
while True:
if not os.path.isdir(_curpwd):
return False
if any([b.name == ".hg" for b in xt.scandir(_curpwd)]):
try:
dot_hg_is_in_curwd = any([b.name == ".hg" for b in xt.scandir(_curpwd)])
except OSError:
return False
if dot_hg_is_in_curwd:
q.put(_curpwd)
break
else:

View file

@ -1,8 +0,0 @@
# must come before ptk / pygments imports
from xonsh.lazyasd import load_module_in_background
load_module_in_background(
"pkg_resources",
debug="XONSH_DEBUG",
replacements={"pygments.plugin": "pkg_resources"},
)

View file

@ -101,4 +101,5 @@ class PromptToolkitCompleter(Completer):
last_h = render._last_screen.height if render._last_screen else 0
last_h = max(render._min_available_height, last_h)
if last_h < size:
render._last_screen.height = size
if render._last_screen:
render._last_screen.height = size

View file

@ -252,8 +252,8 @@ class PromptToolkit2Shell(BaseShell):
width = width - 1
dots = builtins.__xonsh__.env.get("MULTILINE_PROMPT")
dots = dots() if callable(dots) else dots
if dots is None:
return [(Token, " " * (width + 1))]
if not dots:
return ""
basetoks = self.format_color(dots)
baselen = sum(len(t[1]) for t in basetoks)
if baselen == 0:

View file

@ -41,8 +41,10 @@ from xonsh.tools import (
from xonsh.color_tools import (
RE_BACKGROUND,
BASE_XONSH_COLORS,
RE_XONSH_COLOR,
make_palette,
find_closest_color,
iscolor,
)
from xonsh.style_tools import norm_name
from xonsh.lazyimps import terminal256
@ -278,6 +280,63 @@ def color_by_name(name, fg=None, bg=None):
return tok, fg, bg
@lazyobject
def PYGMENTS_MODIFIERS():
# pygments doesn't support all modifiers.
# use None to represent unsupported
return {
"BOLD": "bold",
"FAINT": None,
"ITALIC": "italic",
"UNDERLINE": "underline",
"SLOWBLINK": None,
"FASTBLINK": None,
"INVERT": None,
"CONCEAL": None,
"STRIKETHROUGH": None,
}
def color_name_to_pygments_code(name, styles):
"""Converts a xonsh color name to a pygments color code."""
token = getattr(Color, norm_name(name))
if token in styles:
return styles[token]
m = RE_XONSH_COLOR.match(name)
if m is None:
raise ValueError("{!r} is not a color!".format(name))
parts = m.groupdict()
# convert regex match into actual pygments colors
if parts["nocolor"] is not None:
res = "noinherit"
elif parts["bghex"] is not None:
res = "bg:#" + parts["bghex"][3:]
elif parts["background"] is not None:
color = parts["color"]
if "#" in color:
fgcolor = color
else:
fgcolor = styles[getattr(Color, color)]
res = "bg:" + fgcolor
else:
# have regular, non-background color
mods = parts["modifiers"]
if mods is None:
mods = []
else:
mods = mods.strip("_").split("_")
mods = [PYGMENTS_MODIFIERS[mod] for mod in mods]
mods = list(filter(None, mods)) # remove unsupported entries
color = parts["color"]
if "#" in color:
mods.append(color)
else:
mods.append(styles[getattr(Color, color)])
res = " ".join(mods)
styles[token] = res
return res
def code_by_name(name, styles):
"""Converts a token name into a pygments-style color code.
@ -293,34 +352,22 @@ def code_by_name(name, styles):
code : str
Pygments style color code.
"""
fg, _, bg = name.lower().partition("__")
if fg.startswith("background_"):
fg, _, bg = name.upper().replace("HEX", "#").partition("__")
if fg.startswith("BACKGROUND_") or fg.startswith("BG#"):
# swap fore & back if needed.
fg, bg = bg, fg
codes = []
# foreground color
if len(fg) == 0:
pass
elif "hex" in fg:
for p in fg.split("_"):
codes.append("#" + p[3:] if p.startswith("hex") else p)
# convert names to codes
if len(fg) == 0 and len(bg) == 0:
code = "noinherit"
elif len(fg) == 0:
code = color_name_to_pygments_code(bg, styles)
elif len(bg) == 0:
code = color_name_to_pygments_code(fg, styles)
else:
fgtok = getattr(Color, fg.upper())
if fgtok in styles:
codes.append(styles[fgtok])
else:
codes += fg.split("_")
# background color
if len(bg) == 0:
pass
elif bg.startswith("background_hex"):
codes.append("bg:#" + bg[14:])
else:
bgtok = getattr(Color, bg.upper())
if bgtok in styles:
codes.append(styles[bgtok])
else:
codes.append(bg.replace("background_", "bg:"))
code = " ".join(codes)
# have both colors
code = color_name_to_pygments_code(bg, styles)
code += " "
code += color_name_to_pygments_code(fg, styles)
return code
@ -355,7 +402,7 @@ def _partial_color_tokenize_main(template, styles):
for literal, field, spec, conv in FORMATTER.parse(template):
if field is None:
value += literal
elif field in KNOWN_COLORS or "#" in field:
elif iscolor(field):
value += literal
next_color, fg, bg = color_by_name(field, fg, bg)
if next_color is not color:
@ -469,7 +516,11 @@ class XonshStyle(Style):
self._style_name = value
# Convert new ansicolor names to old PTK1 names
# Can be remvoed when PTK1 support is dropped.
if builtins.__xonsh__.shell.shell_type != "prompt_toolkit2":
if (
builtins.__xonsh__.shell.shell_type != "prompt_toolkit2"
and pygments_version_info()
and pygments_version_info() < (2, 4, 0)
):
for smap in [self.trap, cmap, PTK_STYLE, self._smap]:
smap.update(ansicolors_to_ptk1_names(smap))
if ON_WINDOWS and "prompt_toolkit" in builtins.__xonsh__.shell.shell_type:
@ -501,7 +552,8 @@ def xonsh_style_proxy(styler):
# Monky patch pygments' list of known ansi colors
# with the new ansi color names used by PTK2
# Can be removed once pygment names get fixed.
pygments.style.ansicolors.update(ANSICOLOR_NAMES_MAP)
if pygments_version_info() and pygments_version_info() < (2, 4, 0):
pygments.style.ansicolors.update(ANSICOLOR_NAMES_MAP)
class XonshStyleProxy(Style):
"""Simple proxy class to fool prompt toolkit."""
@ -577,112 +629,6 @@ XONSH_BASE_STYLE = LazyObject(
)
KNOWN_COLORS = LazyObject(
lambda: frozenset(
[
"BACKGROUND_BLACK",
"BACKGROUND_BLUE",
"BACKGROUND_CYAN",
"BACKGROUND_GREEN",
"BACKGROUND_INTENSE_BLACK",
"BACKGROUND_INTENSE_BLUE",
"BACKGROUND_INTENSE_CYAN",
"BACKGROUND_INTENSE_GREEN",
"BACKGROUND_INTENSE_PURPLE",
"BACKGROUND_INTENSE_RED",
"BACKGROUND_INTENSE_WHITE",
"BACKGROUND_INTENSE_YELLOW",
"BACKGROUND_PURPLE",
"BACKGROUND_RED",
"BACKGROUND_WHITE",
"BACKGROUND_YELLOW",
"BLACK",
"BLUE",
"BOLD_BLACK",
"BOLD_BLUE",
"BOLD_CYAN",
"BOLD_GREEN",
"BOLD_INTENSE_BLACK",
"BOLD_INTENSE_BLUE",
"BOLD_INTENSE_CYAN",
"BOLD_INTENSE_GREEN",
"BOLD_INTENSE_PURPLE",
"BOLD_INTENSE_RED",
"BOLD_INTENSE_WHITE",
"BOLD_INTENSE_YELLOW",
"BOLD_PURPLE",
"BOLD_RED",
"BOLD_UNDERLINE_BLACK",
"BOLD_UNDERLINE_BLUE",
"BOLD_UNDERLINE_CYAN",
"BOLD_UNDERLINE_GREEN",
"BOLD_UNDERLINE_INTENSE_BLACK",
"BOLD_UNDERLINE_INTENSE_BLUE",
"BOLD_UNDERLINE_INTENSE_CYAN",
"BOLD_UNDERLINE_INTENSE_GREEN",
"BOLD_UNDERLINE_INTENSE_PURPLE",
"BOLD_UNDERLINE_INTENSE_RED",
"BOLD_UNDERLINE_INTENSE_WHITE",
"BOLD_UNDERLINE_INTENSE_YELLOW",
"BOLD_UNDERLINE_PURPLE",
"BOLD_UNDERLINE_RED",
"BOLD_UNDERLINE_WHITE",
"BOLD_UNDERLINE_YELLOW",
"BOLD_WHITE",
"BOLD_YELLOW",
"CYAN",
"GREEN",
"INTENSE_BLACK",
"INTENSE_BLUE",
"INTENSE_CYAN",
"INTENSE_GREEN",
"INTENSE_PURPLE",
"INTENSE_RED",
"INTENSE_WHITE",
"INTENSE_YELLOW",
"NO_COLOR",
"PURPLE",
"RED",
"UNDERLINE_BLACK",
"UNDERLINE_BLUE",
"UNDERLINE_CYAN",
"UNDERLINE_GREEN",
"UNDERLINE_INTENSE_BLACK",
"UNDERLINE_INTENSE_BLUE",
"UNDERLINE_INTENSE_CYAN",
"UNDERLINE_INTENSE_GREEN",
"UNDERLINE_INTENSE_PURPLE",
"UNDERLINE_INTENSE_RED",
"UNDERLINE_INTENSE_WHITE",
"UNDERLINE_INTENSE_YELLOW",
"UNDERLINE_PURPLE",
"UNDERLINE_RED",
"UNDERLINE_WHITE",
"UNDERLINE_YELLOW",
"WHITE",
"YELLOW",
]
),
globals(),
"KNOWN_COLORS",
)
def _expand_style(cmap):
"""Expands a style in order to more quickly make color map changes."""
for key, val in list(cmap.items()):
if key is Color.NO_COLOR:
continue
_, _, key = str(key).rpartition(".")
cmap[getattr(Color, "BOLD_" + key)] = "bold " + val
cmap[getattr(Color, "UNDERLINE_" + key)] = "underline " + val
cmap[getattr(Color, "BOLD_UNDERLINE_" + key)] = "bold underline " + val
if val == "noinherit":
cmap[getattr(Color, "BACKGROUND_" + key)] = val
else:
cmap[getattr(Color, "BACKGROUND_" + key)] = "bg:" + val
def _bw_style():
style = {
Color.BLACK: "noinherit",
@ -703,7 +649,6 @@ def _bw_style():
Color.WHITE: "noinherit",
Color.YELLOW: "noinherit",
}
_expand_style(style)
return style
@ -727,7 +672,6 @@ def _default_style():
Color.WHITE: "ansigray",
Color.YELLOW: "ansiyellow",
}
_expand_style(style)
return style
@ -751,7 +695,6 @@ def _monokai_style():
Color.WHITE: "#d7d7d7",
Color.YELLOW: "#e2e22e",
}
_expand_style(style)
return style
@ -778,7 +721,6 @@ def _algol_style():
Color.WHITE: "#888",
Color.YELLOW: "#FF0000",
}
_expand_style(style)
return style
@ -802,7 +744,6 @@ def _algol_nu_style():
Color.WHITE: "#888",
Color.YELLOW: "#FF0000",
}
_expand_style(style)
return style
@ -826,7 +767,6 @@ def _autumn_style():
Color.WHITE: "#aaaaaa",
Color.YELLOW: "#aa5500",
}
_expand_style(style)
return style
@ -850,7 +790,6 @@ def _borland_style():
Color.WHITE: "#aaaaaa",
Color.YELLOW: "#a61717",
}
_expand_style(style)
return style
@ -874,7 +813,6 @@ def _colorful_style():
Color.WHITE: "#bbbbbb",
Color.YELLOW: "#A60",
}
_expand_style(style)
return style
@ -898,7 +836,6 @@ def _emacs_style():
Color.WHITE: "#bbbbbb",
Color.YELLOW: "#BB6622",
}
_expand_style(style)
return style
@ -922,7 +859,6 @@ def _friendly_style():
Color.WHITE: "#bbbbbb",
Color.YELLOW: "#c65d09",
}
_expand_style(style)
return style
@ -946,7 +882,6 @@ def _fruity_style():
Color.WHITE: "#cdcaa9",
Color.YELLOW: "#fb660a",
}
_expand_style(style)
return style
@ -970,7 +905,6 @@ def _igor_style():
Color.WHITE: "#CC00A3",
Color.YELLOW: "#C34E00",
}
_expand_style(style)
return style
@ -994,7 +928,6 @@ def _lovelace_style():
Color.WHITE: "#888888",
Color.YELLOW: "#b85820",
}
_expand_style(style)
return style
@ -1018,7 +951,6 @@ def _manni_style():
Color.WHITE: "#AAAAAA",
Color.YELLOW: "#CC3300",
}
_expand_style(style)
return style
@ -1042,7 +974,6 @@ def _murphy_style():
Color.WHITE: "#bbbbbb",
Color.YELLOW: "#c65d09",
}
_expand_style(style)
return style
@ -1066,7 +997,6 @@ def _native_style():
Color.WHITE: "#aaaaaa",
Color.YELLOW: "#a61717",
}
_expand_style(style)
return style
@ -1090,7 +1020,6 @@ def _paraiso_dark_style():
Color.WHITE: "#5bc4bf",
Color.YELLOW: "#f99b15",
}
_expand_style(style)
return style
@ -1114,7 +1043,6 @@ def _paraiso_light_style():
Color.WHITE: "#8d8687",
Color.YELLOW: "#f99b15",
}
_expand_style(style)
return style
@ -1138,7 +1066,6 @@ def _pastie_style():
Color.WHITE: "#bbbbbb",
Color.YELLOW: "#aa6600",
}
_expand_style(style)
return style
@ -1162,7 +1089,6 @@ def _perldoc_style():
Color.WHITE: "#a7a7a7",
Color.YELLOW: "#cb6c20",
}
_expand_style(style)
return style
@ -1186,7 +1112,6 @@ def _rrt_style():
Color.WHITE: "#87ceeb",
Color.YELLOW: "#ff0000",
}
_expand_style(style)
return style
@ -1210,7 +1135,6 @@ def _tango_style():
Color.WHITE: "#f8f8f8",
Color.YELLOW: "#8f5902",
}
_expand_style(style)
return style
@ -1234,7 +1158,6 @@ def _trac_style():
Color.WHITE: "#aaaaaa",
Color.YELLOW: "#808000",
}
_expand_style(style)
return style
@ -1258,7 +1181,6 @@ def _vim_style():
Color.WHITE: "#cccccc",
Color.YELLOW: "#cd0000",
}
_expand_style(style)
return style
@ -1282,7 +1204,6 @@ def _vs_style():
Color.WHITE: "#2b91af",
Color.YELLOW: "#a31515",
}
_expand_style(style)
return style
@ -1306,7 +1227,6 @@ def _xcode_style():
Color.WHITE: "#3F6E75",
Color.YELLOW: "#836C28",
}
_expand_style(style)
return style
@ -1381,10 +1301,6 @@ def make_pygments_style(palette):
for name, t in BASE_XONSH_COLORS.items():
color = find_closest_color(t, palette)
style[getattr(Color, name)] = "#" + color
style[getattr(Color, "BOLD_" + name)] = "bold #" + color
style[getattr(Color, "UNDERLINE_" + name)] = "underline #" + color
style[getattr(Color, "BOLD_UNDERLINE_" + name)] = "bold underline #" + color
style[getattr(Color, "BACKGROUND_" + name)] = "bg:#" + color
return style
@ -1403,6 +1319,9 @@ def _monkey_patch_pygments_codes():
""" Monky patch pygments' dict of console codes,
with new color names
"""
if pygments_version_info() and pygments_version_info() >= (2, 4, 0):
return
import pygments.console
if "brightblack" in pygments.console.codes:

View file

@ -641,7 +641,7 @@ class ReadlineShell(BaseShell, cmd.Cmd):
"""
if not ON_POSIX:
return
stty, _ = builtins.__xonsh__.commands_cache.lazyget("stty", None)
stty, _ = builtins.__xonsh__.commands_cache.lazyget("stty", (None, None))
if stty is None:
return
# If available, we should just call the stty utility. This call should

View file

@ -4,7 +4,7 @@ from collections import defaultdict
from xonsh.platform import HAS_PYGMENTS
from xonsh.lazyasd import LazyObject
from xonsh.color_tools import RE_BACKGROUND
from xonsh.color_tools import RE_BACKGROUND, iscolor
from xonsh.tools import FORMATTER
@ -92,7 +92,7 @@ def _partial_color_tokenize_main(template, styles):
for literal, field, spec, conv in FORMATTER.parse(template):
if field is None:
value += literal
elif field in KNOWN_COLORS or "#" in field:
elif iscolor(field):
value += literal
next_color, fg, bg = color_by_name(field, fg, bg)
if next_color is not color:
@ -164,99 +164,9 @@ def color_by_name(name, fg=None, bg=None):
def norm_name(name):
"""Normalizes a color name."""
return name.replace("#", "HEX").replace("BGHEX", "BACKGROUND_HEX")
return name.upper().replace("#", "HEX")
KNOWN_COLORS = LazyObject(
lambda: frozenset(
[
"BACKGROUND_BLACK",
"BACKGROUND_BLUE",
"BACKGROUND_CYAN",
"BACKGROUND_GREEN",
"BACKGROUND_INTENSE_BLACK",
"BACKGROUND_INTENSE_BLUE",
"BACKGROUND_INTENSE_CYAN",
"BACKGROUND_INTENSE_GREEN",
"BACKGROUND_INTENSE_PURPLE",
"BACKGROUND_INTENSE_RED",
"BACKGROUND_INTENSE_WHITE",
"BACKGROUND_INTENSE_YELLOW",
"BACKGROUND_PURPLE",
"BACKGROUND_RED",
"BACKGROUND_WHITE",
"BACKGROUND_YELLOW",
"BLACK",
"BLUE",
"BOLD_BLACK",
"BOLD_BLUE",
"BOLD_CYAN",
"BOLD_GREEN",
"BOLD_INTENSE_BLACK",
"BOLD_INTENSE_BLUE",
"BOLD_INTENSE_CYAN",
"BOLD_INTENSE_GREEN",
"BOLD_INTENSE_PURPLE",
"BOLD_INTENSE_RED",
"BOLD_INTENSE_WHITE",
"BOLD_INTENSE_YELLOW",
"BOLD_PURPLE",
"BOLD_RED",
"BOLD_UNDERLINE_BLACK",
"BOLD_UNDERLINE_BLUE",
"BOLD_UNDERLINE_CYAN",
"BOLD_UNDERLINE_GREEN",
"BOLD_UNDERLINE_INTENSE_BLACK",
"BOLD_UNDERLINE_INTENSE_BLUE",
"BOLD_UNDERLINE_INTENSE_CYAN",
"BOLD_UNDERLINE_INTENSE_GREEN",
"BOLD_UNDERLINE_INTENSE_PURPLE",
"BOLD_UNDERLINE_INTENSE_RED",
"BOLD_UNDERLINE_INTENSE_WHITE",
"BOLD_UNDERLINE_INTENSE_YELLOW",
"BOLD_UNDERLINE_PURPLE",
"BOLD_UNDERLINE_RED",
"BOLD_UNDERLINE_WHITE",
"BOLD_UNDERLINE_YELLOW",
"BOLD_WHITE",
"BOLD_YELLOW",
"CYAN",
"GREEN",
"INTENSE_BLACK",
"INTENSE_BLUE",
"INTENSE_CYAN",
"INTENSE_GREEN",
"INTENSE_PURPLE",
"INTENSE_RED",
"INTENSE_WHITE",
"INTENSE_YELLOW",
"NO_COLOR",
"PURPLE",
"RED",
"UNDERLINE_BLACK",
"UNDERLINE_BLUE",
"UNDERLINE_CYAN",
"UNDERLINE_GREEN",
"UNDERLINE_INTENSE_BLACK",
"UNDERLINE_INTENSE_BLUE",
"UNDERLINE_INTENSE_CYAN",
"UNDERLINE_INTENSE_GREEN",
"UNDERLINE_INTENSE_PURPLE",
"UNDERLINE_INTENSE_RED",
"UNDERLINE_INTENSE_WHITE",
"UNDERLINE_INTENSE_YELLOW",
"UNDERLINE_PURPLE",
"UNDERLINE_RED",
"UNDERLINE_WHITE",
"UNDERLINE_YELLOW",
"WHITE",
"YELLOW",
]
),
globals(),
"KNOWN_COLORS",
)
DEFAULT_STYLE_DICT = LazyObject(
lambda: defaultdict(
lambda: "",

View file

@ -51,6 +51,7 @@ from xonsh.platform import (
PYTHON_VERSION_INFO,
expanduser,
os_environ,
pygments_version_info,
)
@ -1713,6 +1714,12 @@ def history_tuple_to_str(x):
return "{0} {1}".format(*x)
def all_permutations(iterable):
"""Yeilds all permutations, not just those of a specified length"""
for r in range(1, len(iterable) + 1):
yield from itertools.permutations(iterable, r=r)
def format_color(string, **kwargs):
"""Formats strings that may contain colors. This simply dispatches to the
shell instances method of the same name. The results of this function should
@ -1888,6 +1895,8 @@ def hardcode_colors_for_win10(style_map):
def ansicolors_to_ptk1_names(stylemap):
"""Converts ansicolor names in a stylemap to old PTK1 color names
"""
if pygments_version_info() and pygments_version_info() >= (2, 4, 0):
return stylemap
modified_stylemap = {}
for token, style_str in stylemap.items():
for color, ptk1_color in ANSICOLOR_NAMES_MAP.items():
@ -1923,9 +1932,12 @@ def intensify_colors_on_win_setter(enable):
environment variable.
"""
enable = to_bool(enable)
if builtins.__xonsh__.shell is not None:
if hasattr(builtins.__xonsh__.shell.shell.styler, "style_name"):
delattr(builtins.__xonsh__.shell.shell.styler, "style_name")
if (
hasattr(builtins.__xonsh__, "shell")
and builtins.__xonsh__.shell is not None
and hasattr(builtins.__xonsh__.shell.shell.styler, "style_name")
):
delattr(builtins.__xonsh__.shell.shell.styler, "style_name")
return enable
@ -1936,16 +1948,27 @@ def format_std_prepost(template, env=None):
if not template:
return ""
env = builtins.__xonsh__.env if env is None else env
shell = builtins.__xonsh__.shell.shell
try:
s = shell.prompt_formatter(template)
except Exception:
print_exception()
# \001\002 is there to fool pygments into not returning an empty string
# for potentially empty input. This happens when the template is just a
# color code with no visible text.
invis = "\001\002"
s = shell.format_color(invis + s + invis, force_string=True)
if builtins.__xonsh__.shell is None:
# shell hasn't fully started up (probably still in xonshrc)
from xonsh.prompt.base import PromptFormatter
from xonsh.ansi_colors import ansi_partial_color_format
pf = PromptFormatter()
s = pf(template)
style = env.get("XONSH_COLOR_STYLE")
s = ansi_partial_color_format(invis + s + invis, hide=False, style=style)
else:
# shell has fully started. do the normal thing
shell = builtins.__xonsh__.shell.shell
try:
s = shell.prompt_formatter(template)
except Exception:
print_exception()
# \001\002 is there to fool pygments into not returning an empty string
# for potentially empty input. This happens when the template is just a
# color code with no visible text.
s = shell.format_color(invis + s + invis, force_string=True)
s = s.replace(invis, "")
return s

View file

@ -6,7 +6,7 @@
},
{"name": "autojump",
"package": "xontrib-autojump",
"url": "https://github.com/gsaga/autojump-xonsh",
"url": "https://github.com/sagartewari01/autojump-xonsh",
"description": ["autojump support for xonsh"]
},
{"name": "autoxsh",
@ -79,6 +79,14 @@
"url": "https://github.com/xsteadfastx/xonsh-docker-tabcomplete",
"description": ["Adds tabcomplete functionality to docker inside of xonsh."]
},
{"name": "histcpy",
"package": "xontrib-histcpy",
"url": "https://github.com/con-f-use/xontrib-histcpy",
"description": [
"Useful aliases and shortcuts for extracting links and text",
"from command output history and putting them into the",
" clipboard."]
},
{"name": "jedi",
"package": "xonsh",
"url": "http://xon.sh",
@ -266,6 +274,13 @@
"pip": "xpip install xontrib-avox"
}
},
"xontrib-histcpy": {
"license": "GPLv3",
"url": "https://github.com/con-f-use/xontrib-histcpy",
"install": {
"pip": "xpip install xontrib-histcpy"
}
},
"xontrib-z": {
"license": "GPLv3",
"url": "https://github.com/astronouth7303/xontrib-z",

View file

@ -1,5 +1,6 @@
"""Implements a cat command for xonsh."""
import os
import stat
import time
import builtins
@ -48,8 +49,9 @@ def _cat_single_file(opts, fname, stdin, out, err, line_count=1):
print("cat: No such file or directory: {}".format(fname), file=err)
return True, line_count
else:
file_size = os.stat(fname).st_size
if file_size == 0:
fstat = os.stat(fname)
file_size = fstat.st_size
if file_size == 0 and not stat.S_ISREG(fstat.st_mode):
file_size = None
fobj = open(fname, "rb")
f = xproc.NonBlockingFDReader(fobj.fileno(), timeout=0.1)

View file

@ -89,7 +89,7 @@ def _uptime_beos():
if not hasattr(xp.LIBC, "system_time"):
return None
xp.LIBC.system_time.restype = ctypes.c_int64
return xp.LIBC.system_time() / 1000000.
return xp.LIBC.system_time() / 1000000.0
def _uptime_bsd():
@ -110,8 +110,8 @@ def _uptime_bsd():
sec, usec = struct.unpack_from("@LL", buf.raw)
# OS X disagrees what that second value is.
if usec > 1000000:
usec = 0.
_BOOTTIME = sec + usec / 1000000.
usec = 0.0
_BOOTTIME = sec + usec / 1000000.0
up = time.time() - _BOOTTIME
if up < 0:
up = None
@ -225,11 +225,11 @@ def _uptime_windows():
if hasattr(xp.LIBC, "GetTickCount64"):
# Vista/Server 2008 or later.
xp.LIBC.GetTickCount64.restype = ctypes.c_uint64
return xp.LIBC.GetTickCount64() / 1000.
return xp.LIBC.GetTickCount64() / 1000.0
if hasattr(xp.LIBC, "GetTickCount"):
# WinCE and Win2k or later; gives wrong answers after 49.7 days.
xp.LIBC.GetTickCount.restype = ctypes.c_uint32
return xp.LIBC.GetTickCount() / 1000.
return xp.LIBC.GetTickCount() / 1000.0
return None

View file

@ -1,41 +1,42 @@
"""Bash-like interface extensions for xonsh."""
import shlex
import sys
import re
from prompt_toolkit.keys import Keys
from prompt_toolkit.filters import Condition, EmacsInsertMode, ViInsertMode
from xonsh.platform import ptk_shell_type
__all__ = ()
@events.on_transform_command
def bash_preproc(cmd, **kw):
if not __xonsh__.history.inps:
if cmd.strip() == '!!':
return ''
return cmd
return cmd.replace('!!', __xonsh__.history.inps[-1].strip())
bang_previous = {
"!": lambda x: x,
"$": lambda x: shlex.split(x)[-1],
"^": lambda x: shlex.split(x)[0],
"*": lambda x: " ".join(shlex.split(x)[1:]),
}
def replace_bang(m):
arg = m.group(1)
inputs = __xonsh__.history.inps
@events.on_ptk_create
def custom_keybindings(bindings, **kw):
if ptk_shell_type() == 'prompt_toolkit2':
handler = bindings.add
else:
handler = bindings.registry.add_binding
# Dissect the previous command.
if arg in bang_previous:
try:
return bang_previous[arg](inputs[-1])
except IndexError:
print("xonsh: no history for '!{}'".format(arg))
return ""
insert_mode = ViInsertMode() | EmacsInsertMode()
# Look back in history for a matching command.
else:
try:
return next((x for x in reversed(inputs) if x.startswith(arg)))
except StopIteration:
print("xonsh: no previous commands match '!{}'".format(arg))
return ""
@Condition
def last_command_exists():
return len(__xonsh__.history) > 0
@handler(Keys.Escape, '.', filter=last_command_exists & insert_mode)
def recall_last_arg(event):
arg = __xonsh__.history[-1].cmd.split()[-1]
event.current_buffer.insert_text(arg)
return re.sub(r"!([!$^*]|[\w]+)", replace_bang, cmd)
def alias(args, stdin=None):
@ -43,21 +44,21 @@ def alias(args, stdin=None):
if args:
for arg in args:
if '=' in arg:
if "=" in arg:
# shlex.split to remove quotes, e.g. "foo='echo hey'" into
# "foo=echo hey"
name, cmd = shlex.split(arg)[0].split('=', 1)
name, cmd = shlex.split(arg)[0].split("=", 1)
aliases[name] = shlex.split(cmd)
elif arg in aliases:
print('{}={}'.format(arg, aliases[arg]))
print("{}={}".format(arg, aliases[arg]))
else:
print("alias: {}: not found".format(arg), file=sys.stderr)
ret = 1
else:
for alias, cmd in aliases.items():
print('{}={}'.format(alias, cmd))
print("{}={}".format(alias, cmd))
return ret
aliases['alias'] = alias
aliases["alias"] = alias

View file

@ -22,9 +22,9 @@ from xonsh.xoreutils.yes import yes
__all__ = ()
aliases['cat'] = cat
aliases['echo'] = echo
aliases['pwd'] = pwd
aliases['tee'] = tee
aliases['tty'] = tty
aliases['yes'] = yes
aliases["cat"] = cat
aliases["echo"] = echo
aliases["pwd"] = pwd
aliases["tee"] = tee
aliases["tty"] = tty
aliases["yes"] = yes

View file

@ -1,7 +1,7 @@
"""Hooks for the distributed parallel computing library."""
from xonsh.contexts import Functor
__all__ = 'DSubmitter', 'dsubmit'
__all__ = "DSubmitter", "dsubmit"
def dworker(args, stdin=None):
@ -9,10 +9,11 @@ def dworker(args, stdin=None):
workers that also have access to xonsh builtins.
"""
from distributed.cli import dworker
dworker.main.main(args=args, prog_name='dworker', standalone_mode=False)
dworker.main.main(args=args, prog_name="dworker", standalone_mode=False)
aliases['dworker'] = dworker
aliases["dworker"] = dworker
class DSubmitter(Functor):
@ -44,7 +45,7 @@ class DSubmitter(Functor):
return res
def dsubmit(*a, args=(), kwargs=None, rtn='', **kw):
def dsubmit(*a, args=(), kwargs=None, rtn="", **kw):
"""Returns a distributed submission context manager, DSubmitter(),
with a new executor instance.
@ -66,6 +67,7 @@ def dsubmit(*a, args=(), kwargs=None, rtn='', **kw):
An instance of the DSubmitter context manager.
"""
from distributed import Executor
e = Executor(*a, **kw)
dsub = DSubmitter(e, args=args, kwargs=kwargs, rtn=rtn)
return dsub

View file

@ -36,13 +36,14 @@ def _cwd_release_wrapper(func):
the workdir to the users home directory.
"""
env = builtins.__xonsh__.env
if env.get('UPDATE_PROMPT_ON_KEYPRESS'):
return func if not hasattr(func, '_orgfunc') else func._orgfunc
if env.get("UPDATE_PROMPT_ON_KEYPRESS"):
return func if not hasattr(func, "_orgfunc") else func._orgfunc
if hasattr(func, '_orgfunc'):
if hasattr(func, "_orgfunc"):
# Already wrapped
return func
else:
@functools.wraps(func)
def wrapper(*args, **kwargs):
anchor = Path(os.getcwd()).anchor
@ -51,14 +52,15 @@ def _cwd_release_wrapper(func):
out = func(*args, **kwargs)
finally:
try:
pwd = env.get('PWD', anchor)
pwd = env.get("PWD", anchor)
os.chdir(pwd)
except (FileNotFoundError, NotADirectoryError):
print_exception()
newpath = _chdir_up(pwd)
builtins.__xonsh__.env['PWD'] = newpath
builtins.__xonsh__.env["PWD"] = newpath
raise KeyboardInterrupt
return out
wrapper._orgfunc = func
return wrapper
@ -69,20 +71,22 @@ def _cwd_restore_wrapper(func):
prompt_toolkit or readline.
"""
env = builtins.__xonsh__.env
if env.get('UPDATE_PROMPT_ON_KEYPRESS'):
return func if not hasattr(func, '_orgfunc') else func._orgfunc
if env.get("UPDATE_PROMPT_ON_KEYPRESS"):
return func if not hasattr(func, "_orgfunc") else func._orgfunc
if hasattr(func, '_orgfunc'):
if hasattr(func, "_orgfunc"):
# Already wrapped
return func
else:
@functools.wraps(func)
def wrapper(*args, **kwargs):
workdir = os.getcwd()
_chdir_up(env.get('PWD', workdir))
_chdir_up(env.get("PWD", workdir))
out = func(*args, **kwargs)
_chdir_up(workdir)
return out
wrapper._orgfunc = func
return wrapper
@ -93,4 +97,6 @@ def setup_release_cwd_hook(prompter, history, completer, bindings, **kw):
prompter.prompt = _cwd_release_wrapper(prompter.prompt)
if completer.completer:
# Temporarily restore cwd for callbacks to the completer
completer.completer.complete = _cwd_restore_wrapper(completer.completer.complete)
completer.completer.complete = _cwd_restore_wrapper(
completer.completer.complete
)

View file

@ -13,10 +13,11 @@ __all__ = ()
def mpl(args, stdin=None):
"""Hooks to matplotlib"""
from xontrib.mplhooks import show
show()
aliases['mpl'] = mpl
aliases["mpl"] = mpl
@lazyobject
@ -31,8 +32,9 @@ def pylab_helpers():
@events.on_import_post_exec_module
def interactive_pyplot(module=None, **kwargs):
"""This puts pyplot in interactive mode once it is imported."""
if module.__name__ != 'matplotlib.pyplot' or \
not __xonsh__.env.get('XONSH_INTERACTIVE'):
if module.__name__ != "matplotlib.pyplot" or not __xonsh__.env.get(
"XONSH_INTERACTIVE"
):
return
# Since we are in interactive mode, let's monkey-patch plt.show
# to try to never block.

View file

@ -46,7 +46,9 @@ def figure_to_rgb_array(fig, shape=None):
Note: the method will throw an exception if the given shape is wrong.
"""
array = np.frombuffer(_get_buffer(fig, dpi=fig.dpi, format='raw').read(), dtype='uint8')
array = np.frombuffer(
_get_buffer(fig, dpi=fig.dpi, format="raw").read(), dtype="uint8"
)
if shape is None:
w, h = fig.canvas.get_width_height()
shape = (h, w, 4)
@ -81,7 +83,7 @@ def figure_to_tight_array(fig, width, height, minimal=True):
dpi = dpi_fig
subplotpars = {
k: getattr(fig.subplotpars, k)
for k in ['wspace', 'hspace', 'bottom', 'top', 'left', 'right']
for k in ["wspace", "hspace", "bottom", "top", "left", "right"]
}
# set the figure dimensions to the terminal size
@ -95,8 +97,8 @@ def figure_to_tight_array(fig, width, height, minimal=True):
fig.subplots_adjust(bottom=1 / height, top=1 - 1 / height, left=0, right=1)
# reduce font size in order to reduce text impact on the image
font_size = matplotlib.rcParams['font.size']
matplotlib.rcParams.update({'font.size': 0})
font_size = matplotlib.rcParams["font.size"]
matplotlib.rcParams.update({"font.size": 0})
else:
dpi = min([width * fig.dpi // w, height * fig.dpi // h])
fig.dpi = dpi
@ -108,7 +110,7 @@ def figure_to_tight_array(fig, width, height, minimal=True):
if minimal:
# cleanup after tight layout
# clean up rcParams
matplotlib.rcParams.update({'font.size': font_size})
matplotlib.rcParams.update({"font.size": font_size})
# reset the axis positions and figure dimensions
fig.set_size_inches(w / dpi, h / dpi, forward=True)
@ -121,8 +123,8 @@ def figure_to_tight_array(fig, width, height, minimal=True):
def buf_to_color_str(buf):
"""Converts an RGB array to a xonsh color string."""
space = ' '
pix = '{{bg#{0:02x}{1:02x}{2:02x}}} '
space = " "
pix = "{{bg#{0:02x}{1:02x}{2:02x}}} "
pixels = []
for h in range(buf.shape[0]):
last = None
@ -133,9 +135,9 @@ def buf_to_color_str(buf):
else:
pixels.append(pix.format(*rgb))
last = rgb
pixels.append('{NO_COLOR}\n')
pixels.append("{NO_COLOR}\n")
pixels[-1] = pixels[-1].rstrip()
return ''.join(pixels)
return "".join(pixels)
def display_figure_with_iterm2(fig):
@ -146,13 +148,13 @@ def display_figure_with_iterm2(fig):
fig : matplotlib.figure.Figure
the figure to be plotted
"""
print(display_image_bytes(_get_buffer(fig, format='png', dpi=fig.dpi).read()))
print(display_image_bytes(_get_buffer(fig, format="png", dpi=fig.dpi).read()))
def show():
'''Run the mpl display sequence by printing the most recent figure to console'''
"""Run the mpl display sequence by printing the most recent figure to console"""
try:
minimal = __xonsh__.env['XONTRIB_MPL_MINIMAL']
minimal = __xonsh__.env["XONTRIB_MPL_MINIMAL"]
except KeyError:
minimal = XONTRIB_MPL_MINIMAL_DEFAULT
fig = plt.gcf()

View file

@ -13,20 +13,25 @@ class VoxHandler:
def parser():
from argparse import ArgumentParser
parser = ArgumentParser(prog='vox', description=__doc__)
subparsers = parser.add_subparsers(dest='command')
parser = ArgumentParser(prog="vox", description=__doc__)
subparsers = parser.add_subparsers(dest="command")
create = subparsers.add_parser(
'new', aliases=['create'],
help='Create a new virtual environment in $VIRTUALENV_HOME'
"new",
aliases=["create"],
help="Create a new virtual environment in $VIRTUALENV_HOME",
)
create.add_argument('name', metavar='ENV',
help='The environments to create')
create.add_argument("name", metavar="ENV", help="The environments to create")
create.add_argument('--system-site-packages', default=False,
action='store_true', dest='system_site_packages',
help='Give the virtual environment access to the '
'system site-packages dir.')
create.add_argument(
"--system-site-packages",
default=False,
action="store_true",
dest="system_site_packages",
help="Give the virtual environment access to the "
"system site-packages dir.",
)
create.add_argument(
"-p",
@ -41,54 +46,85 @@ class VoxHandler:
)
from xonsh.platform import ON_WINDOWS
group = create.add_mutually_exclusive_group()
group.add_argument('--symlinks', default=not ON_WINDOWS,
action='store_true', dest='symlinks',
help='Try to use symlinks rather than copies, '
'when symlinks are not the default for '
'the platform.')
group.add_argument('--copies', default=ON_WINDOWS,
action='store_false', dest='symlinks',
help='Try to use copies rather than symlinks, '
'even when symlinks are the default for '
'the platform.')
create.add_argument('--without-pip', dest='with_pip',
default=True, action='store_false',
help='Skips installing or upgrading pip in the '
'virtual environment (pip is bootstrapped '
'by default)')
group.add_argument(
"--symlinks",
default=not ON_WINDOWS,
action="store_true",
dest="symlinks",
help="Try to use symlinks rather than copies, "
"when symlinks are not the default for "
"the platform.",
)
group.add_argument(
"--copies",
default=ON_WINDOWS,
action="store_false",
dest="symlinks",
help="Try to use copies rather than symlinks, "
"even when symlinks are the default for "
"the platform.",
)
create.add_argument(
"--without-pip",
dest="with_pip",
default=True,
action="store_false",
help="Skips installing or upgrading pip in the "
"virtual environment (pip is bootstrapped "
"by default)",
)
activate = subparsers.add_parser(
'activate', aliases=['workon', 'enter'],
help='Activate virtual environment'
"activate", aliases=["workon", "enter"], help="Activate virtual environment"
)
activate.add_argument('name', metavar='ENV',
help=('The environment to activate. ENV can be '
'either a name from the venvs shown by vox'
'list or the path to an arbitrary venv'))
subparsers.add_parser('deactivate', aliases=['exit'], help='Deactivate current virtual environment')
subparsers.add_parser('list', aliases=['ls'],
help=('List environments available in '
'$VIRTUALENV_HOME'))
remove = subparsers.add_parser('remove', aliases=['rm', 'delete', 'del'], help='Remove virtual environment')
remove.add_argument('names', metavar='ENV', nargs='+',
help=('The environments to remove. ENV can be '
'either a name from the venvs shown by vox'
'list or the path to an arbitrary venv'))
subparsers.add_parser('help', help='Show this help message')
activate.add_argument(
"name",
metavar="ENV",
help=(
"The environment to activate. ENV can be "
"either a name from the venvs shown by vox"
"list or the path to an arbitrary venv"
),
)
subparsers.add_parser(
"deactivate",
aliases=["exit"],
help="Deactivate current virtual environment",
)
subparsers.add_parser(
"list",
aliases=["ls"],
help=("List environments available in " "$VIRTUALENV_HOME"),
)
remove = subparsers.add_parser(
"remove", aliases=["rm", "delete", "del"], help="Remove virtual environment"
)
remove.add_argument(
"names",
metavar="ENV",
nargs="+",
help=(
"The environments to remove. ENV can be "
"either a name from the venvs shown by vox"
"list or the path to an arbitrary venv"
),
)
subparsers.add_parser("help", help="Show this help message")
return parser
parser = lazyasd.LazyObject(parser, locals(), 'parser')
parser = lazyasd.LazyObject(parser, locals(), "parser")
aliases = {
'create': 'new',
'workon': 'activate',
'enter': 'activate',
'exit': 'deactivate',
'ls': 'list',
'rm': 'remove',
'delete': 'remove',
'del': 'remove',
"create": "new",
"workon": "activate",
"enter": "activate",
"exit": "deactivate",
"ls": "list",
"rm": "remove",
"delete": "remove",
"del": "remove",
}
def __init__(self):
@ -102,7 +138,7 @@ class VoxHandler:
if cmd is None:
self.parser.print_usage()
else:
getattr(self, 'cmd_' + cmd)(args, stdin)
getattr(self, "cmd_" + cmd)(args, stdin)
def cmd_new(self, args, stdin=None):
"""Create a virtual environment in $VIRTUALENV_HOME with python3's ``venv``.
@ -125,7 +161,11 @@ class VoxHandler:
try:
self.vox.activate(args.name)
except KeyError:
print('This environment doesn\'t exist. Create it with "vox new %s".\n' % args.name, file=sys.stderr)
print(
'This environment doesn\'t exist. Create it with "vox new %s".\n'
% args.name,
file=sys.stderr,
)
return None
else:
print('Activated "%s".\n' % args.name)
@ -134,7 +174,10 @@ class VoxHandler:
"""Deactivate the active virtual environment."""
if self.vox.active() is None:
print('No environment currently active. Activate one with "vox activate".\n', file=sys.stderr)
print(
'No environment currently active. Activate one with "vox activate".\n',
file=sys.stderr,
)
return None
env_name = self.vox.deactivate()
print('Deactivated "%s".\n' % env_name)
@ -145,15 +188,18 @@ class VoxHandler:
try:
envs = sorted(self.vox.keys())
except PermissionError:
print('No permissions on VIRTUALENV_HOME')
print("No permissions on VIRTUALENV_HOME")
return None
if not envs:
print('No environments available. Create one with "vox new".\n', file=sys.stderr)
print(
'No environments available. Create one with "vox new".\n',
file=sys.stderr,
)
return None
print('Available environments:')
print('\n'.join(envs))
print("Available environments:")
print("\n".join(envs))
def cmd_remove(self, args, stdin=None):
"""Remove virtual environments.
@ -162,8 +208,11 @@ class VoxHandler:
try:
del self.vox[name]
except voxapi.EnvironmentInUse:
print('The "%s" environment is currently active. In order to remove it, deactivate it first with "vox deactivate %s".\n' % (name, name),
file=sys.stderr)
print(
'The "%s" environment is currently active. In order to remove it, deactivate it first with "vox deactivate %s".\n'
% (name, name),
file=sys.stderr,
)
return
else:
print('Environment "%s" removed.' % name)
@ -179,4 +228,4 @@ class VoxHandler:
return vox(args, stdin=stdin)
aliases['vox'] = VoxHandler.handle
aliases["vox"] = VoxHandler.handle

View file

@ -25,32 +25,46 @@ from xonsh.fs import PathLike, fspath
from xonsh.events import events
events.doc('vox_on_create', """
events.doc(
"vox_on_create",
"""
vox_on_create(env: str) -> None
Fired after an environment is created.
""")
""",
)
events.doc('vox_on_activate', """
events.doc(
"vox_on_activate",
"""
vox_on_activate(env: str) -> None
Fired after an environment is activated.
""")
""",
)
events.doc('vox_on_deactivate', """
events.doc(
"vox_on_deactivate",
"""
vox_on_deactivate(env: str) -> None
Fired after an environment is deactivated.
""")
""",
)
events.doc('vox_on_delete', """
events.doc(
"vox_on_delete",
"""
vox_on_delete(env: str) -> None
Fired after an environment is deleted (through vox).
""")
""",
)
VirtualEnvironment = collections.namedtuple('VirtualEnvironment', ['env', 'bin', 'lib', 'inc'])
VirtualEnvironment = collections.namedtuple(
"VirtualEnvironment", ["env", "bin", "lib", "inc"]
)
def _subdir_names():
@ -61,11 +75,11 @@ def _subdir_names():
may additional logic to get to useful places.
"""
if ON_WINDOWS:
return 'Scripts', 'Lib', 'Include'
return "Scripts", "Lib", "Include"
elif ON_POSIX:
return 'bin', 'lib', 'include'
return "bin", "lib", "include"
else:
raise OSError('This OS is not supported.')
raise OSError("This OS is not supported.")
def _mkvenv(env_dir):
@ -76,17 +90,17 @@ def _mkvenv(env_dir):
"""
env_dir = os.path.normpath(env_dir)
if ON_WINDOWS:
binname = os.path.join(env_dir, 'Scripts')
incpath = os.path.join(env_dir, 'Include')
libpath = os.path.join(env_dir, 'Lib', 'site-packages')
binname = os.path.join(env_dir, "Scripts")
incpath = os.path.join(env_dir, "Include")
libpath = os.path.join(env_dir, "Lib", "site-packages")
elif ON_POSIX:
binname = os.path.join(env_dir, 'bin')
incpath = os.path.join(env_dir, 'include')
libpath = os.path.join(env_dir, 'lib',
'python%d.%d' % sys.version_info[:2],
'site-packages')
binname = os.path.join(env_dir, "bin")
incpath = os.path.join(env_dir, "include")
libpath = os.path.join(
env_dir, "lib", "python%d.%d" % sys.version_info[:2], "site-packages"
)
else:
raise OSError('This OS is not supported.')
raise OSError("This OS is not supported.")
return VirtualEnvironment(env_dir, binname, libpath, incpath)
@ -109,12 +123,12 @@ class Vox(collections.abc.Mapping):
"""
def __init__(self):
if not builtins.__xonsh__.env.get('VIRTUALENV_HOME'):
home_path = os.path.expanduser('~')
self.venvdir = os.path.join(home_path, '.virtualenvs')
builtins.__xonsh__.env['VIRTUALENV_HOME'] = self.venvdir
if not builtins.__xonsh__.env.get("VIRTUALENV_HOME"):
home_path = os.path.expanduser("~")
self.venvdir = os.path.join(home_path, ".virtualenvs")
builtins.__xonsh__.env["VIRTUALENV_HOME"] = self.venvdir
else:
self.venvdir = builtins.__xonsh__.env['VIRTUALENV_HOME']
self.venvdir = builtins.__xonsh__.env["VIRTUALENV_HOME"]
def create(
self,
@ -244,7 +258,9 @@ class Vox(collections.abc.Mapping):
@staticmethod
def _check_reserved(name):
return os.path.basename(name) not in _subdir_names() # FIXME: Check the middle components, too
return (
os.path.basename(name) not in _subdir_names()
) # FIXME: Check the middle components, too
def __getitem__(self, name):
"""Get information about a virtual environment.
@ -256,7 +272,7 @@ class Vox(collections.abc.Mapping):
the current one (throws a KeyError if there isn't one).
"""
if name is ...:
env_paths = [builtins.__xonsh__.env['VIRTUAL_ENV']]
env_paths = [builtins.__xonsh__.env["VIRTUAL_ENV"]]
elif isinstance(name, PathLike):
env_paths = [fspath(name)]
else:
@ -294,11 +310,11 @@ class Vox(collections.abc.Mapping):
"""
bin_, lib, inc = _subdir_names()
for dirpath, dirnames, filenames in os.walk(self.venvdir):
python_exec = os.path.join(dirpath, bin_, 'python')
python_exec = os.path.join(dirpath, bin_, "python")
if ON_WINDOWS:
python_exec += '.exe'
python_exec += ".exe"
if os.access(python_exec, os.X_OK):
yield dirpath[len(self.venvdir) + 1:] # +1 is to remove the separator
yield dirpath[len(self.venvdir) + 1 :] # +1 is to remove the separator
dirnames.clear()
def __len__(self):
@ -316,12 +332,12 @@ class Vox(collections.abc.Mapping):
Returns None if no environment is active.
"""
if 'VIRTUAL_ENV' not in builtins.__xonsh__.env:
if "VIRTUAL_ENV" not in builtins.__xonsh__.env:
return
env_path = builtins.__xonsh__.env['VIRTUAL_ENV']
env_path = builtins.__xonsh__.env["VIRTUAL_ENV"]
if env_path.startswith(self.venvdir):
name = env_path[len(self.venvdir):]
if name[0] in '/\\':
name = env_path[len(self.venvdir) :]
if name[0] in "/\\":
name = name[1:]
return name
else:
@ -338,14 +354,14 @@ class Vox(collections.abc.Mapping):
"""
env = builtins.__xonsh__.env
ve = self[name]
if 'VIRTUAL_ENV' in env:
if "VIRTUAL_ENV" in env:
self.deactivate()
type(self).oldvars = {'PATH': list(env['PATH'])}
env['PATH'].insert(0, ve.bin)
env['VIRTUAL_ENV'] = ve.env
if 'PYTHONHOME' in env:
type(self).oldvars['PYTHONHOME'] = env.pop('PYTHONHOME')
type(self).oldvars = {"PATH": list(env["PATH"])}
env["PATH"].insert(0, ve.bin)
env["VIRTUAL_ENV"] = ve.env
if "PYTHONHOME" in env:
type(self).oldvars["PYTHONHOME"] = env.pop("PYTHONHOME")
events.vox_on_activate.fire(name=name)
@ -354,17 +370,17 @@ class Vox(collections.abc.Mapping):
Deactivate the active virtual environment. Returns its name.
"""
env = builtins.__xonsh__.env
if 'VIRTUAL_ENV' not in env:
raise NoEnvironmentActive('No environment currently active.')
if "VIRTUAL_ENV" not in env:
raise NoEnvironmentActive("No environment currently active.")
env_name = self.active()
if hasattr(type(self), 'oldvars'):
if hasattr(type(self), "oldvars"):
for k, v in type(self).oldvars.items():
env[k] = v
del type(self).oldvars
env.pop('VIRTUAL_ENV')
env.pop("VIRTUAL_ENV")
events.vox_on_deactivate.fire(name=env_name)
return env_name
@ -381,7 +397,9 @@ class Vox(collections.abc.Mapping):
env_path = self[name].env
try:
if self[...].env == env_path:
raise EnvironmentInUse('The "%s" environment is currently active.' % name)
raise EnvironmentInUse(
'The "%s" environment is currently active.' % name
)
except KeyError:
# No current venv, ... fails
pass

View file

@ -17,7 +17,7 @@ def custom_keybindings(bindings, **kw):
# Alt+Left and Alt+Right still jump over smaller word segments.
# See https://github.com/xonsh/xonsh/issues/2403
if ptk_shell_type() == 'prompt_toolkit2':
if ptk_shell_type() == "prompt_toolkit2":
handler = bindings.add
else:
handler = bindings.registry.add_binding