* chore: adding py310 to ci

though this will require code/parser changes, this is to prepare for
upcoming adoption

* fix: set python version as string

* fix: reference to master -> main

* fix: coverage is not reported in master

- disable amalgamation
	1. during coverage report tests
	2. qa tools like mypy may follow imports
- use python 3.9 for coverage and qa report. since it will have more
coverage and better typing support

* chore: use py3.10 with setup-py action

* chore: add news-item check job

* fix: py3.10 error while starting

the match statement is not supported.
while the syntax support is only upto py3.8

* fix: news-item checker

* chore: enable fail report for py310 tests

* test: add test for ptk_shell
This commit is contained in:
Noorhteen Raja NJ 2021-06-07 23:10:40 +05:30 committed by GitHub
parent 099d301fae
commit 3ce8c9b337
Failed to generate hash of commit
34 changed files with 413 additions and 63 deletions

View file

@ -28,3 +28,6 @@ skip_covered = true
skip_empty = true skip_empty = true
show_missing = true show_missing = true
sort = Cover sort = Cover
# something is better than nothing :)
fail_under = 55

27
.github/workflows/check-news-item.yml vendored Normal file
View file

@ -0,0 +1,27 @@
name: Check News Item
on:
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
name: Check News item
steps:
- uses: actions/checkout@v2
- id: file_changes
uses: trilom/file-changes-action@v1.2.4
with:
output: ','
- shell: bash
run: |
added_files='${{ steps.file_changes.outputs.files_added}}'
echo $added_files
if [[ $added_files == *"news/"*.rst* ]]; then
echo "Found news item for the PR"
else
echo "News item for the PR is not found. Please create one from 'news/TEMPLATE.rst'"
exit 1
fi

View file

@ -3,10 +3,10 @@ name: Check Elm
on: on:
push: push:
branches: branches:
- master - main
pull_request: pull_request:
branches: branches:
- master - main
jobs: jobs:
build: build:

View file

@ -16,14 +16,32 @@ environment = jinja2.Environment(
) )
tmpl = environment.get_template("pytest.tmpl") tmpl = environment.get_template("pytest.tmpl")
OS_NAMES = ["linux", "macos", "windows"]
OS_IMAGES = { def get_attrs(cls):
"linux": "ubuntu-latest", for attr, val in vars(cls).items():
"macos": "macOS-latest", if not attr.startswith("__"):
"windows": "windows-latest", yield attr, val
}
PY_MAIN_VERSION = "3.8"
PYTHON_VERSIONS = ["3.6", "3.7", PY_MAIN_VERSION, "3.9"] class OS:
linux = "ubuntu-latest"
macos = "macOS-latest"
windows = "windows-latest"
OS_NAMES = [attr for attr, _ in get_attrs(OS)]
class PY:
_36 = "3.6"
_37 = "3.7"
_38 = "3.8"
_39 = "3.9"
_310 = "3.10-dev"
PY_MAIN_VERSION = PY._39
PYTHON_VERSIONS = [val for _, val in get_attrs(PY)]
ALLOWED_FAILURES = [] ALLOWED_FAILURES = []
@ -31,13 +49,16 @@ ALLOWED_FAILURES = []
def write_to_file( def write_to_file(
tst: str, os_name: str, python_version: str, report_coverage=False, **kwargs tst: str, os_name: str, python_version: str, report_coverage=False, **kwargs
): ):
fname = os.path.join(CURR_DIR, f"{tst}-{os_name}-{python_version}.yml") py_major = python_version.split("-")[0]
fname = os.path.join(CURR_DIR, f"{tst}-{os_name}-{py_major}.yml")
dev_version = python_version.endswith("-dev")
result = tmpl.render( result = tmpl.render(
OS_NAME=os_name, OS_NAME=os_name,
OS_IMAGE=OS_IMAGES[os_name], OS_IMAGE=getattr(OS, os_name),
PYTHON_VERSION=python_version, PYTHON_VERSION=python_version,
NAME=tst, NAME=tst,
allow_failure=python_version in ALLOWED_FAILURES, allow_failure=python_version in ALLOWED_FAILURES,
use_setup_py=dev_version,
report_coverage=report_coverage, report_coverage=report_coverage,
**kwargs, **kwargs,
) )
@ -48,7 +69,7 @@ def write_to_file(
for os_name, python_version in product(OS_NAMES, PYTHON_VERSIONS): for os_name, python_version in product(OS_NAMES, PYTHON_VERSIONS):
report_coverage = python_version == PY_MAIN_VERSION and os_name == "linux" report_coverage = python_version == PY_MAIN_VERSION and os_name == "linux"
if report_coverage: if report_coverage:
test_cmd = "test --report-coverage -- --timeout=240" test_cmd = "test --report-coverage --no-amalgam -- --timeout=240"
else: else:
test_cmd = "test -- --timeout=240" test_cmd = "test -- --timeout=240"
@ -61,4 +82,4 @@ for os_name, python_version in product(OS_NAMES, PYTHON_VERSIONS):
) )
# qa workflow # qa workflow
write_to_file("qa", "linux", "3.8", test_cmd="qa") write_to_file("qa", "linux", PY_MAIN_VERSION, test_cmd="qa")

