Merge branch 'master' of https://github.com/scopatz/xonsh into signals

This commit is contained in:
Ryan Gonzalez 2016-05-20 21:02:24 -05:00
commit 108300d155
43 changed files with 492 additions and 432 deletions

View file

@ -1,4 +1,4 @@
version: 0.2.7.{build}
version: 0.3.0.{build}
os: Windows Server 2012 R2
install:
- C:\Python34\Scripts\pip install ply pyreadline nose pygments prompt_toolkit

View file

@ -6,6 +6,23 @@ Current Developments
====================
**Added:**
* When a subprocess exits with a signal (e.g. SIGSEGV), a message is printed,
similar to Bash.
**Changed:** None
**Deprecated:** None
**Removed:** None
**Fixed:** None
**Security:** None
v0.3.0
====================
**Added:**
* ``and``, ``or``, ``&&``, ``||`` have been added as subprocess logical operators,
by popular demand!
* Subprocesses may be negated with ``not`` and grouped together with parentheses.
@ -37,8 +54,6 @@ Current Developments
``--cache-everything`` when starting xonsh.
* Added a workaround to allow ctrl-c to interrupt reverse incremental search in
the readline shell
* When a subprocess exits with a signal (e.g. SIGSEGV), a message is printed,
similar to Bash.
**Changed:**
@ -65,9 +80,9 @@ Current Developments
way.
**Deprecated:** None
**Removed:** None
**Fixed:**
@ -91,7 +106,7 @@ Current Developments
* Fixed xonsh.exe launcher on Windows, when Python install directory has a space in it
* Fixed `$CDPATH` to support `~` and environments variables in its items
**Security:** None
v0.2.7

View file

@ -1,7 +1,7 @@
Additional Setup
================
If you want to use xonsh as your default shell, you will first have to add xonsh to `/etc/shells`.
If you want to use xonsh as your default shell, you will first have
to add xonsh to `/etc/shells`.
First ensure that xonsh is on your ``$PATH``
@ -21,4 +21,4 @@ To change shells, run
$ chsh -s $(which xonsh)
You will have to log out and log back in before the changes take effect.
You will have to log out and log back in before the changes take effect.

View file

@ -175,11 +175,11 @@ The following aliases on Windows are expanded to ``['cmd', '/c', alias]``:
``activate``/``deactivate`` on Windows with Anaconda
=====================
=========================================================
On Windows with an Anaconda Python distribution, ``activate`` and
``deactivate`` are aliased to ``['source-bat activate']`` and ``['source-bat deactivate']``.
This makes it possible to use the same commands to activate/deactivate conda environments as
in cmd.exe.
This makes it possible to use the same commands to activate/deactivate conda environments as
in cmd.exe.
``sudo`` on Windows

View file

@ -49,6 +49,7 @@ For those of you who want the gritty details.
:maxdepth: 1
tools
platform
lazyjson
teepty
openpy

11
docs/api/platform.rst Normal file
View file

@ -0,0 +1,11 @@
.. _xonsh_platform:
Platform-specific constants and implementations (``xonsh.platform``)
====================================================================
.. automodule:: xonsh.platform
:members:
:undoc-members:
:inherited-members:

View file

@ -25,7 +25,7 @@ on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.pngmath',
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.imgmath',
'sphinx.ext.inheritance_diagram', 'sphinx.ext.viewcode',
#'sphinx.ext.autosummary',
'numpydoc', 'cmdhelp',
@ -340,4 +340,5 @@ def make_xontribs():
make_envvars()
make_xontribs()
builtins.__xonsh_history__= None
builtins.__xonsh_history__ = None
builtins.__xonsh_env__ = {}

View file

@ -9,6 +9,7 @@ Xonsh currently has the following external dependencies,
#. prompt-toolkit (optional)
#. Jupyter (optional)
#. setproctitle (optional)
#. distro (optional)
*Documentation:*

View file

@ -75,12 +75,14 @@ Contents
**Installation:**
.. toctree::
:titlesonly:
:maxdepth: 1
:titlesonly:
:maxdepth: 1
linux
osx
windows
dependencies
linux
osx
windows
add_to_shell
**Guides:**

View file

@ -1073,7 +1073,7 @@ functions of no arguments (which will be called each time the prompt is
generated, and the results of those calls will be inserted into the prompt).
For example:
.. code-block:: xonshcon
.. code-block:: console
snail@home ~ $ $FORMATTER_DICT['test'] = "hey"
snail@home ~ $ $PROMPT = "{test} {cwd} $ "
@ -1091,7 +1091,7 @@ interpreted as an empty string.
Environment variables and functions are also available with the ``$``
prefix. For example:
.. code-block:: xonshcon
.. code-block:: console
snail@home ~ $ $PROMPT = "{$LANG} >"
en_US.utf8 >
@ -1124,7 +1124,7 @@ script, stored in ``test.xsh``:
print('adding files')
# This is a comment
for i, x in enumerate("xonsh"):
echo @(x) > @("file%d.txt" % i)
echo @(x) > @("file{0}.txt".format(i))
print($(ls).replace('\n', ' '))
@ -1178,7 +1178,7 @@ operates on a given argument, rather than on the string ``'xonsh'`` (notice how
print('adding files')
# This is a comment
for i, x in enumerate($ARG1):
echo @(x) > @("file%d.txt" % i)
echo @(x) > @("file{0}.txt".format(i))
print($(ls).replace('\n', ' '))
print()

View file

@ -50,7 +50,7 @@ dictionaries have the following structure:
``default=false``
:envcmd: *str, optional* - The command to generate environment output with.
``default="env"``
:aliascmd: *str, optional* - The command to generate alais output with.
:aliascmd: *str, optional* - The command to generate alias output with.
``default="alias"``
:extra_args: *list of str, optional* - Addtional command line options to pass
into the shell. ``default=[]``

View file

@ -8,7 +8,7 @@ the ``xontrib`` command:
.. code-block:: xonshcon
$ xontrib mpl xomg ...
>>> xontrib mpl xomg ...
.. See the xontrib tutorial for more information.

View file

@ -1 +0,0 @@
numpydoc==0.5

View file

@ -136,7 +136,7 @@ if HAVE_SETUPTOOLS:
def main():
"""The main entry point."""
if sys.version_info[0] < 3:
if sys.version_info[:2] < (3, 4):
sys.exit('xonsh currently requires Python 3.4+')
try:
if '--name' not in sys.argv:
@ -168,8 +168,7 @@ def main():
if HAVE_SETUPTOOLS:
skw['entry_points'] = {
'pygments.lexers': ['xonsh = xonsh.pyghooks:XonshLexer',
'xonshcon = xonsh.pyghooks:XonshConsoleLexer',
],
'xonshcon = xonsh.pyghooks:XonshConsoleLexer'],
'console_scripts': ['xonsh = xonsh.main:main'],
}
skw['cmdclass']['develop'] = xdevelop

View file

@ -1 +1 @@
__version__ = '0.2.7'
__version__ = '0.3.0'

View file

