Lab/py control file (#4420)

* feat: use python's compile for rc.py

* docs: add news item

* docs: update news item

* test: add tests for py-control files

* fix: rst news item

* docs: update news item

* docs: add sample rc.py
This commit is contained in:
Noorhteen Raja NJ 2021-08-19 22:10:22 +05:30 committed by GitHub
parent e59ac28d7d
commit d7dbfa9011
Failed to generate hash of commit
6 changed files with 93 additions and 3 deletions

23
docs/xonshrc.py Normal file
View file

@ -0,0 +1,23 @@
from xonsh.built_ins import XSH
env = XSH.env
# adjust some paths
env["PATH"].append("/home/scopatz/sandbox/bin")
env["LD_LIBRARY_PATH"] = ["/home/scopatz/.local/lib", "/home/scopatz/miniconda3/lib"]
# alias to quit AwesomeWM from the terminal
def _quit_awesome(args, stdin=None):
print("awesome python code")
XSH.aliases["qa"] = _quit_awesome
# setting aliases as list are faster since they don't involve parser.
XSH.aliases["gc"] = ["git", "commit"]
# some customization options, see https://xon.sh/envvars.html for details
env["MULTILINE_PROMPT"] = "`·.,¸,.·*¯`·.,¸,.·*¯"
env["XONSH_SHOW_TRACEBACK"] = True
env["XONSH_STORE_STDOUT"] = True
env["XONSH_HISTORY_MATCH_ANYWHERE"] = True
env["COMPLETIONS_CONFIRM"] = True
env["XONSH_AUTOPAIR"] = True

View file

@ -1,7 +1,9 @@
Run Control File Run Control File
========================= =========================
Xonsh allows you to customize your shell behavior with run control files, called "xonshrc" files. Xonsh allows you to customize your shell behavior with run control files, called "xonshrc" files.
These files are written in the xonsh language (a superset of Python) and are executed exactly once at startup. These files are written either in the Xonsh language (a superset of Python) or in Python and are executed
exactly once at startup.
The control file usually contains: The control file usually contains:
* Assignment statements setting `environment variables <envvars.html>`_. This includes standard OS environment variables that affect other programs and many that Xonsh uses for itself. * Assignment statements setting `environment variables <envvars.html>`_. This includes standard OS environment variables that affect other programs and many that Xonsh uses for itself.
@ -19,7 +21,7 @@ The options set per user override settings in the system-wide control file.
Xonsh also supports configuration directories, from which all ``.xsh`` files will be sourced in order. Xonsh also supports configuration directories, from which all ``.xsh`` files will be sourced in order.
This allows for drop-in configuration where your configuration can be split across scripts and common This allows for drop-in configuration where your configuration can be split across scripts and common
and local configuration more easily separated. By default, if the directory ``~/.config/xonsh/rc.d`` and local configuration more easily separated. By default, if the directory ``~/.config/xonsh/rc.d``
exists, any ``xsh`` files within will be sourced at startup. exists, any ``*.xsh`` files within will be sourced at startup.
Xonsh provides 2 wizards to create your own "xonshrc". ``xonfig web`` provides basic settings, and ``xonfig wizard`` Xonsh provides 2 wizards to create your own "xonshrc". ``xonfig web`` provides basic settings, and ``xonfig wizard``
steps you through all the available options. steps you through all the available options.
@ -167,6 +169,18 @@ The following is a real-world example of such a file.
:code: xonsh :code: xonsh
Real world sample rc.py
-------------------------
The following is a real-world example of such a file.
This can be set by ``env XONSHRC=rc.py xonsh`` or ``xonsh --rc=rc.py``
:download:`Download rc.py <xonshrc.py>`
.. include:: xonshrc.py
:code: xonsh
Snippets for xonshrc Snippets for xonshrc
-------------------- --------------------

24
news/py-rc-files.rst Normal file
View file

@ -0,0 +1,24 @@
**Added:**
* Pure Python control files are now supported when named ``*.py``.
Using python files may lower the startup time by a bit.
**Changed:**
* <news item>
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* <news item>
**Security:**
* <news item>

View file

@ -5,6 +5,7 @@ flake8-docstrings
flake8-bugbear flake8-bugbear
restructuredtext_lint restructuredtext_lint
pytest-cov pytest-cov
pytest-mock
pytest-timeout pytest-timeout
pytest-subprocess pytest-subprocess
prompt-toolkit>=3.0 prompt-toolkit>=3.0

View file

@ -12,7 +12,7 @@ import sys
import xonsh.main import xonsh.main
from xonsh.main import XonshMode from xonsh.main import XonshMode
import pytest import pytest
from tools import ON_WINDOWS, TEST_DIR, VER_FULL, skip_if_on_windows from tools import ON_WINDOWS, TEST_DIR, skip_if_on_windows
def Shell(*args, **kwargs): def Shell(*args, **kwargs):
@ -90,6 +90,30 @@ def test_rc_with_modules(shell, tmpdir, monkeypatch, capsys, xession):
assert tmpdir.strpath not in sys.path assert tmpdir.strpath not in sys.path
def test_python_rc(shell, tmpdir, monkeypatch, capsys, xession, mocker):
"""Test that python based control files are executed using Python's parser"""
monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
monkeypatch.setitem(os.environ, "XONSH_CACHE_SCRIPTS", "False")
# spy on xonsh's compile method
spy = mocker.spy(xession.execer, "compile")
rc = tmpdir.join("rc.py")
rc.write("print('Hello World!')")
xonsh.main.premain(["--rc", rc.strpath])
assert rc.strpath in xession.rc_files
stdout, stderr = capsys.readouterr()
assert "Hello World!" in stdout
assert len(stderr) == 0
# Check that the temporary rc's folder is not left behind on the path
assert tmpdir.strpath not in sys.path
assert spy.called == False
def test_rcdir(shell, tmpdir, monkeypatch, capsys): def test_rcdir(shell, tmpdir, monkeypatch, capsys):
""" """
Test that files are loaded from an rcdir, after a normal rc file, Test that files are loaded from an rcdir, after a normal rc file,

View file

@ -105,6 +105,10 @@ def compile_code(filename, code, execer, glb, loc, mode):
""" """
Wrapper for ``execer.compile`` to compile the given code Wrapper for ``execer.compile`` to compile the given code
""" """
if filename.endswith(".py") and mode == "exec":
return compile(code, filename, mode)
if not code.endswith("\n"): if not code.endswith("\n"):
code += "\n" code += "\n"
old_filename = execer.filename old_filename = execer.filename