Xonsh Projects¶
Bam! Suppose you want to get beyond scripting and write a whole library, utility, or other big project in xonsh. Here is how you do that. Spoiler alert: it is easy, powerful, and fun!
Overview¶
Xonsh is fully interoperable with Python. Writing a xonsh library is very similar to writing a Python library, using all of the same tooling and infrastructure for packaging pure Python code.
Structure¶
Xonsh modules are written in xonsh files (*.xsh), side-by-side with Python files
(*.py). Suppose we have a package called mypkg which uses xonsh files.
Here is a sample file system layout would be:
|- mypkg/
|- __init__.py # a regular package with an init file
|- other.py # not a xonsh file
|- show.py # "mypkg.show", full module name
|- tell.xsh # "mypkg.tell", full module name
|- subpkg/
|- __init__.py
|- a.py # "mypkg.subpkg.a", full module name
|- b.xsh # "mypkg.subpkg.b", full module name
To ensure that these files are installed, you need to provide the
appropriate information in setup.py file for your project.
For the above structure, this looks like the following.
setup.py:
setup(
packages=['mypkg', 'mypkg.subpkg'],
package_dir={'mypkg': 'mypkg', 'mypkg.subpkg': 'mypkg/subpkg'},
package_data={'mypkg': ['*.xsh'], 'mypkg.subpkg': ['*.xsh']},
)
With this, the xonsh code will be installed and included in any source distribution you create!
Setting up xonsh sessions¶
Xonsh code requires a XonshSession to exist as builtins.__xonsh__ and for
be that object to be setup correctly. This can be quite a bit of work and
the exact setup depends on the execution context. To simplify the process
of constructing the session properly, xonsh provides the xonsh.main.setup()
function specifically for use in 3rd party packages.
While xonsh.main.setup() is safely re-entrant, it is a good idea to add the following
snippet to the root-level __init__.py of your project. With the mypkg example
above, the session setup is as follows:
mypkg/__init__.py
from xonsh.main import setup
setup()
del setup
Enjoy!
Formatting xonsh code¶
Xonsh ships a built-in formatter, available as the xonsh format
subcommand. It re-emits the source with normalized indentation,
spacing and blank-line rules while preserving every xonsh-specific
construct.
Format a single file in place:
@ xonsh format mypkg/tell.xsh
Format several files at once — every path that needs reformatting is rewritten on disk, and a status line is printed for each:
@ xonsh format mypkg/tell.xsh mypkg/subpkg/b.xsh
Read from standard input and write the result to standard output — the canonical way to produce a separate output file or to plug the formatter into an editor / pipeline:
@ xonsh format - < 1.xsh > 2.xsh
Useful flags:
--check— don’t touch any files. Exits with code1if at least one file would be reformatted,0otherwise. Handy for CI.--diff— print a unified diff for each file that would change, again without touching disk.-q/--quiet— suppress per-file status messages on stderr.
For example, to fail a CI job when any file needs reformatting:
@ xonsh format --check mypkg