mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-06 09:20:57 +01:00
Merge branch 'master' into hist_ref
This commit is contained in:
commit
52af21d482
10 changed files with 163 additions and 89 deletions
|
@ -15,6 +15,33 @@ develop xonsh.
|
|||
|
||||
.. note:: All code changes must go through the pull request review procedure.
|
||||
|
||||
|
||||
Making Your First Change
|
||||
========================
|
||||
|
||||
First, install xonsh from source and open a xonsh shell in your favorite
|
||||
terminal application. See installation instructions for details.
|
||||
|
||||
Next, make a trivial change (e.g. ``print("hello!")`` in ``main.py``).
|
||||
|
||||
Finally, run the following commands. You should see the effects of your change
|
||||
(e.g. ``hello!``)::
|
||||
|
||||
$ $XONSH_DEBUG=1
|
||||
$ xonsh
|
||||
|
||||
The xonsh build process collapses all Python source files into a single
|
||||
``__amalgam__.py`` file. When xonsh is started with a falsy value for
|
||||
`$XONSH_DEBUG <envvars.html>`_, it imports Python modules straight from
|
||||
``__amalgam__.py``, which decreases startup times by eliminating the cost of
|
||||
runtime imports. But setting ``$ $XONSH_DEBUG=1`` will suppress amalgamated
|
||||
imports. Reloading the xonsh shell (``$ xonsh``) won't simply import the stale
|
||||
``__amalgam__.py`` file that doesn't contain your new change, but will instead
|
||||
import the unamalgamated source code which does contain your change. You can now
|
||||
load every subsequent change by reloading xonsh, and if your code changes don't
|
||||
seem to have any effect, make sure you check ``$XONSH_DEBUG`` first!
|
||||
|
||||
|
||||
Changelog
|
||||
=========
|
||||
Pull requests will often have CHANGELOG entries associated with. However,
|
||||
|
|
|
@ -244,7 +244,9 @@ Contributing
|
|||
We highly encourage contributions to xonsh! If you would like to contribute,
|
||||
it is as easy as forking the repository on GitHub, making your changes, and
|
||||
issuing a pull request. If you have any questions about this process don't
|
||||
hesitate to ask the mailing list (xonsh@googlegroups.com).
|
||||
hesitate to ask the mailing list (xonsh@googlegroups.com) or the `Gitter <https://gitter.im/xonsh/xonsh>`_ channel.
|
||||
|
||||
See the `Developer's Guide <devguide.html>`_ for more information about contributing.
|
||||
|
||||
==========
|
||||
Contact Us
|
||||
|
|
|
@ -5,9 +5,9 @@ Here are some talks, articles, and other sundry about your favorite shell.
|
|||
|
||||
Talks
|
||||
============
|
||||
**PyCon 2016:** presented by Anthony Scopatz
|
||||
**Python Nordeste 2016:** presented by Lucas Inojosa http://lucasicf.github.io/talks/shell_python/
|
||||
|
||||
**Python Nordeste 2016:** presented by Lucas Inojosa <http://lucasicf.github.io/talks/shell_python/>
|
||||
**PyCon 2016:** presented by Anthony Scopatz
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
|
16
news/enc.rst
Normal file
16
news/enc.rst
Normal file
|
@ -0,0 +1,16 @@
|
|||
**Added:**
|
||||
|
||||
* ``xon.sh`` script now sets ``$LANG=C.UTF8`` in the event that no encoding
|
||||
is detected.
|
||||
|
||||
**Changed:**
|
||||
|
||||
* xonfig command now dumps more encoding related settings.
|
||||
|
||||
**Deprecated:** None
|
||||
|
||||
**Removed:** None
|
||||
|
||||
**Fixed:** None
|
||||
|
||||
**Security:** None
|
14
news/vox_opts.rst
Normal file
14
news/vox_opts.rst
Normal file
|
@ -0,0 +1,14 @@
|
|||
**Added:** None
|
||||
|
||||
**Changed:**
|
||||
|
||||
* The vox xontrib now takes flags very similar to Python's venv tool. Use
|
||||
``vox --help <command>`` to learn more.
|
||||
|
||||
**Deprecated:** None
|
||||
|
||||
**Removed:** None
|
||||
|
||||
**Fixed:** None
|
||||
|
||||
**Security:** None
|
|
@ -1,2 +1,10 @@
|
|||
#!/bin/sh
|
||||
|
||||
# set locale if it is totally undefined
|
||||
if [ -z "${LC_ALL+x}" ] && [ -z "${LC_CTYPE+x}" ] && \
|
||||
[ -z "${LANG+x}" ] && [ -z "${LANGUAGE+x}" ]; then
|
||||
export LANG=C.UTF-8
|
||||
fi
|
||||
|
||||
# run python
|
||||
/usr/bin/env PYTHONUNBUFFERED=1 python3 -u -m xonsh $@
|
||||
|
|
|
@ -23,6 +23,7 @@ class _TeeOut(object):
|
|||
self.buffer = buf
|
||||
self.stdout = sys.stdout
|
||||
self.encoding = self.stdout.encoding
|
||||
self.errors = self.stdout.errors
|
||||
sys.stdout = self
|
||||
|
||||
def __del__(self):
|
||||
|
@ -55,6 +56,7 @@ class _TeeErr(object):
|
|||
self.buffer = buf
|
||||
self.stderr = sys.stderr
|
||||
self.encoding = self.stderr.encoding
|
||||
self.errors = self.stderr.errors
|
||||
sys.stderr = self
|
||||
|
||||
def __del__(self):
|
||||
|
|
|
@ -110,6 +110,7 @@ DEFAULT_ENSURERS = LazyObject(lambda: {
|
|||
'IGNOREEOF': (is_bool, to_bool, bool_to_str),
|
||||
'INTENSIFY_COLORS_ON_WIN': (always_false, intensify_colors_on_win_setter,
|
||||
bool_to_str),
|
||||
'LANG': (is_string, ensure_string, ensure_string),
|
||||
'LC_COLLATE': (always_false, locale_convert('LC_COLLATE'), ensure_string),
|
||||
'LC_CTYPE': (always_false, locale_convert('LC_CTYPE'), ensure_string),
|
||||
'LC_MESSAGES': (always_false, locale_convert('LC_MESSAGES'), ensure_string),
|
||||
|
@ -253,6 +254,7 @@ def DEFAULT_VALUES():
|
|||
'IGNOREEOF': False,
|
||||
'INDENT': ' ',
|
||||
'INTENSIFY_COLORS_ON_WIN': True,
|
||||
'LANG': 'C.UTF-8',
|
||||
'LC_CTYPE': locale.setlocale(locale.LC_CTYPE),
|
||||
'LC_COLLATE': locale.setlocale(locale.LC_COLLATE),
|
||||
'LC_TIME': locale.setlocale(locale.LC_TIME),
|
||||
|
@ -429,6 +431,7 @@ DEFAULT_DOCS = LazyObject(lambda: {
|
|||
'which are hard to read, are replaced with cyan. Other colors are '
|
||||
'generally replaced by their bright counter parts.',
|
||||
configurable=ON_WINDOWS),
|
||||
'LANG': VarDocs('Fallback locale setting for systems where it matters'),
|
||||
'LOADED_CONFIG': VarDocs(
|
||||
'Whether or not the xonsh config file was loaded',
|
||||
configurable=False),
|
||||
|
|
|
@ -336,6 +336,7 @@ def _xonfig_format_json(data):
|
|||
|
||||
|
||||
def _info(ns):
|
||||
env = builtins.__xonsh_env__
|
||||
data = [
|
||||
('xonsh', XONSH_VERSION),
|
||||
('Git SHA', githash()),
|
||||
|
@ -343,9 +344,9 @@ def _info(ns):
|
|||
('PLY', ply.__version__),
|
||||
('have readline', is_readline_available()),
|
||||
('prompt toolkit', ptk_version() or None),
|
||||
('shell type', builtins.__xonsh_env__.get('SHELL_TYPE')),
|
||||
('shell type', env.get('SHELL_TYPE')),
|
||||
('pygments', pygments_version()),
|
||||
('on posix', ON_POSIX),
|
||||
('on posix', bool(ON_POSIX)),
|
||||
('on linux', ON_LINUX)]
|
||||
if ON_LINUX:
|
||||
data.append(('distro', linux_distro()))
|
||||
|
@ -355,6 +356,8 @@ def _info(ns):
|
|||
('on cygwin', ON_CYGWIN),
|
||||
('is superuser', is_superuser()),
|
||||
('default encoding', DEFAULT_ENCODING),
|
||||
('xonsh encoding', env.get('XONSH_ENCODING')),
|
||||
('encoding errors', env.get('XONSH_ENCODING_ERRORS')),
|
||||
])
|
||||
formatter = _xonfig_format_json if ns.json else _xonfig_format_human
|
||||
s = formatter(data)
|
||||
|
|
165
xontrib/vox.py
165
xontrib/vox.py
|
@ -2,77 +2,108 @@
|
|||
|
||||
import sys as _sys
|
||||
import xontrib.voxapi as _voxapi
|
||||
import xonsh.lazyasd as _lazyasd
|
||||
|
||||
|
||||
class _VoxHandler:
|
||||
"""Vox is a virtual environment manager for xonsh."""
|
||||
|
||||
def parser():
|
||||
from argparse import ArgumentParser
|
||||
parser = ArgumentParser(prog='vox', description=__doc__)
|
||||
subparsers = parser.add_subparsers(dest='command')
|
||||
|
||||
create = subparsers.add_parser(
|
||||
'new', aliases=['create'],
|
||||
help='Create a new virtual environment'
|
||||
)
|
||||
create.add_argument('name', metavar='ENV',
|
||||
help='The environments to create')
|
||||
|
||||
create.add_argument('--system-site-packages', default=False,
|
||||
action='store_true', dest='system_site',
|
||||
help='Give the virtual environment access to the '
|
||||
'system site-packages dir.')
|
||||
|
||||
from xonsh.platform import ON_WINDOWS
|
||||
group = create.add_mutually_exclusive_group()
|
||||
group.add_argument('--symlinks', default=not ON_WINDOWS,
|
||||
action='store_true', dest='symlinks',
|
||||
help='Try to use symlinks rather than copies, '
|
||||
'when symlinks are not the default for '
|
||||
'the platform.')
|
||||
group.add_argument('--copies', default=ON_WINDOWS,
|
||||
action='store_false', dest='symlinks',
|
||||
help='Try to use copies rather than symlinks, '
|
||||
'even when symlinks are the default for '
|
||||
'the platform.')
|
||||
create.add_argument('--without-pip', dest='with_pip',
|
||||
default=True, action='store_false',
|
||||
help='Skips installing or upgrading pip in the '
|
||||
'virtual environment (pip is bootstrapped '
|
||||
'by default)')
|
||||
|
||||
activate = subparsers.add_parser(
|
||||
'activate', aliases=['workon', 'enter'],
|
||||
help='Activate virtual environment'
|
||||
)
|
||||
activate.add_argument('name', metavar='ENV',
|
||||
help='The environment to activate')
|
||||
subparsers.add_parser('deactivate', aliases=['exit'], help='Deactivate current virtual environment')
|
||||
subparsers.add_parser('list', aliases=['ls'], help='List all available environments')
|
||||
remove = subparsers.add_parser('remove', aliases=['rm', 'delete', 'del'], help='Remove virtual environment')
|
||||
remove.add_argument('names', metavar='ENV', nargs='+',
|
||||
help='The environments to remove')
|
||||
subparsers.add_parser('help', help='Show this help message')
|
||||
return parser
|
||||
|
||||
parser = _lazyasd.LazyObject(parser, locals(), 'parser')
|
||||
|
||||
aliases = {
|
||||
'create': 'new',
|
||||
'workon': 'activate',
|
||||
'enter': 'activate',
|
||||
'exit': 'deactivate',
|
||||
'ls': 'list',
|
||||
'rm': 'remove',
|
||||
'delete': 'remove',
|
||||
'del': 'remove',
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
"""Ensure that $VIRTUALENV_HOME is defined and declare the available vox commands"""
|
||||
|
||||
self.vox = _voxapi.Vox()
|
||||
|
||||
self.commands = {
|
||||
('new',): self.create_env,
|
||||
('activate', 'workon', 'enter'): self.activate_env,
|
||||
('deactivate', 'exit'): self.deactivate_env,
|
||||
('list', 'ls'): self.list_envs,
|
||||
('remove', 'rm', 'delete', 'del'): self.remove_envs,
|
||||
('help', '-h', '--help'): self.show_help
|
||||
}
|
||||
|
||||
def __call__(self, args, stdin=None):
|
||||
"""Call the right handler method for a given command."""
|
||||
|
||||
if not args:
|
||||
self.show_help()
|
||||
return None
|
||||
args = self.parser.parse_args(args)
|
||||
cmd = self.aliases.get(args.command, args.command)
|
||||
if cmd is None:
|
||||
self.parser.print_usage()
|
||||
else:
|
||||
getattr(self, 'cmd_'+cmd)(args, stdin)
|
||||
|
||||
command_name, params = args[0], args[1:]
|
||||
|
||||
try:
|
||||
command = [
|
||||
self.commands[aliases] for aliases in self.commands
|
||||
if command_name in aliases
|
||||
][0]
|
||||
|
||||
command(*params)
|
||||
|
||||
except IndexError:
|
||||
print('Command "%s" doesn\'t exist.\n' % command_name)
|
||||
self.print_commands()
|
||||
|
||||
def create_env(self, name):
|
||||
def cmd_new(self, args, stdin=None):
|
||||
"""Create a virtual environment in $VIRTUALENV_HOME with python3's ``venv``.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Virtual environment name
|
||||
"""
|
||||
print('Creating environment...')
|
||||
self.vox.create(name)
|
||||
self.vox.create(args.name)
|
||||
msg = 'Environment {0!r} created. Activate it with "vox activate {0}".\n'
|
||||
print(msg.format(name))
|
||||
print(msg.format(args.name))
|
||||
|
||||
def activate_env(self, name):
|
||||
def cmd_activate(self, args, stdin=None):
|
||||
"""Activate a virtual environment.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Virtual environment name
|
||||
"""
|
||||
|
||||
try:
|
||||
self.vox.activate(name)
|
||||
self.vox.activate(args.name)
|
||||
except KeyError:
|
||||
print('This environment doesn\'t exist. Create it with "vox new %s".\n' % name, file=_sys.stderr)
|
||||
return None
|
||||
else:
|
||||
print('Activated "%s".\n' % name)
|
||||
print('Activated "%s".\n' % args.name)
|
||||
|
||||
def deactivate_env(self):
|
||||
def cmd_deactivate(self, args, stdin=None):
|
||||
"""Deactive the active virtual environment."""
|
||||
|
||||
if self.vox.active() is None:
|
||||
|
@ -81,11 +112,11 @@ class _VoxHandler:
|
|||
env_name = self.vox.deactivate()
|
||||
print('Deactivated "%s".\n' % env_name)
|
||||
|
||||
def list_envs(self):
|
||||
def cmd_list(self, args, stdin=None):
|
||||
"""List available virtual environments."""
|
||||
|
||||
try:
|
||||
envs = list(self.vox.keys())
|
||||
envs = sorted(self.vox.keys())
|
||||
except PermissionError:
|
||||
print('No permissions on VIRTUALENV_HOME')
|
||||
return None
|
||||
|
@ -97,15 +128,10 @@ class _VoxHandler:
|
|||
print('Available environments:')
|
||||
print('\n'.join(envs))
|
||||
|
||||
def remove_envs(self, *names):
|
||||
def cmd_remove(self, args, stdin=None):
|
||||
"""Remove virtual environments.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
names : list
|
||||
list of virtual environment names
|
||||
"""
|
||||
for name in names:
|
||||
for name in args.names:
|
||||
try:
|
||||
del self.vox[name]
|
||||
except _voxapi.EnvironmentInUse:
|
||||
|
@ -116,35 +142,8 @@ class _VoxHandler:
|
|||
print('Environment "%s" removed.' % name)
|
||||
print()
|
||||
|
||||
def show_help(self):
|
||||
"""Show help."""
|
||||
|
||||
print(self.__doc__, '\n')
|
||||
self.print_commands()
|
||||
|
||||
@staticmethod
|
||||
def print_commands():
|
||||
"""Print available vox commands."""
|
||||
|
||||
print("""Available commands:
|
||||
vox new <env>
|
||||
Create new virtual environment in $VIRTUALENV_HOME
|
||||
|
||||
vox activate (workon, enter) <env>
|
||||
Activate virtual environment
|
||||
|
||||
vox deactivate (exit)
|
||||
Deactivate current virtual environment
|
||||
|
||||
vox list (ls)
|
||||
List all available environments
|
||||
|
||||
vox remove (rm, delete, del) <env> <env2> ...
|
||||
Remove virtual environments
|
||||
|
||||
vox help (-h, --help)
|
||||
Show help
|
||||
""")
|
||||
def cmd_help(self, args, stdin=None):
|
||||
self.parser.print_help()
|
||||
|
||||
@classmethod
|
||||
def handle(cls, args, stdin=None):
|
||||
|
|
Loading…
Add table
Reference in a new issue