pax_global_header00006660000000000000000000000064135340736100014514gustar00rootroot0000000000000052 comment=b671ae5325d186fe5ea7abb584f15852a1e931aa click-default-group-1.2.2/000077500000000000000000000000001353407361000153575ustar00rootroot00000000000000click-default-group-1.2.2/.gitignore000066400000000000000000000012761353407361000173550ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *,cover # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ # PyBuilder target/ click-default-group-1.2.2/.travis.yml000066400000000000000000000012401353407361000174650ustar00rootroot00000000000000dist: xenial language: python sudo: false python: - "2.7" - "3.5" - "3.6" - "3.7" - "3.8-dev" - pypy - pypy3 env: - CLICK_VERSION=7.0 - CLICK_VERSION=6.7 - CLICK_VERSION=6.6 - CLICK_VERSION=6.4 - CLICK_VERSION=6.3 - CLICK_VERSION=6.2 - CLICK_VERSION=6.1 - CLICK_VERSION=6.0 - CLICK_VERSION=5.1 - CLICK_VERSION=5.0 - CLICK_VERSION=4.1 - CLICK_VERSION=4.0 install: - pip install click==$CLICK_VERSION - pip install -e . - pip install flake8 flake8-import-order pytest-cov coveralls script: - | # flake8 flake8 click_default_group.py test.py setup.py -v --show-source - | # pytest py.test -v --cov=click_default_group --cov-report=term-missing after_success: - coveralls click-default-group-1.2.2/LICENSE000066400000000000000000000027271353407361000163740ustar00rootroot00000000000000Copyright (c) 2015-2016, Heungsub Lee All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. click-default-group-1.2.2/README.md000066400000000000000000000030451353407361000166400ustar00rootroot00000000000000Click Default Group =================== `DefaultGroup` is a sub class of [`click.Group`](http://click.pocoo.org/6/api/#click.Group). But it invokes a default subcommand instead of showing a help message when a subcommand is not passed. [![Build Status](https://img.shields.io/travis/click-contrib/click-default-group.svg)](https://travis-ci.org/click-contrib/click-default-group) [![Coverage Status](https://img.shields.io/coveralls/click-contrib/click-default-group.svg)](https://coveralls.io/r/click-contrib/click-default-group) Usage ----- Define a default subcommand by `default=NAME`: ```python import click from click_default_group import DefaultGroup @click.group(cls=DefaultGroup, default='foo', default_if_no_args=True) def cli(): pass @cli.command() def foo(): click.echo('foo') @cli.command() def bar(): click.echo('bar') ``` Then you can invoke that without explicit subcommand name: ```console $ cli.py --help Usage: cli.py [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Command: foo* bar $ cli.py foo $ cli.py foo foo $ cli.py bar bar ``` Compatibility ------------- `click-default-group` is compatible with these Click versions: - Click-7.0 - Click-6.x - Click-5.1 - Click-5.0 - Click-4.1 - Click-4.0 See the [latest build status](https://travis-ci.org/click-contrib/click-default-group) at Travis CI. Licensing --------- Written by [Heungsub Lee], and distributed under the [BSD 3-Clause] license. [Heungsub Lee]: http://subl.ee/ [BSD 3-Clause]: http://opensource.org/licenses/BSD-3-Clause click-default-group-1.2.2/click_default_group.py000066400000000000000000000075261353407361000217500ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ click_default_group ~~~~~~~~~~~~~~~~~~~ Define a default subcommand by `default=True`: .. sourcecode:: python import click from click_default_group import DefaultGroup @click.group(cls=DefaultGroup, default_if_no_args=True) def cli(): pass @cli.command(default=True) def foo(): click.echo('foo') @cli.command() def bar(): click.echo('bar') Then you can invoke that without explicit subcommand name: .. sourcecode:: console $ cli.py --help Usage: cli.py [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Command: foo* bar $ cli.py foo $ cli.py foo foo $ cli.py bar bar """ import warnings import click __all__ = ['DefaultGroup'] __version__ = '1.2.2' class DefaultGroup(click.Group): """Invokes a subcommand marked with `default=True` if any subcommand not chosen. :param default_if_no_args: resolves to the default command if no arguments passed. """ def __init__(self, *args, **kwargs): # To resolve as the default command. if not kwargs.get('ignore_unknown_options', True): raise ValueError('Default group accepts unknown options') self.ignore_unknown_options = True self.default_cmd_name = kwargs.pop('default', None) self.default_if_no_args = kwargs.pop('default_if_no_args', False) super(DefaultGroup, self).__init__(*args, **kwargs) def set_default_command(self, command): """Sets a command function as the default command.""" cmd_name = command.name self.add_command(command) self.default_cmd_name = cmd_name def parse_args(self, ctx, args): if not args and self.default_if_no_args: args.insert(0, self.default_cmd_name) return super(DefaultGroup, self).parse_args(ctx, args) def get_command(self, ctx, cmd_name): if cmd_name not in self.commands: # No command name matched. ctx.arg0 = cmd_name cmd_name = self.default_cmd_name return super(DefaultGroup, self).get_command(ctx, cmd_name) def resolve_command(self, ctx, args): base = super(DefaultGroup, self) cmd_name, cmd, args = base.resolve_command(ctx, args) if hasattr(ctx, 'arg0'): args.insert(0, ctx.arg0) cmd_name = cmd.name return cmd_name, cmd, args def format_commands(self, ctx, formatter): formatter = DefaultCommandFormatter(self, formatter, mark='*') return super(DefaultGroup, self).format_commands(ctx, formatter) def command(self, *args, **kwargs): default = kwargs.pop('default', False) decorator = super(DefaultGroup, self).command(*args, **kwargs) if not default: return decorator warnings.warn('Use default param of DefaultGroup or ' 'set_default_command() instead', DeprecationWarning) def _decorator(f): cmd = decorator(f) self.set_default_command(cmd) return cmd return _decorator class DefaultCommandFormatter(object): """Wraps a formatter to mark a default command.""" def __init__(self, group, formatter, mark='*'): self.group = group self.formatter = formatter self.mark = mark def __getattr__(self, attr): return getattr(self.formatter, attr) def write_dl(self, rows, *args, **kwargs): rows_ = [] for cmd_name, help in rows: if cmd_name == self.group.default_cmd_name: rows_.insert(0, (cmd_name + self.mark, help)) else: rows_.append((cmd_name, help)) return self.formatter.write_dl(rows_, *args, **kwargs) click-default-group-1.2.2/setup.cfg000066400000000000000000000002101353407361000171710ustar00rootroot00000000000000[flake8] ignore = E301 import-order-style = google application-import-names = click_default_group [tool:pytest] python_files = test.py click-default-group-1.2.2/setup.py000066400000000000000000000031751353407361000170770ustar00rootroot00000000000000# -*- coding: utf-8 -*- import os import re from setuptools import setup from setuptools.command.test import test with open('click_default_group.py') as f: version = re.search(r'__version__\s*=\s*\'(.+?)\'', f.read()).group(1) assert version with open(os.path.join(os.path.dirname(__file__), 'README.md')) as f: long_description = f.read() # Use pytest instead. def run_tests(self): raise SystemExit(__import__('pytest').main(['-v'])) test.run_tests = run_tests setup( name='click-default-group', version=version, license='BSD', author='Heungsub Lee', author_email='sub@subl.ee', description=('Extends click.Group to invoke a ' 'command without explicit subcommand name'), url='https://github.com/sublee/click-default-group/', long_description=long_description, long_description_content_type='text/markdown', platforms='any', py_modules=['click_default_group'], classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: Public Domain', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', ], install_requires=['click'], tests_require=['pytest'], test_suite='...', ) click-default-group-1.2.2/test.py000066400000000000000000000036671353407361000167240ustar00rootroot00000000000000# -*- coding: utf-8 -*- import click from click.testing import CliRunner import pytest from click_default_group import DefaultGroup @click.group(cls=DefaultGroup, default='foo', invoke_without_command=True) @click.option('--group-only', is_flag=True) def cli(group_only): # Called if invoke_without_command=True. if group_only: click.echo('--group-only passed.') @cli.command() @click.option('--foo', default='foo') def foo(foo): click.echo(foo) @cli.command() def bar(): click.echo('bar') r = CliRunner() def test_default_command_with_arguments(): assert r.invoke(cli, ['--foo', 'foooo']).output == 'foooo\n' assert 'no such option' in r.invoke(cli, ['-x']).output def test_group_arguments(): assert r.invoke(cli, ['--group-only']).output == '--group-only passed.\n' def test_explicit_command(): assert r.invoke(cli, ['foo']).output == 'foo\n' assert r.invoke(cli, ['bar']).output == 'bar\n' def test_set_ignore_unknown_options_to_false(): with pytest.raises(ValueError): DefaultGroup(ignore_unknown_options=False) def test_default_if_no_args(): cli = DefaultGroup() @cli.command() @click.argument('foo', required=False) @click.option('--bar') def foobar(foo, bar): click.echo(foo) click.echo(bar) cli.set_default_command(foobar) assert r.invoke(cli, []).output.startswith('Usage:') assert r.invoke(cli, ['foo']).output == 'foo\n\n' assert r.invoke(cli, ['foo', '--bar', 'bar']).output == 'foo\nbar\n' cli.default_if_no_args = True assert r.invoke(cli, []).output == '\n\n' def test_format_commands(): help = r.invoke(cli, ['--help']).output assert 'foo*' in help assert 'bar*' not in help assert 'bar' in help def test_deprecation(): # @cli.command(default=True) has been deprecated since 1.2. cli = DefaultGroup() pytest.deprecated_call(cli.command, default=True) if __name__ == '__main__': cli()