diff --git a/docs/guides.rst b/docs/guides.rst index 975ec35eb..3cb5f587b 100644 --- a/docs/guides.rst +++ b/docs/guides.rst @@ -10,6 +10,7 @@ Guides tutorial_hist tutorial_macros tutorial_xontrib + tutorial_xonsh_projects tutorial_events tutorial_completers tutorial_history_backend diff --git a/docs/tutorial_xonsh_projects.rst b/docs/tutorial_xonsh_projects.rst new file mode 100644 index 000000000..ecd560f7d --- /dev/null +++ b/docs/tutorial_xonsh_projects.rst @@ -0,0 +1,67 @@ +.. _tutorial_xonsh_projects: + +************************************ +Tutorial: 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`` + +.. code-block:: python + + from xonsh.main import setup + setup() + del setup + +Enjoy! diff --git a/xonsh/main.py b/xonsh/main.py index ae7c593d5..7f39c863e 100644 --- a/xonsh/main.py +++ b/xonsh/main.py @@ -487,10 +487,16 @@ def setup( threadable_predictors=(), ): """Starts up a new xonsh shell. Calling this in function in another - packages __init__.py will allow xonsh to be fully used in the + packages ``__init__.py`` will allow xonsh to be fully used in the package in headless or headed mode. This function is primarily indended to make starting up xonsh for 3rd party packages easier. + Here is example of using this at the top of an ``__init__.py``:: + + from xonsh.main import setup + setup() + del setup + Parameters ---------- ctx : dict-like or None, optional