57
.github/workflows/pytest-linux-3.10.yml vendored Normal file
View file

@ -0,0 +1,57 @@
name: pytest linux 3.10-dev
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
python-version: [ "3.10-dev" ]
defaults:
run:
shell: bash
name: Python ${{ matrix.python-version }} ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: |
~/conda_pkgs_dir
~/miniconda*/envs/
key: ${{ runner.os }}-${{ matrix.python-version }}-env-${{ hashFiles('requirements/tests.txt') }}
restore-keys: |
${{ runner.os }}-${{ matrix.python-version }}-env-
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get pip cache dir
id: pip-cache
run: |
python -m pip install --upgrade pip
echo "::set-output name=dir::$(python -m pip cache dir)"
- name: pip cache
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-pip-${{ hashFiles('requirements/tests.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip --version
python -m pip install -r requirements/tests.txt
python -m pip install . --no-deps
- name: Run tests
run: python -m xonsh run-tests.xsh test -- --timeout=240

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
python-version: [3.6] python-version: [ "3.6" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
python-version: [3.7] python-version: [ "3.7" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
python-version: [3.8] python-version: [ "3.8" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}
@ -57,8 +57,4 @@ jobs:
python -m pip install -r requirements/tests.txt python -m pip install -r requirements/tests.txt
python -m pip install . --no-deps python -m pip install . --no-deps
- name: Run tests - name: Run tests
run: python -m xonsh run-tests.xsh test --report-coverage -- --timeout=240 run: python -m xonsh run-tests.xsh test -- --timeout=240
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
verbose: true

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
python-version: [3.9] python-version: [ "3.9" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}
@ -55,6 +55,10 @@ jobs:
run: | run: |
python -m pip --version python -m pip --version
python -m pip install -r requirements/tests.txt python -m pip install -r requirements/tests.txt
python -m pip install . --no-deps python -m pip install -e . --no-deps
- name: Run tests - name: Run tests
run: python -m xonsh run-tests.xsh test -- --timeout=240 run: python -m xonsh run-tests.xsh test --report-coverage --no-amalgam -- --timeout=240
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
verbose: true

57
.github/workflows/pytest-macos-3.10.yml vendored Normal file
View file

@ -0,0 +1,57 @@
name: pytest macos 3.10-dev
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macOS-latest]
python-version: [ "3.10-dev" ]
defaults:
run:
shell: bash
name: Python ${{ matrix.python-version }} ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: |
~/conda_pkgs_dir
~/miniconda*/envs/
key: ${{ runner.os }}-${{ matrix.python-version }}-env-${{ hashFiles('requirements/tests.txt') }}
restore-keys: |
${{ runner.os }}-${{ matrix.python-version }}-env-
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get pip cache dir
id: pip-cache
run: |
python -m pip install --upgrade pip
echo "::set-output name=dir::$(python -m pip cache dir)"
- name: pip cache
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-pip-${{ hashFiles('requirements/tests.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip --version
python -m pip install -r requirements/tests.txt
python -m pip install . --no-deps
- name: Run tests
run: python -m xonsh run-tests.xsh test -- --timeout=240

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [macOS-latest] os: [macOS-latest]
python-version: [3.6] python-version: [ "3.6" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [macOS-latest] os: [macOS-latest]
python-version: [3.7] python-version: [ "3.7" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [macOS-latest] os: [macOS-latest]
python-version: [3.8] python-version: [ "3.8" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [macOS-latest] os: [macOS-latest]
python-version: [3.9] python-version: [ "3.9" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -0,0 +1,57 @@
name: pytest windows 3.10-dev
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest]
python-version: [ "3.10-dev" ]
defaults:
run:
shell: bash
name: Python ${{ matrix.python-version }} ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: |
~/conda_pkgs_dir
~/miniconda*/envs/
key: ${{ runner.os }}-${{ matrix.python-version }}-env-${{ hashFiles('requirements/tests.txt') }}
restore-keys: |
${{ runner.os }}-${{ matrix.python-version }}-env-
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get pip cache dir
id: pip-cache
run: |
python -m pip install --upgrade pip
echo "::set-output name=dir::$(python -m pip cache dir)"
- name: pip cache
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-pip-${{ hashFiles('requirements/tests.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip --version
python -m pip install -r requirements/tests.txt
python -m pip install . --no-deps
- name: Run tests
run: python -m xonsh run-tests.xsh test -- --timeout=240

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [windows-latest] os: [windows-latest]
python-version: [3.6] python-version: [ "3.6" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [windows-latest] os: [windows-latest]
python-version: [3.7] python-version: [ "3.7" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [windows-latest] os: [windows-latest]
python-version: [3.8] python-version: [ "3.8" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [windows-latest] os: [windows-latest]
python-version: [3.9] python-version: [ "3.9" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

View file

@ -10,41 +10,52 @@ on:
jobs: jobs:
build: build:
{% raw %}
runs-on: ${{ matrix.os }} runs-on: {{ '${{ matrix.os }}' }}
{% endraw %}
strategy: strategy:
matrix: matrix:
os: [{{ OS_IMAGE }}] os: [{{ OS_IMAGE }}]
python-version: [{{ PYTHON_VERSION }}] python-version: [ "{{ PYTHON_VERSION }}" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash{% if not use_setup_py %} -l {0}{% endif %}
{% raw %} {% raw %}
name: Python ${{ matrix.python-version }} ${{ matrix.os }} name: Python ${{ matrix.python-version }} ${{ matrix.os }}
{% endraw %}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/cache@v2 - uses: actions/cache@v2
with: with:{% raw %}
path: | path: |
~/conda_pkgs_dir ~/conda_pkgs_dir
~/miniconda*/envs/ ~/miniconda*/envs/
key: ${{ runner.os }}-${{ matrix.python-version }}-env-${{ hashFiles('requirements/tests.txt') }} key: ${{ runner.os }}-${{ matrix.python-version }}-env-${{ hashFiles('requirements/tests.txt') }}
restore-keys: | restore-keys: |
${{ runner.os }}-${{ matrix.python-version }}-env- ${{ runner.os }}-${{ matrix.python-version }}-env-{% endraw %}
{% if use_setup_py %}
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: {{ '${{ matrix.python-version }}' }}
{% else %}
- name: Setup conda - name: Setup conda
uses: conda-incubator/setup-miniconda@v2 uses: conda-incubator/setup-miniconda@v2
with: with:
activate-environment: xonsh-test activate-environment: xonsh-test
auto-update-conda: true auto-update-conda: true
python-version: ${{ matrix.python-version }} # this itself makes sure that Python version is installed python-version: {{ '${{ matrix.python-version }}' }} # this itself makes sure that Python version is installed
condarc-file: ci/condarc.yml condarc-file: ci/condarc.yml
use-only-tar-bz2: true use-only-tar-bz2: true
{% endif %}
- name: Get pip cache dir - name: Get pip cache dir
id: pip-cache id: pip-cache
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
echo "::set-output name=dir::$(python -m pip cache dir)" echo "::set-output name=dir::$(python -m pip cache dir)"
{%- raw %}
- name: pip cache - name: pip cache
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
@ -52,12 +63,12 @@ jobs:
key: ${{ runner.os }}-pip-${{ hashFiles('requirements/tests.txt') }} key: ${{ runner.os }}-pip-${{ hashFiles('requirements/tests.txt') }}
restore-keys: | restore-keys: |
${{ runner.os }}-pip- ${{ runner.os }}-pip-
{% endraw %}
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip --version python -m pip --version
python -m pip install -r requirements/tests.txt python -m pip install -r requirements/tests.txt
python -m pip install . --no-deps python -m pip install{% if report_coverage %} -e{% endif %} . --no-deps
{% endraw %}
- name: Run tests - name: Run tests
run: python -m xonsh run-tests.xsh {{ test_cmd }} run: python -m xonsh run-tests.xsh {{ test_cmd }}
{% if allow_failure %} {% if allow_failure %}

View file

@ -1,4 +1,4 @@
name: qa linux 3.8 name: qa linux 3.9
on: on:
push: push:
@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
python-version: [3.8] python-version: [ "3.9" ]
defaults: defaults:
run: run:
shell: bash -l {0} shell: bash -l {0}

3
.gitignore vendored
View file

@ -83,3 +83,6 @@ xonsh/webconfig/js/app.js
# mypy # mypy
.dmypy.json .dmypy.json
.mypy_cache .mypy_cache
# testmon pytest-plugin
.testmondata

View file

@ -8,7 +8,7 @@ xonsh
The language is a superset of Python 3.6+ with additional shell primitives. The language is a superset of Python 3.6+ with additional shell primitives.
xonsh (pronounced *conch*) is meant for the daily use of experts and novices alike. xonsh (pronounced *conch*) is meant for the daily use of experts and novices alike.
.. image:: https://raw.githubusercontent.com/xonsh/xonsh/master/docs/_static/xonsh5.png .. image:: https://raw.githubusercontent.com/xonsh/xonsh/main/docs/_static/xonsh5.png
:alt: What is xonsh? :alt: What is xonsh?
:align: center :align: center
@ -24,7 +24,7 @@ xonsh
:target: https://matrix.to/#/#xonsh:feneas.org :target: https://matrix.to/#/#xonsh:feneas.org
:alt: Matrix room: #xonsh:feneas.org :alt: Matrix room: #xonsh:feneas.org
.. image:: https://travis-ci.org/xonsh/xonsh.svg?branch=master .. image:: https://travis-ci.org/xonsh/xonsh.svg?branch=main
:target: https://travis-ci.org/xonsh/xonsh :target: https://travis-ci.org/xonsh/xonsh
:alt: Travis :alt: Travis

23
news/py_3.10_fix.rst Normal file
View file

@ -0,0 +1,23 @@
**Added:**
* Now xonsh will work with Python 3.10. (Match statement is not supported).
**Changed:**
* <news item>
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* <news item>
**Security:**
* <news item>

View file

@ -26,11 +26,12 @@ def test(ns: argparse.Namespace):
args = ns.pytest_args args = ns.pytest_args
if not $(xonsh -c "import xonsh.main; print(xonsh.main.__file__, end='')").endswith("__amalgam__.py"): if (not ns.no_amalgam) and not $(xonsh -c "import xonsh.main; print(xonsh.main.__file__, end='')").endswith("__amalgam__.py"):
echo "Tests need to run from the amalgamated xonsh! install with `pip install .` (without `-e`)" echo "Tests need to run from the amalgamated xonsh! install with `pip install .` (without `-e`)"
exit(1) exit(1)
if ns.report_coverage: if ns.report_coverage:
$XONSH_NO_AMALGAMATE = True
![pytest @(_replace_args(args, 0)) --cov --cov-report=xml --cov-report=term] ![pytest @(_replace_args(args, 0)) --cov --cov-report=xml --cov-report=term]
else: else:
![pytest @(_replace_args(args, 0))] ![pytest @(_replace_args(args, 0))]
@ -38,6 +39,7 @@ def test(ns: argparse.Namespace):
def qa(ns: argparse.Namespace): def qa(ns: argparse.Namespace):
"""QA checks""" """QA checks"""
$XONSH_NO_AMALGAMATE = True
echo "---------- Check Black formatter -----------" echo "---------- Check Black formatter -----------"
black --check xonsh xontrib tests black --check xonsh xontrib tests
@ -66,10 +68,18 @@ if __name__ == '__main__':
) )
test_parser.add_argument( test_parser.add_argument(
'--report-coverage', '--report-coverage',
'-c',
action="store_true", action="store_true",
default=False, default=False,
help="Report coverage at the end of the test", help="Report coverage at the end of the test",
) )
test_parser.add_argument(
'--no-amalgam',
'-n',
action="store_true",
default=False,
help="Disable amalgamation check.",
)
test_parser.set_defaults(func=test) test_parser.set_defaults(func=test)
qa_parser = commands.add_parser('qa', help=qa.__doc__) qa_parser = commands.add_parser('qa', help=qa.__doc__)

View file

@ -129,6 +129,21 @@ def completion_context_parse():
return CompletionContextParser().parse return CompletionContextParser().parse
@pytest.fixture
def ptk_shell(xonsh_execer):
from prompt_toolkit.input import create_pipe_input
from prompt_toolkit.output import DummyOutput
from xonsh.ptk_shell.shell import PromptToolkitShell
inp = create_pipe_input()
out = DummyOutput()
shell = PromptToolkitShell(
execer=xonsh_execer, ctx={}, ptk_args={"input": inp, "output": out}
)
yield inp, out, shell
inp.close()
def pytest_configure(config): def pytest_configure(config):
"""Abort test run if --flake8 requested, since it would hang on parser_test.py""" """Abort test run if --flake8 requested, since it would hang on parser_test.py"""
if config.getoption("--flake8", ""): if config.getoption("--flake8", ""):

View file

@ -5,6 +5,7 @@
import os import os
import os.path import os.path
import subprocess import subprocess
import sys
import pytest import pytest
from xonsh import dirstack from xonsh import dirstack
@ -31,6 +32,10 @@ pytestmark = pytest.mark.skipif(
len(TEMP_DRIVE) < MAX_TEMP_DRIVES, len(TEMP_DRIVE) < MAX_TEMP_DRIVES,
reason="Too many drive letters are already used by Windows to run the tests.", reason="Too many drive letters are already used by Windows to run the tests.",
) )
xfail_py310 = pytest.mark.xfail(
sys.version_info >= (3, 10),
reason="throws file-not-found error (todo: fix)",
)
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
@ -287,6 +292,7 @@ def xonsh_builtins_cd(xession):
@pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality") @pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality")
@xfail_py310
def test_uncpushd_cd_unc_auto_pushd(xonsh_builtins_cd, with_unc_check_enabled): def test_uncpushd_cd_unc_auto_pushd(xonsh_builtins_cd, with_unc_check_enabled):
xonsh_builtins_cd.env["AUTO_PUSHD"] = True xonsh_builtins_cd.env["AUTO_PUSHD"] = True
so, se, rc = dirstack.cd([r"\\localhost\uncpushd_test_PARENT"]) so, se, rc = dirstack.cd([r"\\localhost\uncpushd_test_PARENT"])
@ -298,6 +304,7 @@ def test_uncpushd_cd_unc_auto_pushd(xonsh_builtins_cd, with_unc_check_enabled):
@pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality") @pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality")
@xfail_py310
def test_uncpushd_cd_unc_nocheck(xonsh_builtins_cd, with_unc_check_disabled): def test_uncpushd_cd_unc_nocheck(xonsh_builtins_cd, with_unc_check_disabled):
if with_unc_check_disabled == 0: if with_unc_check_disabled == 0:
return return
@ -306,6 +313,7 @@ def test_uncpushd_cd_unc_nocheck(xonsh_builtins_cd, with_unc_check_disabled):
@pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality") @pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality")
@xfail_py310
def test_uncpushd_cd_unc_no_auto_pushd(xonsh_builtins_cd, with_unc_check_enabled): def test_uncpushd_cd_unc_no_auto_pushd(xonsh_builtins_cd, with_unc_check_enabled):
if with_unc_check_enabled == 0: if with_unc_check_enabled == 0:
return return

View file

@ -158,3 +158,10 @@ def test_annotated_assign():
def test_exec_eol(): def test_exec_eol():
locs = dict() locs = dict()
assert check_exec("a=0", locs=locs) and check_exec("a=0\n", locs=locs) assert check_exec("a=0", locs=locs) and check_exec("a=0\n", locs=locs)
def test_exec_print(capsys):
ls = {"nested": "some long list"}
check_exec("print(ls)", locs=dict(ls=ls))
out, err = capsys.readouterr()
assert out.strip() == repr(ls)

View file

@ -3,7 +3,6 @@
import sys import sys
import pytest import pytest
from xonsh.platform import minimum_required_ptk_version from xonsh.platform import minimum_required_ptk_version
# verify error if ptk not installed or below min # verify error if ptk not installed or below min
@ -127,4 +126,10 @@ def test_remove_ansi_osc(raw_prompt, prompt, osc_tokens):
assert removed == ref assert removed == ref
# someday: initialize PromptToolkitShell and have it actually do something. def test_ptk_prompt(ptk_shell):
inp, out, shell = ptk_shell
text = "hello"
inp.send_text(f"{text}\n") # note: terminate with '\n'
result = shell.singleline()
# todo: check rendered output using https://pyte.readthedocs.io/
assert result == text

View file

@ -149,7 +149,10 @@ def test_color_token_by_name(in_tuple, exp_ct, exp_ansi_colors, xs_LS_COLORS):
assert ansi_colors == exp_ansi_colors, "color token mapped to correct color string" assert ansi_colors == exp_ansi_colors, "color token mapped to correct color string"
def test_XonshStyle_init_file_color_tokens(xs_LS_COLORS): def test_XonshStyle_init_file_color_tokens(xs_LS_COLORS, monkeypatch):
keys = list(file_color_tokens)
for n in keys:
monkeypatch.delitem(file_color_tokens, n)
xs = XonshStyle() xs = XonshStyle()
assert xs.styles assert xs.styles
assert type(file_color_tokens) is dict assert type(file_color_tokens) is dict

View file

@ -6,7 +6,9 @@ from xonsh.platform import PYTHON_VERSION_INFO
@lazyobject @lazyobject
def Parser(): def Parser():
if PYTHON_VERSION_INFO > (3, 9): if PYTHON_VERSION_INFO > (3, 10):
from xonsh.parsers.v310 import Parser as p
elif PYTHON_VERSION_INFO > (3, 9):
from xonsh.parsers.v39 import Parser as p from xonsh.parsers.v39 import Parser as p
elif PYTHON_VERSION_INFO > (3, 8): elif PYTHON_VERSION_INFO > (3, 8):
from xonsh.parsers.v38 import Parser as p from xonsh.parsers.v38 import Parser as p

38
xonsh/parsers/v310.py Normal file
View file

@ -0,0 +1,38 @@
"""Handles changes since PY310
handle
- import-alias requiring lineno
"""
import ast
from xonsh.parsers.v39 import Parser as ThreeNineParser
from xonsh.ply.ply import yacc
class Parser(ThreeNineParser):
def p_import_from_post_times(self, p):
"""import_from_post : TIMES"""
p[0] = [ast.alias(name=p[1], asname=None, **self.get_line_cols(p, 1))]
def p_import_as_name(self, p):
"""import_as_name : NAME as_name_opt"""
self.p_dotted_as_name(p)
def p_dotted_as_name(self, p: yacc.YaccProduction):
"""dotted_as_name : dotted_name as_name_opt"""
alias_idx = 2
p[0] = ast.alias(
name=p[1], asname=p[alias_idx], **self.get_line_cols(p, alias_idx)
)
@staticmethod
def get_line_cols(p: yacc.YaccProduction, idx: int):
line_no, end_line_no = p.linespan(idx)
col_offset, end_col_offset = p.lexspan(idx)
return dict(
lineno=line_no,
end_lineno=end_line_no,
col_offset=col_offset,
end_col_offset=end_col_offset,
)

View file

@ -191,18 +191,19 @@ class PromptToolkitShell(BaseShell):
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
ptk_args = kwargs.pop("ptk_args", {})
super().__init__(**kwargs) super().__init__(**kwargs)
if ON_WINDOWS: if ON_WINDOWS:
winutils.enable_virtual_terminal_processing() winutils.enable_virtual_terminal_processing()
self._first_prompt = True self._first_prompt = True
self.history = ThreadedHistory(PromptToolkitHistory()) self.history = ThreadedHistory(PromptToolkitHistory())
ptk_args = {"history": self.history} ptk_args.setdefault("history", self.history)
if not XSH.env.get("XONSH_COPY_ON_DELETE", False): if not XSH.env.get("XONSH_COPY_ON_DELETE", False):
disable_copy_on_deletion() disable_copy_on_deletion()
if HAVE_SYS_CLIPBOARD: if HAVE_SYS_CLIPBOARD:
ptk_args["clipboard"] = PyperclipClipboard() ptk_args.setdefault("clipboard", PyperclipClipboard())
self.prompter = PromptSession(**ptk_args) self.prompter: PromptSession = PromptSession(**ptk_args)
self.prompt_formatter = PTKPromptFormatter(self.prompter) self.prompt_formatter = PTKPromptFormatter(self.prompter)
self.pt_completer = PromptToolkitCompleter(self.completer, self.ctx, self) self.pt_completer = PromptToolkitCompleter(self.completer, self.ctx, self)

View file

@ -7,6 +7,14 @@ from xonsh.built_ins import XSH
__all__ = () __all__ = ()
def _warn_not_supported(msg: str):
print(
f"""Not supported ``{msg}`` in xontrib bashisms.
PRs are welcome - https://github.com/xonsh/xonsh/blob/main/xontrib/bashisms.py""",
file=sys.stderr,
)
@XSH.builtins.events.on_transform_command @XSH.builtins.events.on_transform_command
def bash_preproc(cmd, **kw): def bash_preproc(cmd, **kw):
bang_previous = { bang_previous = {
@ -105,10 +113,7 @@ def _set(args):
elif arg == "+x": elif arg == "+x":
XSH.env["XONSH_TRACE_SUBPROC"] = False XSH.env["XONSH_TRACE_SUBPROC"] = False
else: else:
print( _warn_not_supported(f"set {arg}")
"Not supported in xontrib bashisms.\nPRs are welcome - https://github.com/xonsh/xonsh/blob/master/xontrib/bashisms.py",
file=sys.stderr,
)
XSH.aliases["set"] = _set XSH.aliases["set"] = _set
@ -136,10 +141,7 @@ def _shopt(args):
elif opt == "-u" and optname == "dotglob": elif opt == "-u" and optname == "dotglob":
XSH.env["DOTGLOB"] = False XSH.env["DOTGLOB"] = False
else: else:
print( _warn_not_supported(f"shopt {args}")
"Not supported in xontrib bashisms.\nPRs are welcome - https://github.com/xonsh/xonsh/blob/master/xontrib/bashisms.py",
file=sys.stderr,
)
XSH.aliases["shopt"] = _shopt XSH.aliases["shopt"] = _shopt