Source code for pyangext.cli

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Extension for the pyang command line interface.

This module includes tools for augmenting ``PYANG_PLUGINPATH`` with
the location of auto-discovered pyang plugins.

Pyang do not use the ``setuptools`` to register plugins. Instead it requires
that the paths of all directories containing plugins to be present in the
``PYANG_PLUGINPATH`` environment variable.

``pyangext`` reads all entry points under ``yang.plugins``, detect the path
to the file that contains the function registered, and builds a list with
the containing directories.

In this sense, ``pyangext run`` command can be used as a bridge to
the ``pyang`` command, but using the auto-discovery feature.

Note:
    Including non pyang-plugin python files alongside pyang-plugins
    python files (in the same directory) will result in a pyang CLI crash.

    It is recommended that the function registered as entry-point follows
    the proprietary pyang plugin convention, or in other words:

    - it should be named ``pyang_plugin_init``
    - it should call ``pyang.plugin.register_plugin`` with an instance of
      ``pyang.plugin.PyangPlugin`` as argument.

See Also:
    https://pythonhosted.org/setuptools/setuptools.html#dynamic-discovery-of-services-and-plugins


Command Line Interface
======================

  Usage:
    ``pyangext [OPTIONS] COMMAND [ARGS]``

  Options:
    -h, --help             Show this message and exit.

    -v, --version          Show the version and exit.

    --path                 Prints the auto discovered plugin path.
                           Python packages that register an entry-point
                           inside ``yang.plugins`` will be auto-detected.

    --init, --export-path  Prints an export shell statement with the auto
                           discovered plugin path.

                           This may be used by shell script to configure
                           ``PYANG_PLUGINPATH`` environment variable.

                           Example: |example|

    --help                 Show this message and exit.

  Commands:
    :``call``: invoke pyang script with plugin path adjusted using
        auto-discovery.

.. |example| raw:: html

   <code><pre>eval $(pyangext --export-path)</pre></code>
"""
import sys
from os import environ
from os.path import pathsep
from subprocess import Popen
from textwrap import dedent

from six.moves import shlex_quote

import click

from . import __version__  # noqa
from .paths import expanded

__author__ = "Anderson Bravalheri"
__copyright__ = "Copyright (C) 2016 Anderson Bravalheri"
__license__ = "mozilla"


def _fixdoc(func):
    """Return a new text with the text wrapping in a function's docstring"""
    docstring = dedent(func.__doc__)
    lines = (' '.join(line.split()) for line in docstring.split('\n\n'))

    new_docstring = "\n".join(lines)

    return new_docstring


# click option callback



# click option callback
[docs]def export_path(ctx, _, value): """\ Prints an export shell statement with the auto discovered plugin path. This may be used by shell script to configure ``PYANG_PLUGINPATH`` environment variable. Example: :: eval $(pyangext --export-path) """ if not value or ctx.resilient_parsing: return click.echo( 'export PYANG_PLUGINPATH=' + shlex_quote(pathsep.join(expanded()))) ctx.exit()
@click.group() @click.help_option('-h', '--help') @click.version_option(__version__, '-v', '--version') @click.option( '--path', help=_fixdoc(print_path), is_flag=True, expose_value=False, callback=print_path) @click.option( '--init', '--export-path', help=_fixdoc(export_path), is_flag=True, expose_value=False, callback=export_path) def call(): """pyang + sensible extensions Includes self-registered pyang plugin auto-discovery """ pass @call.command( 'run', context_settings={'ignore_unknown_options': True}) @click.argument('args', nargs=-1, type=click.UNPROCESSED) def call_pyang(args): """invoke pyang script with plugin path adjusted using auto-discovery.""" environ['PYANG_PLUGINPATH'] = pathsep.join(expanded()) proc = Popen(['pyang'] + list(args), stdout=sys.stdout, stderr=sys.stderr) proc.wait() return proc.returncode