fixed conflicts

This commit is contained in:
Anthony Scopatz 2017-02-27 21:14:41 -05:00
commit 13d507e4f8
24 changed files with 286 additions and 77 deletions

1
.gitignore vendored
View file

@ -52,3 +52,4 @@ Actually_test.tst
Actually.tst Actually.tst
Complete_test.tst Complete_test.tst
Complete.tst Complete.tst
tags

View file

@ -54,6 +54,7 @@ For those of you who want the gritty details.
events events
tools tools
platform platform
jsonutils
lazyjson lazyjson
lazyasd lazyasd
openpy openpy

10
docs/api/jsonutils.py Normal file
View file

@ -0,0 +1,10 @@
.. _xonsh_jsonutils:
******************************************
JSON Utilities (``xonsh.jsonutils``)
******************************************
.. automodule:: xonsh.jsonutils
:members:
:undoc-members:

16
news/ao.rst Normal file
View file

@ -0,0 +1,16 @@
**Added:** None
**Changed:**
* The literal tokens ``and`` and ``or`` must be surrounded by
whitespace to delimit subprocess mode. If they do not have
whitespace on both sides in subproc mode, they are condisered
to be part of a command argument.
**Deprecated:** None
**Removed:** None
**Fixed:** None
**Security:** None

View file

@ -0,0 +1,14 @@
**Added:** None
**Changed:** None
**Deprecated:** None
**Removed:** None
**Fixed:**
* ``history replay`` no longer barfs on ``style_name`` when setting up the
environment
**Security:** None

16
news/jsonutils.rst Normal file
View file

@ -0,0 +1,16 @@
**Added:**
* New ``jsonutils`` module available for serializing special
xonsh objects to JSON.
**Changed:** None
**Deprecated:** None
**Removed:** None
**Fixed:**
* Wizard is now able to properly serialize envrionment paths.
**Security:** None

16
news/ntenv.rst Normal file
View file

@ -0,0 +1,16 @@
**Added:** None
**Changed:** None
**Deprecated:** None
**Removed:** None
**Fixed:**
* On Windows, ``os.environ`` is case insensitive. This would potentially
change the case of envrionment variables set into the environment.
Xonsh now uses ``nt.envrion``, the case sensitive counterpart, to avoid
these issues on Windows.
**Security:** None

14
news/ptkcomp.rst Normal file
View file

@ -0,0 +1,14 @@
**Added:** None
**Changed:** None
**Deprecated:** None
**Removed:** None
**Fixed:**
* PTK completions will now correctly deduplicate autosuggest completions
and display completions values based on the cursor position.
**Security:** None

View file

@ -43,6 +43,7 @@ def xonsh_events():
@pytest.yield_fixture @pytest.yield_fixture
def xonsh_builtins(xonsh_events): def xonsh_builtins(xonsh_events):
"""Mock out most of the builtins xonsh attributes.""" """Mock out most of the builtins xonsh attributes."""
old_builtins = set(dir(builtins))
builtins.__xonsh_env__ = DummyEnv() builtins.__xonsh_env__ = DummyEnv()
if ON_WINDOWS: if ON_WINDOWS:
builtins.__xonsh_env__['PATHEXT'] = ['.EXE', '.BAT', '.CMD'] builtins.__xonsh_env__['PATHEXT'] = ['.EXE', '.BAT', '.CMD']
@ -72,40 +73,8 @@ def xonsh_builtins(xonsh_events):
# be firing events on the global instance. # be firing events on the global instance.
builtins.events = xonsh_events builtins.events = xonsh_events
yield builtins yield builtins
if hasattr(builtins, '__xonsh_env__'): for attr in set(dir(builtins)) - old_builtins:
del builtins.__xonsh_env__ delattr(builtins, attr)
if hasattr(builtins, '__xonsh_ctx__'):
del builtins.__xonsh_ctx__
del builtins.__xonsh_shell__
if hasattr(builtins, '__xonsh_help__'):
del builtins.__xonsh_help__
if hasattr(builtins, '__xonsh_glob__'):
del builtins.__xonsh_glob__
if hasattr(builtins, '__xonsh_exit__'):
del builtins.__xonsh_exit__
if hasattr(builtins, '__xonsh_superhelp__'):
del builtins.__xonsh_superhelp__
del builtins.__xonsh_regexpath__
if hasattr(builtins, '__xonsh_expand_path__'):
del builtins.__xonsh_expand_path__
if hasattr(builtins, '__xonsh_stdout_uncaptured__'):
del builtins.__xonsh_stdout_uncaptured__
if hasattr(builtins, '__xonsh_stderr_uncaptured__'):
del builtins.__xonsh_stderr_uncaptured__
del builtins.__xonsh_subproc_captured__
if hasattr(builtins, '__xonsh_subproc_uncaptured__'):
del builtins.__xonsh_subproc_uncaptured__
del builtins.__xonsh_ensure_list_of_strs__
del builtins.__xonsh_commands_cache__
del builtins.__xonsh_all_jobs__
if hasattr(builtins, '__xonsh_history__'):
del builtins.__xonsh_history__
del builtins.__xonsh_enter_macro__
del builtins.evalx
del builtins.execx
del builtins.compilex
del builtins.aliases
del builtins.events
tasks.clear() # must to this to enable resetting all_jobs tasks.clear() # must to this to enable resetting all_jobs

