Skip to content

Commit

Permalink
tests for custom class attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
davidism committed Aug 9, 2020
1 parent c465912 commit aff5168
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 5 deletions.
21 changes: 16 additions & 5 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,22 @@ Unreleased
converted to string. :pr:`1146`
- ``edit(require_save=True)`` will detect saves for editors that exit
very fast on filesystems with 1 second resolution. :pr:`1050`
- ``Command`` has a ``context_class`` attribute to quickly customize
the ``Context``. ``Context`` has a ``formatter_class`` attribute to
quickly customize the ``HelpFormatter``. ``Context.invoke`` creates
child contexts of the same type as itself. Core objects use
``super()`` consistently. :pr:`938`
- New class attributes make it easier to use custom core objects
throughout an entire application. :pr:`938`

- ``Command.context_class`` controls the context created when
running the command.
- ``Context.invoke`` creates new contexts of the same type, so a
custom type will persist to invoked subcommands.
- ``Context.formatter_class`` controls the formatter used to
generate help and usage.
- ``Group.command_class`` changes the default type for
subcommands with ``@group.command()``.
- ``Group.group_class`` changes the default type for subgroups
with ``@group.group()``. Setting it to ``type`` will create
subgroups of the same type as the group itself.
- Core objects use ``super()`` consistently for better support of
subclassing.


Version 7.1.2
Expand Down
112 changes: 112 additions & 0 deletions tests/test_custom_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import click


def test_command_context_class():
"""A command with a custom ``context_class`` should produce a
context using that type.
"""

class CustomContext(click.Context):
pass

class CustomCommand(click.Command):
context_class = CustomContext

command = CustomCommand("test")
context = command.make_context("test", [])
assert isinstance(context, CustomContext)


def test_context_invoke_type(runner):
"""A command invoked from a custom context should have a new
context with the same type.
"""

class CustomContext(click.Context):
pass

class CustomCommand(click.Command):
context_class = CustomContext

@click.command()
@click.argument("first_id", type=int)
@click.pass_context
def second(ctx, first_id):
assert isinstance(ctx, CustomContext)
assert id(ctx) != first_id

@click.command(cls=CustomCommand)
@click.pass_context
def first(ctx):
assert isinstance(ctx, CustomContext)
ctx.invoke(second, first_id=id(ctx))

assert not runner.invoke(first).exception


def test_context_formatter_class():
"""A context with a custom ``formatter_class`` should format help
using that type.
"""

class CustomFormatter(click.HelpFormatter):
def write_heading(self, heading):
heading = click.style(heading, fg="yellow")
return super().write_heading(heading)

class CustomContext(click.Context):
formatter_class = CustomFormatter

context = CustomContext(
click.Command("test", params=[click.Option(["--value"])]), color=True
)
assert "\x1b[33mOptions\x1b[0m:" in context.get_help()


def test_group_command_class(runner):
"""A group with a custom ``command_class`` should create subcommands
of that type by default.
"""

class CustomCommand(click.Command):
pass

class CustomGroup(click.Group):
command_class = CustomCommand

group = CustomGroup()
subcommand = group.command()(lambda: None)
assert type(subcommand) is CustomCommand
subcommand = group.command(cls=click.Command)(lambda: None)
assert type(subcommand) is click.Command


def test_group_group_class(runner):
"""A group with a custom ``group_class`` should create subgroups
of that type by default.
"""

class CustomSubGroup(click.Group):
pass

class CustomGroup(click.Group):
group_class = CustomSubGroup

group = CustomGroup()
subgroup = group.group()(lambda: None)
assert type(subgroup) is CustomSubGroup
subgroup = group.command(cls=click.Group)(lambda: None)
assert type(subgroup) is click.Group


def test_group_group_class_self(runner):
"""A group with ``group_class = type`` should create subgroups of
the same type as itself.
"""

class CustomGroup(click.Group):
group_class = type

group = CustomGroup()
subgroup = group.group()(lambda: None)
assert type(subgroup) is CustomGroup

0 comments on commit aff5168

Please sign in to comment.