Skip to content

Commit 26087f2

Browse files
committed
fix #167
1 parent c0849d0 commit 26087f2

File tree

7 files changed

+120
-10
lines changed

7 files changed

+120
-10
lines changed

django_typer/management/__init__.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2480,11 +2480,15 @@ class OutputWrapper(BaseOutputWrapper):
24802480
returned from command functions.
24812481
"""
24822482

2483+
disable: bool = False
2484+
24832485
def write(self, msg="", style_func=None, ending=None):
24842486
"""
24852487
If the message is not a string, first cast it before invoking the base
24862488
class write method.
24872489
"""
2490+
if self.disable:
2491+
return
24882492
if not isinstance(msg, str):
24892493
msg = str(msg)
24902494
return super().write(msg=msg, style_func=style_func, ending=ending)
@@ -2495,6 +2499,26 @@ def flush(self):
24952499
super().flush()
24962500

24972501

2502+
class _CommandResult:
2503+
"""
2504+
A container for result objects - we use this to make TyperCommand.print_result with
2505+
minimal impact to BaseCommand.
2506+
"""
2507+
2508+
result: t.Any
2509+
print_result: bool
2510+
2511+
def __init__(self, result, print_result):
2512+
self.result = result
2513+
self.print_result = print_result
2514+
2515+
def __str__(self):
2516+
return str(self.result)
2517+
2518+
def __bool__(self):
2519+
return self.print_result and bool(self.result)
2520+
2521+
24982522
class TyperCommand(BaseCommand, metaclass=TyperCommandMeta):
24992523
"""
25002524
An extension of BaseCommand_ that uses the Typer_ library to parse
@@ -2636,6 +2660,10 @@ def command2(self, option: t.Optional[str] = None):
26362660
no_color: bool = False
26372661
force_color: bool = False
26382662
skip_checks: bool = False
2663+
2664+
print_result: bool = True
2665+
"""Turn on/off automatic write to stdout of results returned by command"""
2666+
26392667
_handle: t.Callable[..., t.Any]
26402668
_traceback: bool = False
26412669
_help_kwarg: t.Optional[str] = Default(None)
@@ -3248,9 +3276,10 @@ def _run(self, *args, **options):
32483276
):
32493277
# result callbacks are not called on singular commands by click/typer
32503278
# we do that here to keep our interface consistent
3251-
return self.typer_app.info.result_callback(
3279+
result = self.typer_app.info.result_callback(
32523280
result, **options, _command=self
32533281
)
3282+
self.stdout.disable = not self.print_result
32543283
return result
32553284

32563285
def run_from_argv(self, argv):

doc/source/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ v3.0.0 (202X-XX-XX)
1010
* Implemented `Completer for media files. <https://github.com/django-commons/django-typer/issues/175>`_
1111
* Implemented `Completer for static files. <https://github.com/django-commons/django-typer/issues/174>`_
1212
* Fixed `Completions before the end of the typed command string do not work. <https://github.com/django-commons/django-typer/issues/168>`_
13+
* Implemented `Add print_return class field to enable/disable result printing <https://github.com/django-commons/django-typer/issues/167>`_
1314
* BREAKING `Default rich traceback should not show locals - its too much information. <https://github.com/django-commons/django-typer/issues/166>`_
1415
* Implemented `path completers should be configurable with a root directory other than cwd <https://github.com/django-commons/django-typer/issues/165>`_
1516
* Implemented `Migrate pyproject.toml to poetry 2 and portable project specifiers. <https://github.com/django-commons/django-typer/issues/164>_`

doc/source/howto.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,3 +849,31 @@ streams:
849849
.. literalinclude:: ../../tests/apps/howto/management/commands/printing_typer.py
850850
:language: python
851851
:linenos:
852+
853+
854+
Toggle on/off result printing
855+
-----------------------------
856+
857+
Django's BaseCommand_ will print any truthy values returned from the handle() method. This may not
858+
always be desired behavior. By default :class:`~django_typer.management.TyperCommand` will do the
859+
same, but you may toggle this behavior off by setting the class field ``print_result`` to False.
860+
861+
862+
.. tabs::
863+
864+
.. tab:: Django-style
865+
866+
.. literalinclude:: ../../tests/apps/howto/management/commands/print_result.py
867+
:language: python
868+
:linenos:
869+
870+
.. tab:: Typer-style
871+
872+
.. literalinclude:: ../../tests/apps/howto/management/commands/print_result_typer.py
873+
:language: python
874+
:linenos:
875+
876+
.. warning::
877+
878+
We may switch the default behavior to not print in the future, so if you want guaranteed forward
879+
compatible behavior you should set this field.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from django_typer.management import TyperCommand
2+
3+
4+
class Command(TyperCommand):
5+
print_result = False
6+
7+
def handle(self):
8+
return "This will not be printed"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from django_typer.management import Typer
2+
3+
app = Typer()
4+
5+
app.django_command.print_result = False
6+
7+
8+
@app.command()
9+
def handle():
10+
return "This will not be printed"

tests/test_examples.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -401,15 +401,20 @@ def test_hierarchy(self):
401401
"multiply",
402402
"--help",
403403
)[0].strip()
404-
self.assertGreater(
405-
similarity(
406-
observed_help,
407-
hierarchy_math_multiply_help
408-
if rich_installed
409-
else hierarchy_math_multiply_help_no_rich,
410-
),
411-
0.99,
412-
)
404+
try:
405+
self.assertGreater(
406+
similarity(
407+
observed_help,
408+
hierarchy_math_multiply_help
409+
if rich_installed
410+
else hierarchy_math_multiply_help_no_rich,
411+
),
412+
0.99,
413+
)
414+
except AssertionError:
415+
import ipdb
416+
417+
ipdb.set_trace()
413418

414419
self.assertEqual(
415420
run_command(

tests/test_howto.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44
from django.core.management import call_command
55
from django.test import TestCase, override_settings
6+
from contextlib import redirect_stdout
67

78
from django_typer.management import TyperCommand, get_command
89
from tests.utils import rich_installed, run_command, similarity
@@ -498,3 +499,31 @@ def test_howto_finalizer_obj(self):
498499

499500
class TestFinalizerGroupTyperExtHowto(TestFinalizerGroupHowto):
500501
command = "finalize_group_typer_ext"
502+
503+
504+
@override_settings(INSTALLED_APPS=["tests.apps.howto"])
505+
class TestPrintResultHowTo(TestCase):
506+
command = "print_result"
507+
508+
def test_howto_print_result_run(self):
509+
self.assertEqual(
510+
run_command(self.command, "--settings", "tests.settings.howto")[0].strip(),
511+
"",
512+
)
513+
514+
def test_howto_print_result_call(self):
515+
output = StringIO()
516+
with redirect_stdout(output):
517+
self.assertEqual(call_command(self.command), "This will not be printed")
518+
self.assertEqual(output.getvalue().strip(), "")
519+
520+
def test_howto_print_result_obj(self):
521+
command = get_command(self.command)
522+
self.assertEqual(
523+
command.handle(),
524+
"This will not be printed",
525+
)
526+
527+
528+
class TestPrintResultTyperHowTo(TestPrintResultHowTo):
529+
command = "print_result_typer"

0 commit comments

Comments
 (0)