mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 08:24:40 +01:00
Merge branch 'master' of https://github.com/xonsh/xonsh
This commit is contained in:
commit
b38c477402
14 changed files with 35 additions and 260 deletions
|
@ -4,8 +4,8 @@ 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"
|
||||
|
|
|
@ -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:
|
||||
|
@ -220,7 +175,6 @@ workflows:
|
|||
version: 2
|
||||
run_all_pythons:
|
||||
jobs:
|
||||
- build_34
|
||||
- build_35
|
||||
- build_36
|
||||
- build_black
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
name: py34-xonsh-test
|
||||
channels:
|
||||
- conda-forge
|
||||
- defaults
|
||||
dependencies:
|
||||
- python=3.4
|
||||
- pygments
|
||||
- prompt_toolkit
|
||||
- pytest
|
||||
- pytest-timeout
|
||||
- numpy
|
||||
- psutil
|
||||
- matplotlib
|
||||
- flake8
|
||||
- coverage
|
||||
- pyflakes
|
||||
- pytest-cov
|
||||
- codecov
|
||||
# conda forge doesn't have the following for Python v3.4
|
||||
- pip:
|
||||
- pytest-flake8
|
|
@ -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.
|
||||
|
|
25
news/remove_py34.rst
Normal file
25
news/remove_py34.rst
Normal file
|
@ -0,0 +1,25 @@
|
|||
**Added:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Changed:**
|
||||
|
||||
* <news item>
|
||||
* Update documentation pointing to the minimal required version of
|
||||
Python (3.5).
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* Drop support for Python 3.4.
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
4
setup.py
4
setup.py
|
@ -325,8 +325,8 @@ if HAVE_SETUPTOOLS:
|
|||
|
||||
def main():
|
||||
"""The main entry point."""
|
||||
if sys.version_info[:2] < (3, 4):
|
||||
sys.exit("xonsh currently requires Python 3.4+")
|
||||
if sys.version_info[:2] < (3, 5):
|
||||
sys.exit("xonsh currently requires Python 3.5+")
|
||||
try:
|
||||
if "--name" not in sys.argv:
|
||||
logo_fname = os.path.join(os.path.dirname(__file__), "logo.txt")
|
||||
|
|
|
@ -11,7 +11,7 @@ from xonsh.ast import AST, With, Pass, pdump
|
|||
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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -76,7 +76,7 @@ from xonsh.tools import (
|
|||
)
|
||||
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()
|
||||
|
@ -1653,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__)
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Add table
Reference in a new issue