mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-06 09:20:57 +01:00
Merge branch 'master' into aspace
This commit is contained in:
commit
73e6e4b34e
8 changed files with 97 additions and 11 deletions
14
news/iglob.rst
Normal file
14
news/iglob.rst
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
**Added:** None
|
||||||
|
|
||||||
|
**Changed:** None
|
||||||
|
|
||||||
|
**Deprecated:** None
|
||||||
|
|
||||||
|
**Removed:** None
|
||||||
|
|
||||||
|
**Fixed:**
|
||||||
|
|
||||||
|
* Made an exceptional case in ``iglobpath()`` more robust when Python globbing
|
||||||
|
fails for due to strange scrandir issue.
|
||||||
|
|
||||||
|
**Security:** None
|
15
news/synstar.rst
Normal file
15
news/synstar.rst
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
**Added:** None
|
||||||
|
|
||||||
|
**Changed:** None
|
||||||
|
|
||||||
|
**Deprecated:** None
|
||||||
|
|
||||||
|
**Removed:** None
|
||||||
|
|
||||||
|
**Fixed:**
|
||||||
|
|
||||||
|
* Properly throw ``SyntaxError`` when no kwargs are defined
|
||||||
|
in a kwarg-only function. This used to throw a
|
||||||
|
``TypeError: 'NoneType' object is not iterable``.
|
||||||
|
|
||||||
|
**Security:** None
|
13
news/teenc.rst
Normal file
13
news/teenc.rst
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
**Added:** None
|
||||||
|
|
||||||
|
**Changed:** None
|
||||||
|
|
||||||
|
**Deprecated:** None
|
||||||
|
|
||||||
|
**Removed:** None
|
||||||
|
|
||||||
|
**Fixed:**
|
||||||
|
|
||||||
|
* Addressed issue where encoding and errors were None when teeing output.
|
||||||
|
|
||||||
|
**Security:** None
|
|
@ -2310,3 +2310,8 @@ def test_syntax_error_augassign_ops(exp):
|
||||||
def test_syntax_error_augassign_cmp(exp):
|
def test_syntax_error_augassign_cmp(exp):
|
||||||
with pytest.raises(SyntaxError):
|
with pytest.raises(SyntaxError):
|
||||||
PARSER.parse('{} += a'.format(exp))
|
PARSER.parse('{} += a'.format(exp))
|
||||||
|
|
||||||
|
|
||||||
|
def test_syntax_error_bar_kwonlyargs():
|
||||||
|
with pytest.raises(SyntaxError):
|
||||||
|
PARSER.parse('def spam(*):\n pass\n', mode='exec')
|
||||||
|
|
|
@ -27,7 +27,7 @@ from xonsh.tools import (
|
||||||
pathsep_to_upper_seq, seq_to_upper_pathsep, expandvars, is_int_as_str, is_slice_as_str,
|
pathsep_to_upper_seq, seq_to_upper_pathsep, expandvars, is_int_as_str, is_slice_as_str,
|
||||||
ensure_timestamp, get_portions, is_balanced, subexpr_before_unbalanced,
|
ensure_timestamp, get_portions, is_balanced, subexpr_before_unbalanced,
|
||||||
swap_values, get_logical_line, replace_logical_line, check_quotes, deprecated,
|
swap_values, get_logical_line, replace_logical_line, check_quotes, deprecated,
|
||||||
is_writable_file, balanced_parens)
|
is_writable_file, balanced_parens, iglobpath)
|
||||||
from xonsh.environ import Env
|
from xonsh.environ import Env
|
||||||
|
|
||||||
from tools import skip_if_on_windows, skip_if_on_unix
|
from tools import skip_if_on_windows, skip_if_on_unix
|
||||||
|
@ -1360,3 +1360,17 @@ def test_deprecated_past_expiry_raises_assertion_error(expired_version):
|
||||||
|
|
||||||
with pytest.raises(AssertionError):
|
with pytest.raises(AssertionError):
|
||||||
my_function()
|
my_function()
|
||||||
|
|
||||||
|
|
||||||
|
def test_iglobpath_empty_str(monkeypatch, xonsh_builtins):
|
||||||
|
# makes sure that iglobpath works, even when os.scandir() and os.listdir()
|
||||||
|
# fail to return valid results, like an empty filename
|
||||||
|
def mockscandir(path):
|
||||||
|
yield ''
|
||||||
|
if hasattr(os, 'scandir'):
|
||||||
|
monkeypatch.setattr(os, 'scandir', mockscandir)
|
||||||
|
def mocklistdir(path):
|
||||||
|
return ['']
|
||||||
|
monkeypatch.setattr(os, 'listdir', mocklistdir)
|
||||||
|
paths = list(iglobpath('some/path'))
|
||||||
|
assert len(paths) == 0
|
||||||
|
|
|
@ -42,10 +42,11 @@ class _TeeStdBuf(io.RawIOBase):
|
||||||
The in memory stream buffer.
|
The in memory stream buffer.
|
||||||
encoding : str or None, optional
|
encoding : str or None, optional
|
||||||
The encoding of the stream. Only used if stdbuf is a text stream,
|
The encoding of the stream. Only used if stdbuf is a text stream,
|
||||||
rather than a binary one.
|
rather than a binary one. Defaults to $XONSH_ENCODING if None.
|
||||||
errors : str or None, optional
|
errors : str or None, optional
|
||||||
The error form for the encoding of the stream. Only used if stdbuf
|
The error form for the encoding of the stream. Only used if stdbuf
|
||||||
is a text stream, rather than a binary one.
|
is a text stream, rather than a binary one. Deafults to
|
||||||
|
$XONSH_ENCODING_ERRORS if None.
|
||||||
prestd : bytes, optional
|
prestd : bytes, optional
|
||||||
The prefix to prepend to the standard buffer.
|
The prefix to prepend to the standard buffer.
|
||||||
poststd : bytes, optional
|
poststd : bytes, optional
|
||||||
|
@ -53,8 +54,9 @@ class _TeeStdBuf(io.RawIOBase):
|
||||||
"""
|
"""
|
||||||
self.stdbuf = stdbuf
|
self.stdbuf = stdbuf
|
||||||
self.membuf = membuf
|
self.membuf = membuf
|
||||||
self.encoding = encoding
|
env = builtins.__xonsh_env__
|
||||||
self.errors = errors
|
self.encoding = env.get('XONSH_ENCODING') if encoding is None else encoding
|
||||||
|
self.errors = env.get('XONSH_ENCODING_ERRORS') if errors is None else errors
|
||||||
self.prestd = prestd
|
self.prestd = prestd
|
||||||
self.poststd = poststd
|
self.poststd = poststd
|
||||||
self._std_is_binary = not hasattr(stdbuf, 'encoding')
|
self._std_is_binary = not hasattr(stdbuf, 'encoding')
|
||||||
|
|
|
@ -646,21 +646,37 @@ class BaseParser(object):
|
||||||
p[0] = ast.arguments(args=[], vararg=None, kwonlyargs=[],
|
p[0] = ast.arguments(args=[], vararg=None, kwonlyargs=[],
|
||||||
kw_defaults=[], kwarg=p[2], defaults=[])
|
kw_defaults=[], kwarg=p[2], defaults=[])
|
||||||
|
|
||||||
def p_typedargslist_times4(self, p):
|
def p_typedargslist_times4_tfpdef(self, p):
|
||||||
"""typedargslist : TIMES tfpdef_opt comma_pow_tfpdef_opt"""
|
"""typedargslist : TIMES tfpdef comma_pow_tfpdef_opt"""
|
||||||
|
# *args, **kwargs
|
||||||
p0 = ast.arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[],
|
p0 = ast.arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[],
|
||||||
kwarg=p[3], defaults=[])
|
kwarg=p[3], defaults=[])
|
||||||
self._set_var_args(p0, p[2], None)
|
self._set_var_args(p0, p[2], None)
|
||||||
p[0] = p0
|
p[0] = p0
|
||||||
|
|
||||||
def p_typedargslist_times5(self, p):
|
def p_typedargslist_times4_comma(self, p):
|
||||||
"""typedargslist : TIMES tfpdef_opt comma_tfpdef_list comma_pow_tfpdef_opt"""
|
"""typedargslist : TIMES comma_pow_tfpdef"""
|
||||||
|
# *, **kwargs
|
||||||
|
p0 = ast.arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[],
|
||||||
|
kwarg=p[2], defaults=[])
|
||||||
|
p[0] = p0
|
||||||
|
|
||||||
|
def p_typedargslist_times5_tdpdef(self, p):
|
||||||
|
"""typedargslist : TIMES tfpdef comma_tfpdef_list comma_pow_tfpdef_opt"""
|
||||||
# *args, x, **kwargs
|
# *args, x, **kwargs
|
||||||
p0 = ast.arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[],
|
p0 = ast.arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[],
|
||||||
kwarg=p[4], defaults=[])
|
kwarg=p[4], defaults=[])
|
||||||
self._set_var_args(p0, p[2], p[3]) # *args
|
self._set_var_args(p0, p[2], p[3]) # *args
|
||||||
p[0] = p0
|
p[0] = p0
|
||||||
|
|
||||||
|
def p_typedargslist_times5_comma(self, p):
|
||||||
|
"""typedargslist : TIMES comma_tfpdef_list comma_pow_tfpdef_opt"""
|
||||||
|
# *, x, **kwargs
|
||||||
|
p0 = ast.arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[],
|
||||||
|
kwarg=p[3], defaults=[])
|
||||||
|
self._set_var_args(p0, None, p[2]) # *args
|
||||||
|
p[0] = p0
|
||||||
|
|
||||||
def p_typedargslist_t5(self, p):
|
def p_typedargslist_t5(self, p):
|
||||||
"""typedargslist : tfpdef equals_test_opt comma_tfpdef_list_opt comma_opt"""
|
"""typedargslist : tfpdef equals_test_opt comma_tfpdef_list_opt comma_opt"""
|
||||||
# x
|
# x
|
||||||
|
@ -733,6 +749,9 @@ class BaseParser(object):
|
||||||
def _set_args_def(self, argmts, vals, kwargs=False):
|
def _set_args_def(self, argmts, vals, kwargs=False):
|
||||||
args, defs = (argmts.kwonlyargs, argmts.kw_defaults) if kwargs else \
|
args, defs = (argmts.kwonlyargs, argmts.kw_defaults) if kwargs else \
|
||||||
(argmts.args, argmts.defaults)
|
(argmts.args, argmts.defaults)
|
||||||
|
if vals is None and kwargs:
|
||||||
|
loc = self.currloc(self.lineno, self.col)
|
||||||
|
self._parse_error('named arguments must follow bare *', loc)
|
||||||
for v in vals:
|
for v in vals:
|
||||||
args.append(v['arg'])
|
args.append(v['arg'])
|
||||||
d = v['default']
|
d = v['default']
|
||||||
|
@ -758,7 +777,7 @@ class BaseParser(object):
|
||||||
self._set_args_def(p0, p3)
|
self._set_args_def(p0, p3)
|
||||||
|
|
||||||
def _set_var_args(self, p0, vararg, kwargs):
|
def _set_var_args(self, p0, vararg, kwargs):
|
||||||
if vararg is None:
|
if vararg is None and kwargs is not None:
|
||||||
self._set_args_def(p0, kwargs, kwargs=True)
|
self._set_args_def(p0, kwargs, kwargs=True)
|
||||||
elif vararg is not None and kwargs is None:
|
elif vararg is not None and kwargs is None:
|
||||||
# *args
|
# *args
|
||||||
|
|
|
@ -1888,7 +1888,11 @@ def _iglobpath(s, ignore_case=False, sort_result=None):
|
||||||
|
|
||||||
def iglobpath(s, ignore_case=False, sort_result=None):
|
def iglobpath(s, ignore_case=False, sort_result=None):
|
||||||
"""Simple wrapper around iglob that also expands home and env vars."""
|
"""Simple wrapper around iglob that also expands home and env vars."""
|
||||||
return _iglobpath(s, ignore_case=ignore_case, sort_result=sort_result)[0]
|
try:
|
||||||
|
return _iglobpath(s, ignore_case=ignore_case, sort_result=sort_result)[0]
|
||||||
|
except IndexError:
|
||||||
|
# something went wrong in the actual iglob() call
|
||||||
|
return iter(())
|
||||||
|
|
||||||
|
|
||||||
def ensure_timestamp(t, datetime_format=None):
|
def ensure_timestamp(t, datetime_format=None):
|
||||||
|
|
Loading…
Add table
Reference in a new issue