From 3dd51fafae18f0002eec8eb051aa354adaf6bb83 Mon Sep 17 00:00:00 2001 From: yuvipanda Date: Sun, 12 Aug 2018 17:02:24 -0700 Subject: [PATCH] Add docs on writing & using plugins --- docs/contributing/plugins.rst | 119 +++++++++++++++++++++++++++ docs/index.rst | 1 + docs/topic/customizing-installer.rst | 29 +++++++ 3 files changed, 149 insertions(+) create mode 100644 docs/contributing/plugins.rst diff --git a/docs/contributing/plugins.rst b/docs/contributing/plugins.rst new file mode 100644 index 000000000..97e4eaac3 --- /dev/null +++ b/docs/contributing/plugins.rst @@ -0,0 +1,119 @@ +.. _contributing/plugins: + +============ +TLJH Plugins +============ + +TLJH plugins are the official way to make customized 'spins' or 'stacks' +with TLJH as the base. For example, the earth sciences community can make +a plugin that installs commonly used packages, set up authentication +and pre-download useful datasets. The mybinder.org community can +make a plugin that gives you a single-node, single-repository mybinder.org. +Plugins are very powerful, so the possibilities are endless. + +Design +====== + +`pluggy `_ is used to implement +plugin functionality. TLJH exposes specific **hooks** that your plugin +can provide implementations for. This allows us to have specific hook +points in the application that can be explicitly extended by plugins, +balancing the need to change TLJH internals in the future with the +stability required for a good plugin ecosystem. + +Writing a simple plugins +======================== + +We shall try to write a simple plugin that installs a few libraries, +and use it to explain how the plugin mechanism works. We shall call +this plugin ``tljh-simple``. + +Plugin directory layout +----------------------- + +We recommend creating a new git repo for your plugin. Plugins are +normal python packages - however, since they are usually simpler, +we recommend they live in one file. + +For ``tljh-simple``, the repository's structure should look like: + +.. code-block:: none + + tljh_simple: + - tljh_simple.py + - setup.py + - README.md + - LICENSE + +The ``README.md`` (or ``README.rst`` file) contains human readable +information about what your plugin does for your users. ``LICENSE`` +specifies the license used by your plugin - we recommend the +3-Clause BSD License, since that is what is used by TLJH itself. + +``setup.py`` - metadata & registration +-------------------------------------- + +``setup.py`` marks this as a python package, and contains metadata +about the package itself. It should look something like: + +.. code-block:: python + + from setuptools import setup + + setup( + name="tljh-simple", + author="YuviPanda", + version="0.1", + license="3-clause BSD", + url='https://github.com/yuvipanda/tljh-simple', + entry_points={"tljh": ["simple = tljh_simple"]}, + py_modules=["tljh_simple"], + ) + + +This is a mostly standard ``setup.py`` file. ``entry_points={"tljh": ["simple = tljh_simple]}`` +'registers' the module ``tljh_simple`` (in file ``tljh_simple.py``) with TLJH as a plugin. + +``tljh_simple.py`` - implementation +----------------------------------- + +In ``tljh_simple.py``, you provide implementations for whichever hooks +you want to extend. + +A hook implementation is a function that has the following characteristics: + +#. Has same name as the hook +#. Accepts some or all of the parameters defined for the hook +#. Is decorated with the ``hookimpl`` decorator function, imported from + ``tljh.hooks``. + +The current list of available hooks and when they are called can be +seen in ```tljh/hooks.py`` `_ +in the source repository. + + +This example provides an implementation for the ``tljh_extra_user_conda_packages`` +hook, which can return a list of conda packages that'll be installed in users' +environment from conda-forge. + +.. code-block:: python + + from tljh.hooks import hookimpl + + @hookimpl + def tljh_extra_user_conda_packages(): + return [ + 'xarray', + 'iris', + 'dask', + ] + + +Publishing plugins +================== + +Plugins are python packages and should be published on PyPI. Users +can also install them directly from GitHub - although this is +not good long term practice. + +The python package should be named ``tljh-``. \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index a03589e3e..b84366bfa 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -127,3 +127,4 @@ to people contributing in various ways. contributing/code-review contributing/dev-setup contributing/tests + contributing/plugins \ No newline at end of file diff --git a/docs/topic/customizing-installer.rst b/docs/topic/customizing-installer.rst index 30f1f9902..359baea66 100644 --- a/docs/topic/customizing-installer.rst +++ b/docs/topic/customizing-installer.rst @@ -56,3 +56,32 @@ will fail. When pointing to a file on GitHub, make sure to use the 'Raw' version. It should point to ``raw.githubusercontent.com``, not ``github.com``. + +Installing TLJH plugins +======================= + +The Littlest JupyterHub can install additional *plugins* that provide additional +features. They are most commonly used to install a particular *stack* - such as +the `PANGEO Stack `_ for earth sciences +research, a stack for a praticular class, etc. + +``--plugin `` installs and activates a plugin. You can pass it +however many times you want. Since plugins are distributed as python packages, +```` can be anything that can be passed to ``pip install`` - +``plugin-name-on-pypy==`` and ``git+https://github.com/user/repo@tag`` +are the most popular ones. Specifying a version or tag is highly recommended. + +For example, to install the PANGEO Plugin version 0.1 in your new TLJH install, +you would use: + +.. code-block:: bash + + curl https://raw.githubusercontent.com/jupyterhub/the-littlest-jupyterhub/master/bootstrap/bootstrap.py \ + | sudo python3 - \ + --plugin git+https://github.com/yuvipanda/tljh-pangeo@v0.1 + + +.. note:: + + Plugins are extremely powerful and can do a large number of arbitrary things. + Only install plugins you trust. \ No newline at end of file