21
tests/test_jsonutils.py Normal file
View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
"""Testing xonsh json hooks"""
import json
import pytest
from xonsh.tools import EnvPath
from xonsh.jsonutils import serialize_xonsh_json
@pytest.mark.parametrize('inp', [
42, "yo", ["hello"], {"x": 65},
EnvPath(["wakka", "jawaka"]),
["y", EnvPath(["wakka", "jawaka"])],
{"z": EnvPath(["wakka", "jawaka"])},
])
def test_serialize_xonsh_json_roundtrip(inp):
s = json.dumps(inp, default=serialize_xonsh_json)
obs = json.loads(s)
assert inp == obs

View file

@ -169,6 +169,82 @@ def test_ampersand():
assert check_token('&', ['AMPERSAND', '&', 0]) assert check_token('&', ['AMPERSAND', '&', 0])
def test_not_really_and_pre():
inp = "![foo-and]"
exp = [
('BANG_LBRACKET', '![', 0),
('NAME', 'foo', 2),
('MINUS', '-', 5),
('NAME', 'and', 6),
('RBRACKET', ']', 9),
]
assert check_tokens(inp, exp)
def test_not_really_and_post():
inp = "![and-bar]"
exp = [
('BANG_LBRACKET', '![', 0),
('NAME', 'and', 2),
('MINUS', '-', 5),
('NAME', 'bar', 6),
('RBRACKET', ']', 9),
]
assert check_tokens(inp, exp)
def test_not_really_and_pre_post():
inp = "![foo-and-bar]"
exp = [
('BANG_LBRACKET', '![', 0),
('NAME', 'foo', 2),
('MINUS', '-', 5),
('NAME', 'and', 6),
('MINUS', '-', 9),
('NAME', 'bar', 10),
('RBRACKET', ']', 13),
]
assert check_tokens(inp, exp)
def test_not_really_or_pre():
inp = "![foo-or]"
exp = [
('BANG_LBRACKET', '![', 0),
('NAME', 'foo', 2),
('MINUS', '-', 5),
('NAME', 'or', 6),
('RBRACKET', ']', 8),
]
assert check_tokens(inp, exp)
def test_not_really_or_post():
inp = "![or-bar]"
exp = [
('BANG_LBRACKET', '![', 0),
('NAME', 'or', 2),
('MINUS', '-', 4),
('NAME', 'bar', 5),
('RBRACKET', ']', 8),
]
assert check_tokens(inp, exp)
def test_not_really_or_pre_post():
inp = "![foo-or-bar]"
exp = [
('BANG_LBRACKET', '![', 0),
('NAME', 'foo', 2),
('MINUS', '-', 5),
('NAME', 'or', 6),
('MINUS', '-', 8),
('NAME', 'bar', 9),
('RBRACKET', ']', 12),
]
assert check_tokens(inp, exp)
def test_atdollar(): def test_atdollar():
assert check_token('@$', ['ATDOLLAR', '@$', 0]) assert check_token('@$', ['ATDOLLAR', '@$', 0])