@ -1,28 +1,25 @@
# -*- coding: utf-8 -*-
"""Aliases for the xonsh shell."""
from argparse import ArgumentParser, Action
import builtins
from collections.abc import MutableMapping, Iterable, Sequence
import os
import shlex
import builtins
import sys
import subprocess
from functools import lru_cache
from argparse import ArgumentParser, Action
from collections.abc import MutableMapping, Iterable, Sequence
from xonsh.dirstack import cd, pushd, popd, dirs, _get_cwd
from xonsh.jobs import jobs, fg, bg, kill_all_jobs
from xonsh.proc import foreground
from xonsh.timings import timeit_alias
from xonsh.tools import (ON_MAC, ON_WINDOWS, ON_ANACONDA,
XonshError, to_bool, string_types)
from xonsh.history import main as history_alias
from xonsh.replay import main as replay_main
from xonsh.xontribs import main as xontribs_main
from xonsh.environ import locate_binary
from xonsh.foreign_shells import foreign_shell_data
from xonsh.jobs import jobs, fg, bg, kill_all_jobs
from xonsh.history import main as history_alias
from xonsh.platform import ON_ANACONDA, ON_DARWIN, ON_WINDOWS
from xonsh.proc import foreground
from xonsh.replay import main as replay_main
from xonsh.timings import timeit_alias
from xonsh.tools import (XonshError, argvquote, escape_windows_cmd_string,
to_bool)
from xonsh.vox import Vox
from xonsh.tools import argvquote, escape_windows_cmd_string
from xonsh.xontribs import main as xontribs_main
from xonsh.xoreutils import _which
@ -106,7 +103,7 @@ class Aliases(MutableMapping):
return self._raw[key]
def __setitem__(self, key, val):
if isinstance(val, string_types):
if isinstance(val, str):
self._raw[key] = shlex.split(val)
else:
self._raw[key] = val
@ -330,7 +327,6 @@ def bang_bang(args, stdin=None):
class AWitchAWitch(Action):
SUPPRESS = '==SUPPRESS=='
def __init__(self, option_strings, version=None, dest=SUPPRESS,
default=SUPPRESS, **kwargs):
super().__init__(option_strings=option_strings, dest=dest,
@ -384,10 +380,10 @@ def which(args, stdin=None, stdout=None, stderr=None):
parser.print_usage(file=stderr)
return -1
pargs = parser.parse_args(args)
if pargs.all:
pargs.verbose = True
if ON_WINDOWS:
if pargs.exts:
exts = pargs.exts
@ -411,9 +407,9 @@ def which(args, stdin=None, stdout=None, stderr=None):
nmatches += 1
if not pargs.all:
continue
macthes = _which.whichgen(arg, exts=exts, verbose=pargs.verbose,
matches = _which.whichgen(arg, exts=exts, verbose=pargs.verbose,
path=builtins.__xonsh_env__['PATH'])
for abs_name, from_where in macthes:
for abs_name, from_where in matches:
if ON_WINDOWS:
# Use list dir to get correct case for the filename
# i.e. windows is case insesitive but case preserving
@ -548,10 +544,9 @@ def make_default_aliases():
print(msg.format(cmd))
default_aliases['sudo'] = sudo
elif ON_MAC:
elif ON_DARWIN:
default_aliases['ls'] = ['ls', '-G']
else:
default_aliases['grep'] = ['grep', '--color=auto']
default_aliases['ls'] = ['ls', '--color=auto', '-v']
return default_aliases

View file

@ -18,9 +18,10 @@ from ast import Ellipsis # pylint: disable=redefined-builtin
import textwrap
from itertools import repeat
from xonsh.tools import subproc_toks, VER_3_5, VER_MAJOR_MINOR
from xonsh.tools import subproc_toks
from xonsh.platform import PYTHON_VERSION_INFO
if VER_3_5 <= VER_MAJOR_MINOR:
if PYTHON_VERSION_INFO >= (3, 5, 0):
# pylint: disable=unused-import
# pylint: disable=no-name-in-module
from ast import MatMult, AsyncFunctionDef, AsyncWith, AsyncFor, Await

View file

@ -6,14 +6,14 @@ import sys
import time
import builtins
from xonsh.tools import XonshError, escape_windows_cmd_string, ON_WINDOWS, \
print_exception, HAVE_PYGMENTS
from xonsh.tools import XonshError, escape_windows_cmd_string, print_exception
from xonsh.platform import HAS_PYGMENTS, ON_WINDOWS
from xonsh.codecache import (should_use_cache, code_cache_name,
code_cache_check, get_cache_filename,
update_cache, run_compiled_code)
from xonsh.completer import Completer
from xonsh.environ import multiline_prompt, format_prompt, partial_format_prompt
if HAVE_PYGMENTS:
if HAS_PYGMENTS:
from xonsh.pyghooks import XonshStyle
@ -119,7 +119,7 @@ class BaseShell(object):
self.buffer = []
self.need_more_lines = False
self.mlprompt = None
if HAVE_PYGMENTS:
if HAS_PYGMENTS:
env = builtins.__xonsh_env__
self.styler = XonshStyle(env.get('XONSH_COLOR_STYLE'))
else:

View file

@ -4,34 +4,35 @@
Note that this module is named 'built_ins' so as not to be confused with the
special Python builtins module.
"""
import atexit
import builtins
from collections import Sequence
from contextlib import contextmanager
import inspect
from glob import iglob
import os
import re
import sys
import time
import shlex
import atexit
import signal
import inspect
import builtins
import tempfile
from glob import glob, iglob
from subprocess import Popen, PIPE, STDOUT, CalledProcessError
from contextlib import contextmanager
from collections import Sequence, Iterable
import sys
import tempfile
import time
from xonsh.tools import (
suggest_commands, XonshError, ON_POSIX, ON_WINDOWS, string_types,
expandvars, CommandsCache
)
from xonsh.inspectors import Inspector
from xonsh.aliases import Aliases, make_default_aliases
from xonsh.environ import Env, default_env, locate_binary
from xonsh.foreign_shells import load_foreign_aliases
from xonsh.history import History
from xonsh.inspectors import Inspector
from xonsh.jobs import add_job, wait_for_active_job
from xonsh.platform import ON_POSIX, ON_WINDOWS
from xonsh.proc import (ProcProxy, SimpleProcProxy, ForegroundProcProxy,
SimpleForegroundProcProxy, TeePTYProc,
CompletedCommand, HiddenCompletedCommand)
from xonsh.aliases import Aliases, make_default_aliases
from xonsh.history import History
from xonsh.foreign_shells import load_foreign_aliases
from xonsh.tools import (
suggest_commands, XonshError, expandvars, CommandsCache
)
ENV = None
BUILTINS_LOADED = False
@ -412,7 +413,7 @@ def run_subproc(cmds, captured=False):
procinfo['args'] = list(cmd)
stdin = None
stderr = None
if isinstance(cmd, string_types):
if isinstance(cmd, str):
continue
streams = {}
while True:
@ -671,10 +672,10 @@ def subproc_uncaptured(*cmds):
def ensure_list_of_strs(x):
"""Ensures that x is a list of strings."""
if isinstance(x, string_types):
if isinstance(x, str):
rtn = [x]
elif isinstance(x, Sequence):
rtn = [i if isinstance(i, string_types) else str(i) for i in x]
rtn = [i if isinstance(i, str) else str(i) for i in x]
else:
rtn = [str(x)]
return rtn

View file

@ -1,21 +1,21 @@
# -*- coding: utf-8 -*-
"""A (tab-)completer for xonsh."""
import os
import re
import ast
import sys
import shlex
import builtins
import inspect
import importlib
import os
from pathlib import Path
import pickle
import inspect
import builtins
import importlib
import re
import shlex
import subprocess
import sys
from xonsh.built_ins import iglobpath, expand_path
from xonsh.platform import ON_WINDOWS
from xonsh.tools import (subexpr_from_unbalanced, get_sep,
check_for_partial_string, RE_STRING_START)
from xonsh.tools import ON_WINDOWS
RE_DASHF = re.compile(r'-F\s+(\w+)')
@ -445,7 +445,7 @@ class Completer(object):
def _collect_completions_sources():
sources = []
paths = (Path(x) for x in
builtins.__xonsh_env__.get('BASH_COMPLETIONS'))
builtins.__xonsh_env__.get('BASH_COMPLETIONS', ()))
for path in paths:
if path.is_file():
sources.append('source ' + str(path))

View file

@ -1,36 +1,37 @@
# -*- coding: utf-8 -*-
"""Environment for the xonsh shell."""
import os
import re
import sys
import builtins
from collections import Mapping, MutableMapping, MutableSequence, MutableSet, namedtuple
from contextlib import contextmanager
from functools import wraps
from itertools import chain
import json
import locale
import os
from pprint import pformat
import re
import socket
import string
import locale
import builtins
import subprocess
from itertools import chain
import sys
from warnings import warn
from pprint import pformat
from functools import wraps
from contextlib import contextmanager
from collections import (Mapping, MutableMapping, MutableSequence,
MutableSet, namedtuple)
from xonsh import __version__ as XONSH_VERSION
from xonsh.tools import (
ON_WINDOWS, ON_MAC, ON_LINUX, ON_ARCH, IS_ROOT, ON_ANACONDA,
always_true, always_false, ensure_string, is_env_path, str_to_env_path,
env_path_to_str, is_bool, to_bool, bool_to_str, is_history_tuple, to_history_tuple,
history_tuple_to_str, is_float, string_types, is_string, DEFAULT_ENCODING,
is_completions_display_value, to_completions_display_value, is_string_set,
csv_to_set, set_to_csv, get_sep, is_int, is_bool_seq, csv_to_bool_seq,
bool_seq_to_csv, DefaultNotGiven, setup_win_unicode_console,
intensify_colors_on_win_setter, print_exception
)
from xonsh.codecache import run_script_with_cache
from xonsh.dirstack import _get_cwd
from xonsh.foreign_shells import DEFAULT_SHELLS, load_foreign_envs
from xonsh.platform import (BASH_COMPLETIONS_DEFAULT, ON_ANACONDA, ON_LINUX,
ON_WINDOWS, DEFAULT_ENCODING)
from xonsh.tools import (
IS_SUPERUSER, always_true, always_false, ensure_string, is_env_path,
str_to_env_path, env_path_to_str, is_bool, to_bool, bool_to_str,
is_history_tuple, to_history_tuple, history_tuple_to_str, is_float,
is_string, is_completions_display_value, to_completions_display_value,
is_string_set, csv_to_set, set_to_csv, get_sep, is_int, is_bool_seq,
csv_to_bool_seq, bool_seq_to_csv, DefaultNotGiven, print_exception,
setup_win_unicode_console, intensify_colors_on_win_setter
)
LOCALE_CATS = {
'LC_CTYPE': locale.LC_CTYPE,
@ -157,14 +158,7 @@ DEFAULT_VALUES = {
'AUTO_CD': False,
'AUTO_PUSHD': False,
'AUTO_SUGGEST': True,
'BASH_COMPLETIONS': (('/usr/local/etc/bash_completion',
'/opt/local/etc/profile.d/bash_completion.sh')
if ON_MAC else
('/usr/share/bash-completion/bash_completion',
'/usr/share/bash-completion/completions/git')
if ON_ARCH else
('/etc/bash_completion',
'/usr/share/bash-completion/completions/git')),
'BASH_COMPLETIONS': BASH_COMPLETIONS_DEFAULT,
'CASE_SENSITIVE_COMPLETIONS': ON_LINUX,
'CDPATH': (),
'COMPLETIONS_DISPLAY': 'multi',
@ -320,7 +314,8 @@ DEFAULT_DOCS = {
'INTENSIFY_COLORS_ON_WIN': VarDocs('Enhance style colors for readability '
'when using the default terminal (cmd.exe) on winodws. Blue colors, '
'which are hard to read, are replaced with cyan. Other colors are '
'generally replaced by their bright counter parts.'),
'generally replaced by their bright counter parts.',
configurable=ON_WINDOWS),
'LOADED_CONFIG': VarDocs('Whether or not the xonsh config file was loaded',
configurable=False),
'LOADED_RC_FILES': VarDocs(
@ -391,7 +386,8 @@ DEFAULT_DOCS = {
'used. This can be used to fix situations where a spawned process, '
'such as piping into \'grep\', exits too quickly for the piping '
'operation itself. TeePTY (and thus this variable) are currently '
'only used when $XONSH_STORE_STDOUT is True.', configurable=ON_LINUX),
'only used when $XONSH_STORE_STDOUT is True.',
configurable=ON_LINUX),
'TERM': VarDocs(
'TERM is sometimes set by the terminal emulator. This is used (when '
"valid) to determine whether or not to set the title. Users shouldn't "
@ -538,7 +534,7 @@ class Env(MutableMapping):
for key, val in self._d.items():
if not self.detypeable(val):
continue
if not isinstance(key, string_types):
if not isinstance(key, str):
key = str(key)
ensurer = self.get_ensurer(key)
val = ensurer.detype(val)
@ -570,16 +566,14 @@ class Env(MutableMapping):
if key in self.ensurers:
return self.ensurers[key]
for k, ensurer in self.ensurers.items():
if isinstance(k, string_types):
if isinstance(k, str):
continue
m = k.match(key)
if m is not None:
ens = ensurer
if k.match(key) is not None:
break
else:
ens = default
self.ensurers[key] = ens
return ens
ensurer = default
self.ensurers[key] = ensurer
return ensurer
def get_docs(self, key, default=VarDocs('<no documentation>')):
"""Gets the documentation for the environment variable."""
@ -660,16 +654,14 @@ class Env(MutableMapping):
if self._orig_env is None:
self.replace_env()
else:
dval = ensurer.detype(val)
os.environ[key] = dval
os.environ[key] = ensurer.detype(val)
def __delitem__(self, key):
val = self._d.pop(key)
if self.detypeable(val):
self._detyped = None
if self.get('UPDATE_OS_ENVIRON'):
if key in os.environ:
del os.environ[key]
if self.get('UPDATE_OS_ENVIRON') and key in os.environ:
del os.environ[key]
def get(self, key, default=None):
"""The environment will look up default values from its own defaults if a
@ -756,7 +748,7 @@ def yield_executables_posix(directory, name):
names = os.listdir(directory)
except PermissionError:
return
if name in os.listdir(directory):
if name in names:
path = os.path.join(directory, name)
if _is_executable_file(path):
yield path
@ -1052,7 +1044,7 @@ else:
FORMATTER_DICT = dict(
user=os.environ.get(USER, '<user>'),
prompt_end='#' if IS_ROOT else '$',
prompt_end='#' if IS_SUPERUSER else '$',
hostname=socket.gethostname().split('.', 1)[0],
cwd=_replace_home_cwd,
cwd_dir=lambda: os.path.dirname(_replace_home_cwd()),
@ -1127,7 +1119,7 @@ def partial_format_prompt(template=DEFAULT_PROMPT, formatter_dict=None):
if field is None:
continue
elif field.startswith('$'):
v = builtins.__xonsh_env__[name[1:]]
v = builtins.__xonsh_env__[name[1:]] # FIXME `name` is an unresolved ref
v = _FORMATTER.convert_field(v, conv)
v = _FORMATTER.format_field(v, spec)
toks.append(v)
@ -1226,7 +1218,7 @@ def load_static_config(ctx, config=None):
def xonshrc_context(rcfiles=None, execer=None):
"""Attempts to read in xonshrc file, and return the contents."""
loaded = builtins.__xonsh_env__['LOADED_RC_FILES'] = []
if (rcfiles is None or execer is None):
if rcfiles is None or execer is None:
return {}
env = {}
for rcfile in rcfiles:

View file

@ -3,13 +3,12 @@
This module registers the hooks it defines when it is imported.
"""
import builtins
from importlib.abc import MetaPathFinder, SourceLoader
from importlib.machinery import ModuleSpec
import os
import sys
import builtins
from importlib.machinery import ModuleSpec
from importlib.abc import MetaPathFinder, SourceLoader
from xonsh.tools import string_types
from xonsh.execer import Execer
@ -46,7 +45,7 @@ class XonshImportHook(MetaPathFinder, SourceLoader):
name = fullname.rsplit(dot, 1)[-1]
fname = name + '.xsh'
for p in path:
if not isinstance(p, string_types):
if not isinstance(p, str):
continue
if not os.path.isdir(p):
continue

View file

@ -8,29 +8,24 @@ This file was forked from the IPython project:
* Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
* Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
"""
from collections import namedtuple
import inspect
import io as stdlib_io
from itertools import zip_longest
import linecache
import os
import sys
import types
import inspect
import linecache
import io as stdlib_io
from collections import namedtuple
from xonsh import openpy
from xonsh.tools import (cast_unicode, safe_hasattr, string_types, indent,
VER_MAJOR_MINOR, VER_3_4, print_color, format_color, HAVE_PYGMENTS)
from xonsh.tools import (cast_unicode, safe_hasattr, indent,
print_color, format_color)
from xonsh.platform import HAS_PYGMENTS, PYTHON_VERSION_INFO
if HAVE_PYGMENTS:
if HAS_PYGMENTS:
import pygments
from xonsh import pyghooks
if sys.version_info[0] > 2:
ISPY3K = True
from itertools import zip_longest
else:
ISPY3K = False
from itertools import izip_longest as zip_longest
# builtin docstrings to ignore
_func_call_docstring = types.FunctionType.__call__.__doc__
@ -100,7 +95,7 @@ def getdoc(obj):
pass
else:
# if we get extra info, we add it to the normal docstring.
if isinstance(ds, string_types):
if isinstance(ds, str):
return inspect.cleandoc(ds)
try:
@ -162,7 +157,7 @@ def getargspec(obj):
if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
obj = obj.__call__
return inspect.getfullargspec(obj) if ISPY3K else inspect.getargspec(obj)
return inspect.getfullargspec(obj)
def format_argspec(argspec):
@ -300,7 +295,7 @@ def find_source_lines(obj):
return lineno
if VER_MAJOR_MINOR <= VER_3_4:
if PYTHON_VERSION_INFO < (3, 5, 0):
FrameInfo = namedtuple('FrameInfo', ['frame', 'filename', 'lineno', 'function',
'code_context', 'index'])
def getouterframes(frame, context=1):
@ -351,8 +346,6 @@ class Inspector(object):
if inspect.isclass(obj):
header = self.__head('Class constructor information:\n')
obj = obj.__init__
elif (not ISPY3K) and type(obj) is types.InstanceType:
obj = obj.__call__
output = self._getdef(obj, oname)
if output is None:
@ -488,7 +481,7 @@ class Inspector(object):
title_width : int
How many characters to pad titles to. Default to longest title.
"""
if HAVE_PYGMENTS:
if HAS_PYGMENTS:
rtn = self._format_fields_tokens(fields, title_width=title_width)
else:
rtn = self._format_fields_str(fields, title_width=title_width)
@ -535,14 +528,6 @@ class Inspector(object):
displayfields.append((title, field.rstrip()))
add_fields(self.pinfo_fields1)
# Base class for old-style instances
if ((not ISPY3K) and
isinstance(obj, types.InstanceType) and
info['base_class']):
o = ("Base Class", info['base_class'].rstrip())
displayfields.append(o)
add_fields(self.pinfo_fields2)
# Namespace
@ -600,7 +585,7 @@ class Inspector(object):
# Get docstring, special-casing aliases:
if isalias:
if not callable(obj):
if len(obj) >= 2 and isinstance(obj[1], string_types):
if len(obj) >= 2 and isinstance(obj[1], str):
ds = "Alias to the system command:\n {0}".format(obj[1])
else: # pylint:disable=bare-except
ds = "Alias: " + str(obj)
@ -689,7 +674,7 @@ class Inspector(object):
source = getsource(obj.__class__, binary_file)
if source is not None:
source = source.rstrip()
if HAVE_PYGMENTS:
if HAS_PYGMENTS:
lexer = pyghooks.XonshLexer()
source = list(pygments.lex(source, lexer=lexer))
out['source'] = source

View file

@ -1,20 +1,15 @@
# -*- coding: utf-8 -*-
"""Implements a lazy JSON file class that wraps around json data."""
import io
import weakref
from contextlib import contextmanager
import json
from collections import Mapping, Sequence
from contextlib import contextmanager
import weakref
try:
import simplejson as json
except ImportError:
import json
from xonsh.tools import string_types
def _to_json_with_size(obj, offset=0, sort_keys=False):
if isinstance(obj, string_types):
if isinstance(obj, str):
s = json.dumps(obj)
o = offset
n = size = len(s.encode()) # size in bytes
@ -207,7 +202,7 @@ class LazyJSON(Node):
"""
self._f = f
self.reopen = reopen
if not reopen and isinstance(f, string_types):
if not reopen and isinstance(f, str):
self._f = open(f, 'r', newline='\n')
self._load_index()
self.root = weakref.proxy(self)
@ -224,7 +219,7 @@ class LazyJSON(Node):
@contextmanager
def _open(self, *args, **kwargs):
if self.reopen and isinstance(self._f, string_types):
if self.reopen and isinstance(self._f, str):
f = open(self._f, *args, **kwargs)
yield f
f.close()

View file

@ -3,7 +3,6 @@
Written using a hybrid of ``tokenize`` and PLY.
"""
import xonsh.tokenize as tokenize
from io import BytesIO
from keyword import kwlist
@ -13,7 +12,8 @@ try:
except ImportError:
from xonsh.ply.lex import LexToken
from xonsh.tools import VER_3_5, VER_MAJOR_MINOR
from xonsh.platform import PYTHON_VERSION_INFO
import xonsh.tokenize as tokenize
token_map = {}
"""
@ -51,7 +51,7 @@ token_map[tokenize.REGEXPATH] = 'REGEXPATH'
token_map[tokenize.NEWLINE] = 'NEWLINE'
token_map[tokenize.INDENT] = 'INDENT'
token_map[tokenize.DEDENT] = 'DEDENT'
if VER_3_5 <= VER_MAJOR_MINOR:
if PYTHON_VERSION_INFO >= (3, 5, 0):
token_map[tokenize.ASYNC] = 'ASYNC'
token_map[tokenize.AWAIT] = 'AWAIT'

View file

@ -13,15 +13,16 @@ except ImportError:
setproctitle = None
from xonsh import __version__
from xonsh.environ import DEFAULT_VALUES
from xonsh.shell import Shell
from xonsh.pretty import pprint, pretty
from xonsh.proc import HiddenCompletedCommand
from xonsh.jobs import ignore_sigtstp
from xonsh.tools import (HAVE_PYGMENTS, setup_win_unicode_console, print_color,
ON_WINDOWS)
from xonsh.codecache import (run_script_with_cache, run_code_with_cache)
from xonsh.tools import setup_win_unicode_console, print_color
from xonsh.platform import HAS_PYGMENTS, ON_WINDOWS
from xonsh.codecache import run_script_with_cache, run_code_with_cache
if HAVE_PYGMENTS:
if HAS_PYGMENTS:
import pygments
from xonsh import pyghooks
@ -134,6 +135,7 @@ def arg_undoers():
return au
def undo_args(args):
"""Undoes missaligned args."""
au = arg_undoers()
@ -145,11 +147,12 @@ def undo_args(args):
if a.startswith(k):
au[k](args)
def _pprint_displayhook(value):
if value is None or isinstance(value, HiddenCompletedCommand):
return
builtins._ = None # Set '_' to None to avoid recursion
if HAVE_PYGMENTS:
if HAS_PYGMENTS:
s = pretty(value) # color case
lexer = pyghooks.XonshLexer()
tokens = list(pygments.lex(s, lexer=lexer))
@ -158,12 +161,14 @@ def _pprint_displayhook(value):
pprint(value) # black & white case
builtins._ = value
class XonshMode(enum.Enum):
single_command = 0
script_from_file = 1
script_from_stdin = 2
interactive = 3
def premain(argv=None):
"""Setup for main xonsh entry point, returns parsed arguments."""
if setproctitle is not None:
@ -181,7 +186,8 @@ def premain(argv=None):
version = '/'.join(('xonsh', __version__)),
print(version)
exit()
shell_kwargs = {'shell_type': args.shell_type,
shell_kwargs = {'shell_type': args.shell_type or
DEFAULT_VALUES.get('SHELL_TYPE'),
'completer': False,
'login': False,
'scriptcache': args.scriptcache,
@ -268,6 +274,5 @@ def main_context(argv=None):
postmain(args)
if __name__ == '__main__':
main()

View file

@ -13,11 +13,9 @@ This file was forked from the IPython project:
* Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
"""
import io
import re
import os.path
from io import TextIOWrapper, BytesIO
import re
from xonsh.tools import unicode_type
cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)", re.UNICODE)
cookie_comment_re = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE)
@ -127,7 +125,7 @@ except ImportError:
buf = io.open(filename, 'rb') # Tweaked to use io.open for Python 2
encoding, lines = detect_encoding(buf.readline)
buf.seek(0)
text = TextIOWrapper(buf, encoding, line_buffering=True)
text = io.TextIOWrapper(buf, encoding, line_buffering=True)
text.mode = 'r'
return text
@ -140,10 +138,10 @@ def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True):
txt can be either a bytes buffer or a string containing the source
code.
"""
if isinstance(txt, unicode_type):
if isinstance(txt, str):
return txt
if isinstance(txt, bytes):
buf = BytesIO(txt)
buf = io.BytesIO(txt)
else:
buf = txt
try:
@ -151,7 +149,7 @@ def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True):
except SyntaxError:
encoding = "ascii"
buf.seek(0)
text = TextIOWrapper(buf, encoding, errors=errors, line_buffering=True)
text = io.TextIOWrapper(buf, encoding, errors=errors, line_buffering=True)
text.mode = 'r'
if skip_encoding_cookie:
return u"".join(strip_encoding_cookie(text))

View file

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
"""Implements the xonsh parser."""
from xonsh.tools import (VER_3_4, VER_3_5, VER_MAJOR_MINOR)
from xonsh.platform import PYTHON_VERSION_INFO
if VER_MAJOR_MINOR <= VER_3_4:
if PYTHON_VERSION_INFO < (3, 5, 0):
from xonsh.parsers.v34 import Parser
else:
from xonsh.parsers.v35 import Parser

View file

@ -9,7 +9,7 @@ except ImportError:
from xonsh import ast
from xonsh.lexer import Lexer, LexToken
from xonsh.tools import VER_3_5_1, VER_FULL
from xonsh.platform import PYTHON_VERSION_INFO
class Location(object):
@ -610,7 +610,7 @@ class BaseParser(object):
"""tfpdef : name_tok colon_test_opt"""
p1 = p[1]
kwargs = {'arg': p1.value, 'annotation': p[2]}
if VER_FULL >= VER_3_5_1:
if PYTHON_VERSION_INFO >= (3, 5, 1):
kwargs.update({
'lineno': p1.lineno,
'col_offset': p1.lexpos,
@ -736,7 +736,7 @@ class BaseParser(object):
"""vfpdef : name_tok"""
p1 = p[1]
kwargs = {'arg': p1.value, 'annotation': None}
if VER_FULL >= VER_3_5_1:
if PYTHON_VERSION_INFO >= (3, 5, 1):
kwargs.update({
'lineno': p1.lineno,
'col_offset': p1.lexpos,

155
xonsh/platform.py Normal file
View file

@ -0,0 +1,155 @@
""" Module for platform-specific constants and implementations, as well as
compatibility layers to make use of the 'best' implementation available
on a platform. """
from functools import lru_cache
import os
import platform
import sys
try:
import distro
except ImportError:
distro = None
except:
raise
# do not import any xonsh-modules here to avoid circular dependencies
#
# OS
#
ON_DARWIN = platform.system() == 'Darwin'
ON_LINUX = platform.system() == 'Linux'
ON_WINDOWS = platform.system() == 'Windows'
ON_POSIX = (os.name == 'posix')
#
# Python & packages
#
PYTHON_VERSION_INFO = sys.version_info[:3]
ON_ANACONDA = any(s in sys.version for s in {'Anaconda', 'Continuum'})
try:
import pygments
except ImportError:
HAS_PYGMENTS, PYGMENTS_VERSION = False, None
except:
raise
else:
HAS_PYGMENTS, PYGMENTS_VERSION = True, pygments.__version__
@lru_cache(1)
def has_prompt_toolkit():
try:
import prompt_toolkit
except ImportError:
return False
except:
raise
else:
return True
@lru_cache(1)
def ptk_version():
if has_prompt_toolkit():
import prompt_toolkit
return getattr(prompt_toolkit, '__version__', '<0.57')
else:
return None
@lru_cache(1)
def ptk_version_info():
if has_prompt_toolkit():
return tuple(int(x) for x in ptk_version().strip('<>+-=.').split('.'))
else:
return None
if ON_WINDOWS or has_prompt_toolkit():
BEST_SHELL_TYPE = 'prompt_toolkit'
else:
BEST_SHELL_TYPE = 'readline'
@lru_cache(1)
def is_readline_available():
"""Checks if readline is available to import."""
try:
import readline
except: # pyreadline will sometimes fail in strange ways
return False
else:
return True
#
# Encoding
#
DEFAULT_ENCODING = sys.getdefaultencoding()
#
# Linux distro
#
if ON_LINUX:
if distro:
LINUX_DISTRO = distro.id()
elif PYTHON_VERSION_INFO < (3, 7, 0):
LINUX_DISTRO = platform.linux_distribution()[0] or 'unknown'
elif '-ARCH-' in platform.platform():
LINUX_DISTRO = 'arch' # that's the only one we need to know for now
else:
LINUX_DISTRO = 'unknown'
else:
LINUX_DISTRO = None
#
# Windows
#
if ON_WINDOWS:
try:
import win_unicode_console
except ImportError:
win_unicode_console = None
else:
win_unicode_console = None
#
# Bash completions defaults
#
if LINUX_DISTRO == 'arch':
BASH_COMPLETIONS_DEFAULT = (
'/etc/bash_completion',
'/usr/share/bash-completion/completions')
elif ON_LINUX:
BASH_COMPLETIONS_DEFAULT = (
'/usr/share/bash-completion',
'/usr/share/bash-completion/completions')
elif ON_DARWIN:
BASH_COMPLETIONS_DEFAULT = (
'/usr/local/etc/bash_completion',
'/opt/local/etc/profile.d/bash_completion.sh')
else:
BASH_COMPLETIONS_DEFAULT = ()
#
# All constants as a dict
#
PLATFORM_INFO = {name: obj for name, obj in globals().items()
if name.isupper()}

View file

@ -92,12 +92,6 @@ resultlimit = 40 # Size limit of results when running in debug mod
pickle_protocol = 0 # Protocol to use when writing pickle files
# String type-checking compatibility
if sys.version_info[0] < 3:
string_types = basestring
else:
string_types = str
MAXINT = sys.maxsize
# This object is a stand-in for a logging object created by the
@ -1982,7 +1976,7 @@ class LRTable(object):
import cPickle as pickle
except ImportError:
import pickle
if not os.path.exists(filename):
raise ImportError
@ -3002,7 +2996,7 @@ class ParserReflect(object):
# Validate the start symbol
def validate_start(self):
if self.start is not None:
if not isinstance(self.start, string_types):
if not isinstance(self.start, str):
self.log.error("'start' must be a string")
# Look for error handler
@ -3088,12 +3082,12 @@ class ParserReflect(object):
self.error = True
return
assoc = p[0]
if not isinstance(assoc, string_types):
if not isinstance(assoc, str):
self.log.error('precedence associativity must be a string')
self.error = True
return
for term in p[1:]:
if not isinstance(term, string_types):
if not isinstance(term, str):
self.log.error('precedence items must be strings')
self.error = True
return

View file

@ -73,12 +73,11 @@ without open / close parameters. You can also use this code::
with p.indent(2):
...
:copyright: 2007 by Armin Ronacher.
Portions (c) 2009 by Robert Kern.
:license: BSD License.
"""
#from __future__ import print_function
from contextlib import contextmanager
import sys
import types
@ -88,7 +87,6 @@ from collections import deque
#from IPython.utils.py3compat import PY3, cast_unicode, string_types
#from IPython.utils.encoding import get_stream_enc
string_types = (str,)
from io import StringIO
@ -102,7 +100,7 @@ _re_pattern_type = type(re.compile(''))
def _safe_getattr(obj, attr, default=None):
"""Safe version of getattr.
Same as getattr, but will return ``default`` on any Exception,
rather than raising.
"""
@ -231,7 +229,7 @@ class PrettyPrinter(_PrettyPrinterBase):
self.buffer.append(Breakable(sep, width, self))
self.buffer_width += width
self._break_outer_groups()
def break_(self):
"""
Explicitly insert a newline into the output, maintaining correct indentation.
@ -241,7 +239,7 @@ class PrettyPrinter(_PrettyPrinterBase):
self.output.write(' ' * self.indentation)
self.output_width = self.indentation
self.buffer_width = 0
def begin_group(self, indent=0, open=''):
"""
@ -267,7 +265,7 @@ class PrettyPrinter(_PrettyPrinterBase):
self.group_stack.append(group)
self.group_queue.enq(group)
self.indentation += indent
def _enumerate(self, seq):
"""like enumerate, but with an upper limit on the number of items"""
for idx, x in enumerate(seq):
@ -277,7 +275,7 @@ class PrettyPrinter(_PrettyPrinterBase):
self.text('...')
return
yield idx, x
def end_group(self, dedent=0, close=''):
"""End a group. See `begin_group` for more details."""
self.indentation -= dedent
@ -675,13 +673,13 @@ def _type_pprint(obj, p, cycle):
mod = _safe_getattr(obj, '__module__', None)
try:
name = obj.__qualname__
if not isinstance(name, string_types):
if not isinstance(name, str):
# This can happen if the type implements __qualname__ as a property
# or other descriptor in Python 2.
raise Exception("Try __name__")
except Exception:
name = obj.__name__
if not isinstance(name, string_types):
if not isinstance(name, str):
name = '<unknown type>'
if mod in (None, '__builtin__', 'builtins', 'exceptions'):
@ -739,7 +737,7 @@ _type_pprinters = {
tuple: _seq_pprinter_factory('(', ')', tuple),
list: _seq_pprinter_factory('[', ']', list),
dict: _dict_pprinter_factory('{', '}', dict),
set: _set_pprinter_factory('{', '}', set),
frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
super: _super_pprint,
@ -748,7 +746,7 @@ _type_pprinters = {
types.FunctionType: _function_pprint,
types.BuiltinFunctionType: _function_pprint,
types.MethodType: _repr_pprint,
datetime.datetime: _repr_pprint,
datetime.timedelta: _repr_pprint,
_exception_base: _exception_pprint
@ -760,7 +758,7 @@ try:
_type_pprinters[types.SliceType] = _repr_pprint
except AttributeError: # Python 3
_type_pprinters[slice] = _repr_pprint
try:
_type_pprinters[xrange] = _repr_pprint
_type_pprinters[long] = _repr_pprint

View file

@ -437,6 +437,7 @@ def foreground(f):
# Pseudo-terminal Proxies
#
@fallback(ON_LINUX, Popen)
class TeePTYProc(object):

View file

@ -2,11 +2,12 @@
"""Completer implementation to use with prompt_toolkit."""
import os
import builtins
import xonsh.shell
from prompt_toolkit.layout.dimension import LayoutDimension
from prompt_toolkit.completion import Completer, Completion
from xonsh.platform import ptk_version
class PromptToolkitCompleter(Completer):
"""Simple prompt_toolkit Completer object.
@ -42,7 +43,7 @@ class PromptToolkitCompleter(Completer):
def reserve_space(self):
cli = builtins.__xonsh_shell__.shell.prompter.cli
if xonsh.shell.prompt_toolkit_version().startswith("1.0"):
if ptk_version().startswith("1.0"):
# This is the layout for ptk 1.0
window = cli.application.layout.children[0].content.children[1]
else:

View file

@ -7,22 +7,20 @@ from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.layout.lexers import PygmentsLexer
from prompt_toolkit.filters import Condition
from prompt_toolkit.styles import PygmentsStyle
from pygments.style import Style
from pygments.styles import get_all_styles
from pygments.styles.default import DefaultStyle
from pygments.token import (Keyword, Name, Comment, String, Error, Number,
Operator, Generic, Whitespace, Token)
from pygments.token import Token
from xonsh.base_shell import BaseShell
from xonsh.tools import print_exception
from xonsh.environ import partial_format_prompt
from xonsh.pyghooks import XonshLexer, XonshStyle, partial_color_tokenize, \
xonsh_style_proxy
from xonsh.platform import ptk_version, ptk_version_info
from xonsh.pyghooks import (XonshLexer, partial_color_tokenize,
xonsh_style_proxy)
from xonsh.ptk.completer import PromptToolkitCompleter
from xonsh.ptk.history import PromptToolkitHistory
from xonsh.ptk.key_bindings import load_xonsh_bindings
from xonsh.ptk.shortcuts import Prompter, print_tokens
from xonsh.shell import prompt_toolkit_version
class PromptToolkitShell(BaseShell):
"""The xonsh shell."""
@ -37,12 +35,12 @@ class PromptToolkitShell(BaseShell):
'enable_auto_suggest_bindings': True,
'enable_search': True,
'enable_abort_and_exit_bindings': True,
'enable_open_in_editor': True
'enable_open_in_editor': True,
}
vptk = prompt_toolkit_version()
major, minor = [int(x) for x in vptk.split('.')[:2]]
self.new_vi_mode_flag = ((major, minor) >= (1, 0)) and (vptk != '<0.57')
if not(self.new_vi_mode_flag):
major, minor = ptk_version_info()[:2]
self.new_vi_mode_flag = (major, minor) >= (1, 0) \
and ptk_version() != '<0.57'
if not self.new_vi_mode_flag:
# enable_vi_mode is deprecated acoording to prompt_toolset 1.0 document.
key_bindings_manager_args['enable_vi_mode'] = Condition(lambda cli: builtins.__xonsh_env__.get('VI_MODE'))

View file

@ -1,12 +1,14 @@
"""A prompt-toolkit inspired shortcut collection."""
import builtins
import textwrap
from prompt_toolkit.interface import CommandLineInterface
from prompt_toolkit.utils import DummyContext
from prompt_toolkit.shortcuts import (create_prompt_application,
create_eventloop, create_asyncio_eventloop, create_output)
from xonsh.shell import prompt_toolkit_version_info
from xonsh.platform import ptk_version_info
import builtins
class Prompter(object):
@ -22,7 +24,7 @@ class Prompter(object):
will be created when the prompt() method is called.
"""
self.cli = cli
self.major_minor = prompt_toolkit_version_info()[:2]
self.major_minor = ptk_version_info()[:2]
def __enter__(self):
self.reset()
@ -78,8 +80,8 @@ class Prompter(object):
editing_mode = EditingMode.VI
else:
editing_mode = EditingMode.EMACS
kwargs['editing_mode'] = editing_mode
kwargs['vi_mode'] = builtins.__xonsh_env__.get('VI_MODE')
cli = CommandLineInterface(
application=create_prompt_application(message, **kwargs),
eventloop=eventloop,
@ -95,7 +97,7 @@ class Prompter(object):
if return_asyncio_coroutine:
# Create an asyncio coroutine and call it.
exec_context = {'patch_context': patch_context, 'cli': cli}
exec_(textwrap.dedent('''
exec(textwrap.dedent('''
import asyncio
@asyncio.coroutine
def prompt_coro():

View file

@ -12,9 +12,10 @@ from xonsh import lazyjson
from xonsh.base_shell import BaseShell
from xonsh.ansi_colors import partial_color_format, color_style_names, color_style
from xonsh.environ import partial_format_prompt, multiline_prompt
from xonsh.tools import ON_WINDOWS, print_exception, HAVE_PYGMENTS
from xonsh.tools import print_exception
from xonsh.platform import HAS_PYGMENTS, ON_WINDOWS
if HAVE_PYGMENTS:
if HAS_PYGMENTS:
from xonsh import pyghooks
import pygments
from pygments.formatters.terminal256 import Terminal256Formatter

View file

@ -1,52 +1,15 @@
# -*- coding: utf-8 -*-
"""The xonsh shell"""
import random
import builtins
import random
from warnings import warn
from xonsh import xontribs
from xonsh.execer import Execer
from xonsh.environ import xonshrc_context
from xonsh.tools import XonshError, ON_WINDOWS
def is_readline_available():
"""Checks if readline is available to import."""
try:
import readline
return True
except Exception: # pyreadline will sometimes fail in strange ways
return False
def is_prompt_toolkit_available():
"""Checks if prompt_toolkit is available to import."""
try:
import prompt_toolkit
return True
except ImportError:
return False
def prompt_toolkit_version():
"""Gets the prompt toolkit version."""
import prompt_toolkit
return getattr(prompt_toolkit, '__version__', '<0.57')
def prompt_toolkit_version_info():
"""Gets the prompt toolkit version info tuple."""
v = prompt_toolkit_version().strip('<>+-=.')
return tuple(map(int, v.split('.')))
def best_shell_type():
"""Gets the best shell type that is available"""
if ON_WINDOWS or is_prompt_toolkit_available():
shell_type = 'prompt_toolkit'
else:
shell_type = 'readline'
return shell_type
from xonsh.execer import Execer
from xonsh.platform import (BEST_SHELL_TYPE, has_prompt_toolkit, ptk_version,
ptk_version_info)
from xonsh.tools import XonshError
class Shell(object):
@ -85,20 +48,19 @@ class Shell(object):
env['SHELL_TYPE'] = shell_type
shell_type = env.get('SHELL_TYPE')
if shell_type == 'best':
shell_type = best_shell_type()
shell_type = BEST_SHELL_TYPE
elif shell_type == 'random':
shell_type = random.choice(('readline', 'prompt_toolkit'))
if shell_type == 'prompt_toolkit':
if not is_prompt_toolkit_available():
if not has_prompt_toolkit():
warn('prompt_toolkit is not available, using readline instead.')
shell_type = env['SHELL_TYPE'] = 'readline'
# actually make the shell
if shell_type == 'none':
from xonsh.base_shell import BaseShell as shell_class
elif shell_type == 'prompt_toolkit':
vptk = prompt_toolkit_version()
major,minor = [int(x) for x in vptk.split('.')[:2]]
if (major,minor) < (0, 57) or vptk == '<0.57': # TODO: remove in future
if ptk_version_info()[:2] < (0, 57) or \
ptk_version() == '<0.57': # TODO: remove in future
msg = ('prompt-toolkit version < v0.57 and may not work as '
'expected. Please update.')
warn(msg, RuntimeWarning)

View file

@ -1,6 +1,6 @@
from xonsh.tools import VER_3_5, VER_FULL
from xonsh.platform import PYTHON_VERSION_INFO
if VER_FULL >= VER_3_5:
if PYTHON_VERSION_INFO >= (3, 5, 0):
from xonsh.tokenize.tokenize_35 import *
else:
from xonsh.tokenize.tokenize_34 import *

View file

@ -20,70 +20,28 @@ Implementations:
import os
import re
import sys
import string
import ctypes
import builtins
import platform
import traceback
import threading
import subprocess
import threading
import traceback
from warnings import warn
from contextlib import contextmanager
from collections import OrderedDict, Sequence, Set
from warnings import warn
#
# Check pygments
#
# adding further imports from xonsh modules is discouraged to avoid cirular
# dependencies
from xonsh.platform import (has_prompt_toolkit, win_unicode_console,
DEFAULT_ENCODING, ON_LINUX, ON_WINDOWS)
def pygments_version():
"""Returns the Pygments version or False."""
try:
import pygments
v = pygments.__version__
except ImportError:
v = False
return v
if sys.version_info[0] >= 3:
string_types = (str, bytes)
unicode_type = str
if has_prompt_toolkit():
import prompt_toolkit
else:
string_types = (str, unicode)
unicode_type = unicode
try:
import win_unicode_console
except ImportError:
win_unicode_console = None
prompt_toolkit = None
DEFAULT_ENCODING = sys.getdefaultencoding()
ON_ANACONDA = any(s in sys.version for s in ['Anaconda','Continuum'])
ON_WINDOWS = (platform.system() == 'Windows')
ON_MAC = (platform.system() == 'Darwin')
ON_LINUX = (platform.system() == 'Linux')
ON_ARCH = (platform.linux_distribution()[0] == 'arch')
ON_POSIX = (os.name == 'posix')
IS_ROOT = ctypes.windll.shell32.IsUserAnAdmin() != 0 if ON_WINDOWS else os.getuid() == 0
HAVE_PYGMENTS = bool(pygments_version())
VER_3_4 = (3, 4)
VER_3_5 = (3, 5)
VER_3_5_1 = (3, 5, 1)
VER_FULL = sys.version_info[:3]
VER_MAJOR_MINOR = sys.version_info[:2]
V_MAJOR_MINOR = 'v{0}{1}'.format(*sys.version_info[:2])
def docstring_by_version(**kwargs):
"""Sets a docstring by the python version."""
doc = kwargs.get(V_MAJOR_MINOR, None)
if V_MAJOR_MINOR is None:
raise RuntimeError('unrecognized version ' + V_MAJOR_MINOR)
def dec(f):
f.__doc__ = doc
return f
return dec
IS_SUPERUSER = ctypes.windll.shell32.IsUserAnAdmin() != 0 if ON_WINDOWS else os.getuid() == 0
class XonshError(Exception):
@ -168,7 +126,7 @@ def subproc_toks(line, mincol=-1, maxcol=None, lexer=None, returnline=False):
return # handle comment lines
tok = toks[-1]
pos = tok.lexpos
if isinstance(tok.value, string_types):
if isinstance(tok.value, str):
end_offset = len(tok.value.rstrip())
else:
el = line[pos:].split('#')[0].rstrip()
@ -507,7 +465,7 @@ def is_float(x):
def is_string(x):
"""Tests if something is a string"""
return isinstance(x, string_types)
return isinstance(x, str)
def always_true(x):
@ -522,19 +480,16 @@ def always_false(x):
def ensure_string(x):
"""Returns a string if x is not a string, and x if it already is."""
if isinstance(x, string_types):
return x
else:
return str(x)
return str(x)
def is_env_path(x):
"""This tests if something is an environment path, ie a list of strings."""
if isinstance(x, string_types):
if isinstance(x, str):
return False
else:
return (isinstance(x, Sequence) and
all([isinstance(a, string_types) for a in x]))
all(isinstance(a, str) for a in x))
def str_to_env_path(x):
@ -560,7 +515,7 @@ def to_bool(x):
""""Converts to a boolean in a semantically meaningful way."""
if isinstance(x, bool):
return x
elif isinstance(x, string_types):
elif isinstance(x, str):
return False if x.lower() in _FALSES else True
else:
return bool(x)
@ -573,8 +528,9 @@ def bool_to_str(x):
_BREAKS = frozenset(['b', 'break', 's', 'skip', 'q', 'quit'])
def to_bool_or_break(x):
if isinstance(x, string_types) and x.lower() in _BREAKS:
if isinstance(x, str) and x.lower() in _BREAKS:
return 'break'
else:
return to_bool(x)
@ -596,11 +552,8 @@ def ensure_int_or_slice(x):
def is_string_set(x):
"""Tests if something is a set"""
if isinstance(x, string_types):
return False
else:
return (isinstance(x, Set) and
all([isinstance(a, string_types) for a in x]))
return (isinstance(x, Set) and
all(isinstance(a, str) for a in x))
def csv_to_set(x):
@ -618,14 +571,12 @@ def set_to_csv(x):
def is_bool_seq(x):
"""Tests if an object is a sequence of bools."""
return isinstance(x, Sequence) and all(map(isinstance, x, [bool]*len(x)))
return isinstance(x, Sequence) and all(isinstance(y, bool) for y in x)
def csv_to_bool_seq(x):
"""Takes a comma-separated string and converts it into a list of bools."""
if len(x) == 0:
return []
return list(map(to_bool, x.split(',')))
return [to_bool(y) for y in csv_to_set(x)]
def bool_seq_to_csv(x):
@ -643,8 +594,8 @@ def to_completions_display_value(x):
x = 'none'
elif x in {'multi', 'true'}:
x = 'multi'
elif x in {'single'}:
x = 'single'
elif x == 'single':
pass
else:
warn('"{}" is not a valid value for $COMPLETIONS_DISPLAY. '.format(x) +
'Using "multi".', RuntimeWarning)
@ -784,12 +735,6 @@ def color_style():
return builtins.__xonsh_shell__.shell.color_style()
try:
import prompt_toolkit
except ImportError:
prompt_toolkit = None
def _get_color_indexes(style_map):
""" Generates the color and windows color index for a style """
table = prompt_toolkit.terminal.win32_output.ColorLookupTable()
@ -980,9 +925,8 @@ def expandvars(path):
if isinstance(path, bytes):
path = path.decode(encoding=ENV.get('XONSH_ENCODING'),
errors=ENV.get('XONSH_ENCODING_ERRORS'))
if '$' not in path and ((not ON_WINDOWS) or ('%' not in path)):
if '$' not in path and (not ON_WINDOWS or '%' not in path):
return path
import string
varchars = string.ascii_letters + string.digits + '_-'
quote = '\''
percent = '%'
@ -1108,28 +1052,30 @@ class CommandsCache(Set):
@property
def all_commands(self):
path = builtins.__xonsh_env__.get('PATH', [])
paths = builtins.__xonsh_env__.get('PATH', [])
paths = frozenset(x for x in paths if os.path.isdir(x))
# did PATH change?
path_hash = hash(frozenset(path))
path_hash = hash(paths)
cache_valid = path_hash == self._path_checksum
self._path_checksum = path_hash
# did aliases change?
al_hash = hash(frozenset(builtins.aliases.keys()))
al_hash = hash(frozenset(builtins.aliases))
cache_valid = cache_valid and al_hash == self._alias_checksum
self._alias_checksum = al_hash
pm = self._path_mtime
# did the contents of any directory in PATH change?
for d in filter(os.path.isdir, path):
m = os.stat(d).st_mtime
if m > pm:
pm = m
cache_valid = False
self._path_mtime = pm
max_mtime = 0
for path in paths:
mtime = os.stat(path).st_mtime
if mtime > max_mtime:
max_mtime = mtime
cache_valid = cache_valid and max_mtime > self._path_mtime
self._path_mtime = max_mtime
if cache_valid:
return self._cmds_cache
allcmds = set()
for d in filter(os.path.isdir, path):
allcmds |= set(os.listdir(d))
allcmds |= set(builtins.aliases.keys())
for path in paths:
allcmds |= set(x for x in os.listdir(path)
if os.path.isfile(x) and os.access(x, os.X_OK))
allcmds |= set(builtins.aliases)
self._cmds_cache = frozenset(allcmds)
return self._cmds_cache

View file

@ -7,27 +7,27 @@ import linecache
from functools import lru_cache
from argparse import ArgumentParser
from xonsh.tools import (DefaultNotGiven, print_color, pygments_version,
format_color, normabspath, to_bool, HAVE_PYGMENTS)
from xonsh.tools import DefaultNotGiven, print_color, normabspath, to_bool
from xonsh.platform import HAS_PYGMENTS
from xonsh import inspectors
from xonsh.environ import _replace_home as replace_home
if HAVE_PYGMENTS:
if HAS_PYGMENTS:
from xonsh import pyghooks
import pygments
import pygments.formatters.terminal
class TracerType(object):
"""Represents a xonsh tracer object, which keeps track of all tracing
state. This is a singleton.
"""
_inst = None
valid_events = frozenset(['line', 'call'])
def __new__(cls, *args, **kwargs):
if cls._inst is None:
cls._inst = super(TracerType, cls).__new__(cls, *args,
**kwargs)
cls._inst = super(TracerType, cls).__new__(cls, *args, **kwargs)
return cls._inst
def __init__(self):
@ -97,7 +97,7 @@ def format_line(fname, lineno, line, color=True, lexer=None, formatter=None):
if not color:
return COLORLESS_LINE.format(fname=fname, lineno=lineno, line=line)
cline = COLOR_LINE.format(fname=fname, lineno=lineno)
if not HAVE_PYGMENTS:
if not HAS_PYGMENTS:
return cline + line
# OK, so we have pygments
tokens = pyghooks.partial_color_tokenize(cline)
@ -109,11 +109,12 @@ def format_line(fname, lineno, line, color=True, lexer=None, formatter=None):
#
# Command line interface
#
def _find_caller(args):
"""Somewhat hacky method of finding the __file__ based on the line executed."""
re_line = re.compile(r'[^;\s|&<>]+\s+' + r'\s+'.join(args))
curr = inspect.currentframe()
for _, fname, lineno, _, lines, _ in inspectors.getouterframes(curr, context=1)[3:]:
for _, fname, lineno, _, lines, _ in inspectors.getouterframes(curr, context=1)[3:]:
if lines is not None and re_line.search(lines[0]) is not None:
return fname
elif lineno == 1 and re_line.search(linecache.getline(fname, lineno)) is not None:
@ -186,6 +187,7 @@ _MAIN_ACTIONS = {
'color': _color,
}
def main(args=None):
"""Main function for tracer command-line interface."""
parser = _create_parser()
@ -195,4 +197,3 @@ def main(args=None):
if __name__ == '__main__':
main()

View file

@ -1,11 +1,11 @@
import os
from os.path import join, basename, exists, expanduser
from os import listdir
from shutil import rmtree
import venv
import builtins
from shutil import rmtree
import xonsh.tools
from xonsh.platform import ON_POSIX, ON_WINDOWS
class Vox:
@ -82,10 +82,10 @@ class Vox:
print('This environment doesn\'t exist. Create it with "vox new %s".\n' % name)
return None
if xonsh.tools.ON_WINDOWS:
if ON_WINDOWS:
bin_dir = 'Scripts'
elif xonsh.tools.ON_POSIX:
elif ON_POSIX:
bin_dir = 'bin'
else:
@ -117,7 +117,7 @@ class Vox:
if xonsh.tools.ON_WINDOWS:
bin_dir = 'Scripts'
elif xonsh.tools.ON_POSIX:
elif ON_POSIX:
bin_dir = 'bin'
else:
@ -137,19 +137,20 @@ class Vox:
def list_envs():
"""List available virtual environments."""
env_names = listdir(builtins.__xonsh_env__['VIRTUALENV_HOME'])
venv_home = builtins.__xonsh_env__['VIRTUALENV_HOME']
try:
env_dirs = os.listdir(builtins.__xonsh_env__['VIRTUALENV_HOME'])
except PermissionError:
print('No permissions on {}'.format(venv_home))
return None
if not env_names:
print('No environments evailable. Create one with "vox new".\n')
if not env_dirs:
print('No environments available. Create one with "vox new".\n')
return None
print('Available environments:')
print('\n'.join(env_dirs))
for env_name in env_names:
print(' %s' % env_name)
else:
print()
@staticmethod
def remove_env(name):

View file

@ -1,5 +1,4 @@
"""The xonsh configuration (xonfig) utility."""
import os
import ast
import json
import shutil
@ -17,10 +16,10 @@ except ImportError:
from xonsh import ply
from xonsh import __version__ as XONSH_VERSION
from xonsh import tools
from xonsh.environ import is_template_string
from xonsh.shell import (is_readline_available, is_prompt_toolkit_available,
prompt_toolkit_version)
from xonsh import platform
from xonsh.platform import is_readline_available, ptk_version
from xonsh import tools
from xonsh.wizard import (Wizard, Pass, Message, Save, Load, YesNo, Input,
PromptVisitor, While, StoreNonEmpty, create_truefalse_cond, YN, Unstorable,
Question)
@ -332,20 +331,21 @@ def _format_json(data):
def _info(ns):
data = [
('xonsh', XONSH_VERSION),
('Python', '.'.join(map(str, tools.VER_FULL))),
('Python', '{}.{}.{}'.format(*platform.PYTHON_VERSION_INFO)),
('PLY', ply.__version__),
('have readline', is_readline_available()),
('prompt toolkit', prompt_toolkit_version() if \
is_prompt_toolkit_available() else False),
('pygments', tools.pygments_version()),
('on posix', tools.ON_POSIX),
('on linux', tools.ON_LINUX),
('on arch', tools.ON_ARCH),
('on windows', tools.ON_WINDOWS),
('on mac', tools.ON_MAC),
('are root user', tools.IS_ROOT),
('default encoding', tools.DEFAULT_ENCODING),
]
('prompt toolkit', ptk_version() or None),
('pygments', platform.PYGMENTS_VERSION),
('on posix', platform.ON_POSIX),
('on linux', platform.ON_LINUX)]
if platform.ON_LINUX:
data.append(('distro', platform.LINUX_DISTRO))
data.extend([
('on darwin', platform.ON_DARWIN),
('on windows', platform.ON_WINDOWS),
('is superuser', tools.IS_SUPERUSER),
('default encoding', platform.DEFAULT_ENCODING),
])
formatter = _format_json if ns.json else _format_human
s = formatter(data)
return s