View file

@ -50,6 +50,8 @@ else:
_sys.modules['xonsh.foreign_shells'] = __amalgam__ _sys.modules['xonsh.foreign_shells'] = __amalgam__
jobs = __amalgam__ jobs = __amalgam__
_sys.modules['xonsh.jobs'] = __amalgam__ _sys.modules['xonsh.jobs'] = __amalgam__
jsonutils = __amalgam__
_sys.modules['xonsh.jsonutils'] = __amalgam__
lexer = __amalgam__ lexer = __amalgam__
_sys.modules['xonsh.lexer'] = __amalgam__ _sys.modules['xonsh.lexer'] = __amalgam__
openpy = __amalgam__ openpy = __amalgam__

View file

@ -22,7 +22,7 @@ from xonsh.foreign_shells import load_foreign_envs, load_foreign_aliases
from xonsh.xontribs import update_context, prompt_xontrib_install from xonsh.xontribs import update_context, prompt_xontrib_install
from xonsh.platform import ( from xonsh.platform import (
BASH_COMPLETIONS_DEFAULT, DEFAULT_ENCODING, PATH_DEFAULT, BASH_COMPLETIONS_DEFAULT, DEFAULT_ENCODING, PATH_DEFAULT,
ON_WINDOWS, ON_LINUX ON_WINDOWS, ON_LINUX, os_environ
) )
from xonsh.tools import ( from xonsh.tools import (
@ -240,7 +240,7 @@ def default_xonshrc(env):
"""Creates a new instance of the default xonshrc tuple.""" """Creates a new instance of the default xonshrc tuple."""
if ON_WINDOWS: if ON_WINDOWS:
dxrc = (xonshconfig(env), dxrc = (xonshconfig(env),
os.path.join(os.environ['ALLUSERSPROFILE'], os.path.join(os_environ['ALLUSERSPROFILE'],
'xonsh', 'xonshrc'), 'xonsh', 'xonshrc'),
os.path.expanduser('~/.xonshrc')) os.path.expanduser('~/.xonshrc'))
else: else:
@ -599,7 +599,7 @@ def DEFAULT_DOCS():
'the possibilities. This currently only affects the prompt-toolkit shell.' 'the possibilities. This currently only affects the prompt-toolkit shell.'
), ),
'UPDATE_OS_ENVIRON': VarDocs( 'UPDATE_OS_ENVIRON': VarDocs(
"If True ``os.environ`` will always be updated " "If True ``os_environ`` will always be updated "
"when the xonsh environment changes. The environment can be reset to " "when the xonsh environment changes. The environment can be reset to "
"the default value by calling ``__xonsh_env__.undo_replace_env()``"), "the default value by calling ``__xonsh_env__.undo_replace_env()``"),
'UPDATE_PROMPT_ON_KEYPRESS': VarDocs( 'UPDATE_PROMPT_ON_KEYPRESS': VarDocs(
@ -775,7 +775,7 @@ class Env(cabc.MutableMapping):
_arg_regex = None _arg_regex = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"""If no initial environment is given, os.environ is used.""" """If no initial environment is given, os_environ is used."""
self._d = {} self._d = {}
# sentinel value for non existing envvars # sentinel value for non existing envvars
self._no_value = object() self._no_value = object()
@ -784,7 +784,7 @@ class Env(cabc.MutableMapping):
self._defaults = DEFAULT_VALUES self._defaults = DEFAULT_VALUES
self._docs = DEFAULT_DOCS self._docs = DEFAULT_DOCS
if len(args) == 0 and len(kwargs) == 0: if len(args) == 0 and len(kwargs) == 0:
args = (os.environ,) args = (os_environ,)
for key, val in dict(*args, **kwargs).items(): for key, val in dict(*args, **kwargs).items():
self[key] = val self[key] = val
if 'PATH' not in self._d: if 'PATH' not in self._d:
@ -819,21 +819,21 @@ class Env(cabc.MutableMapping):
return ctx return ctx
def replace_env(self): def replace_env(self):
"""Replaces the contents of os.environ with a detyped version """Replaces the contents of os_environ with a detyped version
of the xonsh environement. of the xonsh environement.
""" """
if self._orig_env is None: if self._orig_env is None:
self._orig_env = dict(os.environ) self._orig_env = dict(os_environ)
os.environ.clear() os_environ.clear()
os.environ.update(self.detype()) os_environ.update(self.detype())
def undo_replace_env(self): def undo_replace_env(self):
"""Replaces the contents of os.environ with a detyped version """Replaces the contents of os_environ with a detyped version
of the xonsh environement. of the xonsh environement.
""" """
if self._orig_env is not None: if self._orig_env is not None:
os.environ.clear() os_environ.clear()
os.environ.update(self._orig_env) os_environ.update(self._orig_env)
self._orig_env = None self._orig_env = None
def get_ensurer(self, key, def get_ensurer(self, key,
@ -952,7 +952,7 @@ class Env(cabc.MutableMapping):
if self._orig_env is None: if self._orig_env is None:
self.replace_env() self.replace_env()
else: else:
os.environ[key] = ensurer.detype(val) os_environ[key] = ensurer.detype(val)
if old_value is self._no_value: if old_value is self._no_value:
events.on_envvar_new.fire(name=key, value=val) events.on_envvar_new.fire(name=key, value=val)
elif old_value != val: elif old_value != val:
@ -964,8 +964,8 @@ class Env(cabc.MutableMapping):
val = self._d.pop(key) val = self._d.pop(key)
if self.detypeable(val): if self.detypeable(val):
self._detyped = None self._detyped = None
if self.get('UPDATE_OS_ENVIRON') and key in os.environ: if self.get('UPDATE_OS_ENVIRON') and key in os_environ:
del os.environ[key] del os_environ[key]
def get(self, key, default=None): def get(self, key, default=None):
"""The environment will look up default values from its own defaults if a """The environment will look up default values from its own defaults if a
@ -1047,10 +1047,10 @@ def load_static_config(ctx, config=None):
config = env['XONSHCONFIG'] = xonshconfig(env) config = env['XONSHCONFIG'] = xonshconfig(env)
if os.path.isfile(config): if os.path.isfile(config):
# Note that an Env instance at __xonsh_env__ has not been started yet, # Note that an Env instance at __xonsh_env__ has not been started yet,
# per se, so we have to use os.environ # per se, so we have to use os_environ
encoding = os.environ.get('XONSH_ENCODING', encoding = os_environ.get('XONSH_ENCODING',
DEFAULT_VALUES.get('XONSH_ENCODING', 'utf8')) DEFAULT_VALUES.get('XONSH_ENCODING', 'utf8'))
errors = os.environ.get('XONSH_ENCODING_ERRORS', errors = os_environ.get('XONSH_ENCODING_ERRORS',
DEFAULT_VALUES.get('XONSH_ENCODING_ERRORS', DEFAULT_VALUES.get('XONSH_ENCODING_ERRORS',
'surrogateescape')) 'surrogateescape'))
with open(config, 'r', encoding=encoding, errors=errors) as f: with open(config, 'r', encoding=encoding, errors=errors) as f:
@ -1109,8 +1109,8 @@ def windows_foreign_env_fixes(ctx):
# /c/Windows/System32 syntax instead of C:\\Windows\\System32 # /c/Windows/System32 syntax instead of C:\\Windows\\System32
# which messes up these environment variables for xonsh. # which messes up these environment variables for xonsh.
for ev in ['PATH', 'TEMP', 'TMP']: for ev in ['PATH', 'TEMP', 'TMP']:
if ev in os.environ: if ev in os_environ:
ctx[ev] = os.environ[ev] ctx[ev] = os_environ[ev]
elif ev in ctx: elif ev in ctx:
del ctx[ev] del ctx[ev]
ctx['PWD'] = _get_cwd() or '' ctx['PWD'] = _get_cwd() or ''
@ -1181,7 +1181,7 @@ def default_env(env=None):
"""Constructs a default xonsh environment.""" """Constructs a default xonsh environment."""
# in order of increasing precedence # in order of increasing precedence
ctx = dict(BASE_ENV) ctx = dict(BASE_ENV)
ctx.update(os.environ) ctx.update(os_environ)
ctx['PWD'] = _get_cwd() or '' ctx['PWD'] = _get_cwd() or ''
# other shells' PROMPT definitions generally don't work in XONSH: # other shells' PROMPT definitions generally don't work in XONSH:
try: try:

View file

@ -14,7 +14,7 @@ import collections.abc as cabc
from xonsh.lazyasd import lazyobject from xonsh.lazyasd import lazyobject
from xonsh.tools import to_bool, ensure_string from xonsh.tools import to_bool, ensure_string
from xonsh.platform import ON_WINDOWS, ON_CYGWIN from xonsh.platform import ON_WINDOWS, ON_CYGWIN, os_environ
COMMAND = """{seterrprevcmd} COMMAND = """{seterrprevcmd}
{prevcmd} {prevcmd}
@ -539,7 +539,7 @@ def _get_shells(shells=None, config=None, issue_warning=True):
elif shells is not None: elif shells is not None:
pass pass
else: else:
env = getattr(builtins, '__xonsh_env__', os.environ) env = getattr(builtins, '__xonsh_env__', os_environ)
if env.get('LOADED_CONFIG', False): if env.get('LOADED_CONFIG', False):
conf = builtins.__xonsh_config__ conf = builtins.__xonsh_config__
else: else:

19
xonsh/jsonutils.py Normal file
View file

@ -0,0 +1,19 @@
"""Custom tools for managing JSON serialization / deserialization of xonsh
objects.
"""
import functools
from xonsh.tools import EnvPath
@functools.singledispatch
def serialize_xonsh_json(val):
"""JSON serializer for xonsh custom data structures. This is only
called when another normal JSON types are not found.
"""
return str(val)
@serialize_xonsh_json.register(EnvPath)
def _serialize_xonsh_json_env_path(val):
return val.paths

View file

@ -69,15 +69,18 @@ def token_map():
def handle_name(state, token): def handle_name(state, token):
"""Function for handling name tokens""" """Function for handling name tokens"""
typ = 'NAME' typ = 'NAME'
state['last'] = token
if state['pymode'][-1][0]: if state['pymode'][-1][0]:
if token.string in kwmod.kwlist: if token.string in kwmod.kwlist:
typ = token.string.upper() typ = token.string.upper()
state['last'] = token
yield _new_token(typ, token.string, token.start) yield _new_token(typ, token.string, token.start)
else: else:
if token.string == 'and': prev = state['last']
state['last'] = token
has_whitespace = prev.end != token.start
if token.string == 'and' and has_whitespace:
yield _new_token('AND', token.string, token.start) yield _new_token('AND', token.string, token.start)
elif token.string == 'or': elif token.string == 'or' and has_whitespace:
yield _new_token('OR', token.string, token.start) yield _new_token('OR', token.string, token.start)
else: else:
yield _new_token('NAME', token.string, token.start) yield _new_token('NAME', token.string, token.start)

View file

@ -359,6 +359,20 @@ def windows_bash_command():
# #
@lazyobject
def os_environ():
"""This dispatches to the correct, case-senstive version of os.envrion.
This is mainly a problem for Windows. See #2024 for more details.
This can probably go away once support for Python v3.5 or v3.6 is
dropped.
"""
if ON_WINDOWS:
import nt
return nt.environ
else:
return os.environ
@functools.lru_cache(1) @functools.lru_cache(1)
def bash_command(): def bash_command():
"""Determines the command for Bash on the current plaform.""" """Determines the command for Bash on the current plaform."""

View file

@ -92,7 +92,7 @@ class PromptFormatter:
@xl.lazyobject @xl.lazyobject
def PROMPT_FIELDS(): def PROMPT_FIELDS():
return dict( return dict(
user=os.environ.get('USERNAME' if xp.ON_WINDOWS else 'USER', '<user>'), user=xp.os_environ.get('USERNAME' if xp.ON_WINDOWS else 'USER', '<user>'),
prompt_end='#' if xt.is_superuser() else '$', prompt_end='#' if xt.is_superuser() else '$',
hostname=socket.gethostname().split('.', 1)[0], hostname=socket.gethostname().split('.', 1)[0],
cwd=_dynamically_collapsed_pwd, cwd=_dynamically_collapsed_pwd,

View file

@ -48,6 +48,7 @@ class PromptToolkitCompleter(Completer):
endidx + expand_offset, endidx + expand_offset,
self.ctx) self.ctx)
# completions from auto suggest # completions from auto suggest
sug_comp = None
if env.get('AUTO_SUGGEST'): if env.get('AUTO_SUGGEST'):
sug_comp = self.suggestion_completion(document, line) sug_comp = self.suggestion_completion(document, line)
if sug_comp is None: if sug_comp is None:
@ -55,7 +56,9 @@ class PromptToolkitCompleter(Completer):
elif len(completions) == 0: elif len(completions) == 0:
completions = (sug_comp,) completions = (sug_comp,)
else: else:
completions = (sug_comp,) + completions completions = set(completions)
completions.discard(sug_comp)
completions = (sug_comp,) + tuple(sorted(completions))
# reserve space, if needed. # reserve space, if needed.
if len(completions) <= 1: if len(completions) <= 1:
pass pass
@ -69,9 +72,13 @@ class PromptToolkitCompleter(Completer):
break break
c_prefix = c_prefix[:-1] c_prefix = c_prefix[:-1]
# yield completions # yield completions
if sug_comp is None:
pre = min(document.cursor_position_col - begidx, len(c_prefix))
else:
pre = len(c_prefix)
for comp in completions: for comp in completions:
# do not display quote # do not display quote
disp = comp.strip('\'"')[len(c_prefix):] disp = comp[pre:].strip('\'"')
yield Completion(comp, -l, display=disp) yield Completion(comp, -l, display=disp)
def suggestion_completion(self, document, line): def suggestion_completion(self, document, line):

View file

@ -28,6 +28,7 @@ from xonsh.color_tools import (RE_BACKGROUND, BASE_XONSH_COLORS, make_pallete,
find_closest_color) find_closest_color)
from xonsh.style_tools import norm_name from xonsh.style_tools import norm_name
from xonsh.lazyimps import terminal256 from xonsh.lazyimps import terminal256
from xonsh.platform import os_environ
load_module_in_background('pkg_resources', debug='XONSH_DEBUG', load_module_in_background('pkg_resources', debug='XONSH_DEBUG',
replacements={'pygments.plugin': 'pkg_resources'}) replacements={'pygments.plugin': 'pkg_resources'})
@ -86,7 +87,7 @@ class XonshLexer(PythonLexer):
if not hasattr(builtins, '__xonsh_env__'): if not hasattr(builtins, '__xonsh_env__'):
setattr(builtins, '__xonsh_env__', {}) setattr(builtins, '__xonsh_env__', {})
if ON_WINDOWS: if ON_WINDOWS:
pathext = os.environ.get('PATHEXT', ['.EXE', '.BAT', '.CMD']) pathext = os_environ.get('PATHEXT', ['.EXE', '.BAT', '.CMD'])
builtins.__xonsh_env__['PATHEXT'] = pathext.split(os.pathsep) builtins.__xonsh_env__['PATHEXT'] = pathext.split(os.pathsep)
if not hasattr(builtins, '__xonsh_commands_cache__'): if not hasattr(builtins, '__xonsh_commands_cache__'):
setattr(builtins, '__xonsh_commands_cache__', CommandsCache()) setattr(builtins, '__xonsh_commands_cache__', CommandsCache())
@ -735,7 +736,7 @@ def _default_style():
Color.WHITE: '#ansilightgray', Color.WHITE: '#ansilightgray',
Color.YELLOW: '#ansibrown', Color.YELLOW: '#ansibrown',
} }
elif ON_WINDOWS and 'CONEMUANSI' not in os.environ: elif ON_WINDOWS and 'CONEMUANSI' not in os_environ:
# These colors must match the color specification # These colors must match the color specification
# in prompt_toolkit, so the colors are converted # in prompt_toolkit, so the colors are converted
# correctly when using cmd.exe # correctly when using cmd.exe

View file

@ -28,7 +28,7 @@ from xonsh.ansi_colors import (ansi_partial_color_format, ansi_color_style_names
from xonsh.prompt.base import multiline_prompt from xonsh.prompt.base import multiline_prompt
from xonsh.tools import (print_exception, check_for_partial_string, to_bool, from xonsh.tools import (print_exception, check_for_partial_string, to_bool,
columnize, carriage_return) columnize, carriage_return)
from xonsh.platform import ON_WINDOWS, ON_CYGWIN, ON_DARWIN, ON_POSIX from xonsh.platform import ON_WINDOWS, ON_CYGWIN, ON_DARWIN, ON_POSIX, os_environ
from xonsh.lazyimps import pygments, pyghooks, winutils from xonsh.lazyimps import pygments, pyghooks, winutils
from xonsh.events import events from xonsh.events import events
@ -117,7 +117,7 @@ def setup_readline():
else: else:
readline.parse_and_bind("tab: complete") readline.parse_and_bind("tab: complete")
# try to load custom user settings # try to load custom user settings
inputrc_name = os.environ.get('INPUTRC') inputrc_name = os_environ.get('INPUTRC')
if inputrc_name is None: if inputrc_name is None:
if uses_libedit: if uses_libedit:
inputrc_name = '.editrc' inputrc_name = '.editrc'

View file

@ -34,13 +34,14 @@ import sys
import threading import threading
import traceback import traceback
import warnings import warnings
import operator
# adding imports from further xonsh modules is discouraged to avoid circular # adding imports from further xonsh modules is discouraged to avoid circular
# dependencies # dependencies
from xonsh.lazyasd import LazyObject, LazyDict, lazyobject from xonsh.lazyasd import LazyObject, LazyDict, lazyobject
from xonsh.platform import (has_prompt_toolkit, scandir, DEFAULT_ENCODING, from xonsh.platform import (has_prompt_toolkit, scandir, DEFAULT_ENCODING,
ON_LINUX, ON_WINDOWS, PYTHON_VERSION_INFO, ON_LINUX, ON_WINDOWS, PYTHON_VERSION_INFO,
expanduser) expanduser, os_environ)
@functools.lru_cache(1) @functools.lru_cache(1)
@ -85,7 +86,7 @@ class XonshCalledProcessError(XonshError, subprocess.CalledProcessError):
def expand_path(s, expand_user=True): def expand_path(s, expand_user=True):
"""Takes a string path and expands ~ to home if expand_user is set """Takes a string path and expands ~ to home if expand_user is set
and environment vars if EXPAND_ENV_VARS is set.""" and environment vars if EXPAND_ENV_VARS is set."""
env = getattr(builtins, '__xonsh_env__', os.environ) env = getattr(builtins, '__xonsh_env__', os_environ)
if env.get('EXPAND_ENV_VARS', False): if env.get('EXPAND_ENV_VARS', False):
s = expandvars(s) s = expandvars(s)
if expand_user: if expand_user:
@ -106,7 +107,7 @@ def _expandpath(path):
"""Performs environment variable / user expansion on a given path """Performs environment variable / user expansion on a given path
if EXPAND_ENV_VARS is set. if EXPAND_ENV_VARS is set.
""" """
env = getattr(builtins, '__xonsh_env__', os.environ) env = getattr(builtins, '__xonsh_env__', os_environ)
expand_user = env.get('EXPAND_ENV_VARS', False) expand_user = env.get('EXPAND_ENV_VARS', False)
return expand_path(path, expand_user=expand_user) return expand_path(path, expand_user=expand_user)
@ -115,7 +116,7 @@ def decode_bytes(b):
"""Tries to decode the bytes using XONSH_ENCODING if available, """Tries to decode the bytes using XONSH_ENCODING if available,
otherwise using sys.getdefaultencoding(). otherwise using sys.getdefaultencoding().
""" """
env = getattr(builtins, '__xonsh_env__', os.environ) env = getattr(builtins, '__xonsh_env__', os_environ)
enc = env.get('XONSH_ENCODING') or DEFAULT_ENCODING enc = env.get('XONSH_ENCODING') or DEFAULT_ENCODING
err = env.get('XONSH_ENCODING_ERRORS') or 'strict' err = env.get('XONSH_ENCODING_ERRORS') or 'strict'
return b.decode(encoding=enc, errors=err) return b.decode(encoding=enc, errors=err)
@ -198,6 +199,11 @@ class EnvPath(collections.MutableSequence):
def __repr__(self): def __repr__(self):
return repr(self._l) return repr(self._l)
def __eq__(self, other):
if len(self) != len(other):
return False
return all(map(operator.eq, self, other))
class DefaultNotGivenType(object): class DefaultNotGivenType(object):
"""Singleton for representing when no default value is given.""" """Singleton for representing when no default value is given."""
@ -745,7 +751,7 @@ def print_exception(msg=None):
env = getattr(builtins, '__xonsh_env__', None) env = getattr(builtins, '__xonsh_env__', None)
# flags indicating whether the traceback options have been manually set # flags indicating whether the traceback options have been manually set
if env is None: if env is None:
env = os.environ env = os_environ
manually_set_trace = 'XONSH_SHOW_TRACEBACK' in env manually_set_trace = 'XONSH_SHOW_TRACEBACK' in env
manually_set_logfile = 'XONSH_TRACEBACK_LOGFILE' in env manually_set_logfile = 'XONSH_TRACEBACK_LOGFILE' in env
else: else:
@ -1570,7 +1576,8 @@ def intensify_colors_on_win_setter(enable):
""" """
enable = to_bool(enable) enable = to_bool(enable)
if hasattr(builtins, '__xonsh_shell__'): if hasattr(builtins, '__xonsh_shell__'):
delattr(builtins.__xonsh_shell__.shell.styler, 'style_name') if hasattr(builtins.__xonsh_shell__.shell.styler, 'style_name'):
delattr(builtins.__xonsh_shell__.shell.styler, 'style_name')
return enable return enable

View file

@ -8,6 +8,7 @@ import builtins
import textwrap import textwrap
from xonsh.tools import to_bool, to_bool_or_break, backup_file, print_color from xonsh.tools import to_bool, to_bool_or_break, backup_file, print_color
from xonsh.jsonutils import serialize_xonsh_json
# #
@ -610,7 +611,8 @@ class PromptVisitor(StateVisitor):
return rtns return rtns
def visit_save(self, node): def visit_save(self, node):
jstate = json.dumps(self.state, indent=1, sort_keys=True) jstate = json.dumps(self.state, indent=1, sort_keys=True,
default=serialize_xonsh_json)
if node.check: if node.check:
msg = 'The current state is:\n\n{0}\n' msg = 'The current state is:\n\n{0}\n'
print(msg.format(textwrap.indent(jstate, ' '))) print(msg.format(textwrap.indent(jstate, ' ')))

View file

@ -124,15 +124,15 @@ def which(args, stdin=None, stdout=None, stderr=None, spec=None):
# which.whichgen gives the nicest 'verbose' output if PATH is taken # which.whichgen gives the nicest 'verbose' output if PATH is taken
# from os.environ so we temporarily override it with # from os.environ so we temporarily override it with
# __xosnh_env__['PATH'] # __xosnh_env__['PATH']
original_os_path = os.environ['PATH'] original_os_path = xp.os_environ['PATH']
os.environ['PATH'] = builtins.__xonsh_env__.detype()['PATH'] xp.os_environ['PATH'] = builtins.__xonsh_env__.detype()['PATH']
matches = _which.whichgen(arg, exts=exts, verbose=verbose) matches = _which.whichgen(arg, exts=exts, verbose=verbose)
for abs_name, from_where in matches: for abs_name, from_where in matches:
print_path(abs_name, from_where, stdout, verbose, captured) print_path(abs_name, from_where, stdout, verbose, captured)
nmatches += 1 nmatches += 1
if not pargs.all: if not pargs.all:
break break
os.environ['PATH'] = original_os_path xp.os_environ['PATH'] = original_os_path
if not nmatches: if not nmatches:
failures.append(arg) failures.append(arg)
if len(failures) == 0: if len(failures) == 0: