Skip to content

Commit 7dbb331

Browse files
authored
Merge pull request #816 from python-cmd2/pfeedback
Updated arguments to pfeedback and ppaged for consistency with other …
2 parents 1cad8d9 + 389f356 commit 7dbb331

File tree

2 files changed

+56
-44
lines changed

2 files changed

+56
-44
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
an argument to disable tab completion while input is being entered.
77
* Added capability to override the argument parser class used by cmd2 built-in commands. See override_parser.py
88
example for more details.
9+
* Added `end` argument to `pfeedback()` to be consistent with the other print functions like `poutput()`.
10+
* Breaking changes
11+
* For consistency between all the print functions:
12+
* Made `end` and `chop` keyword-only arguments of `ppaged()`
13+
* `end` is always added to message in `ppaged()`
914

1015
## 0.9.20 (November 12, 2019)
1116
* Bug Fixes

cmd2/cmd2.py

Lines changed: 51 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -502,23 +502,26 @@ def pexcept(self, msg: Any, *, end: str = '\n', apply_style: bool = True) -> Non
502502
# Set apply_style to False since style has already been applied
503503
self.perror(final_msg, end=end, apply_style=False)
504504

505-
def pfeedback(self, msg: str) -> None:
505+
def pfeedback(self, msg: Any, *, end: str = '\n') -> None:
506506
"""For printing nonessential feedback. Can be silenced with `quiet`.
507-
Inclusion in redirected output is controlled by `feedback_to_output`."""
507+
Inclusion in redirected output is controlled by `feedback_to_output`.
508+
:param msg: message to print (anything convertible to a str with '{}'.format() is OK)
509+
:param end: string appended after the end of the message, default a newline
510+
"""
508511
if not self.quiet:
509512
if self.feedback_to_output:
510-
self.poutput(msg)
513+
self.poutput(msg, end=end)
511514
else:
512-
ansi.ansi_aware_write(sys.stderr, "{}\n".format(msg))
515+
self.perror(msg, end=end, apply_style=False)
513516

514-
def ppaged(self, msg: str, end: str = '\n', chop: bool = False) -> None:
517+
def ppaged(self, msg: Any, *, end: str = '\n', chop: bool = False) -> None:
515518
"""Print output using a pager if it would go off screen and stdout isn't currently being redirected.
516519
517520
Never uses a pager inside of a script (Python or text) or when output is being redirected or piped or when
518521
stdout or stdin are not a fully functional terminal.
519522
520523
:param msg: message to print to current stdout (anything convertible to a str with '{}'.format() is OK)
521-
:param end: string appended after the end of the message if not already present, default a newline
524+
:param end: string appended after the end of the message, default a newline
522525
:param chop: True -> causes lines longer than the screen width to be chopped (truncated) rather than wrapped
523526
- truncated text is still accessible by scrolling with the right & left arrow keys
524527
- chopping is ideal for displaying wide tabular data as is done in utilities like pgcli
@@ -527,44 +530,48 @@ def ppaged(self, msg: str, end: str = '\n', chop: bool = False) -> None:
527530
528531
WARNING: On Windows, the text always wraps regardless of what the chop argument is set to
529532
"""
530-
import subprocess
531-
if msg is not None and msg != '':
532-
try:
533-
msg_str = '{}'.format(msg)
534-
if not msg_str.endswith(end):
535-
msg_str += end
536-
537-
# Attempt to detect if we are not running within a fully functional terminal.
538-
# Don't try to use the pager when being run by a continuous integration system like Jenkins + pexpect.
539-
functional_terminal = False
540-
541-
if self.stdin.isatty() and self.stdout.isatty():
542-
if sys.platform.startswith('win') or os.environ.get('TERM') is not None:
543-
functional_terminal = True
544-
545-
# Don't attempt to use a pager that can block if redirecting or running a script (either text or Python)
546-
# Also only attempt to use a pager if actually running in a real fully functional terminal
547-
if functional_terminal and not self._redirecting and not self.in_pyscript() and not self.in_script():
548-
if ansi.allow_ansi.lower() == ansi.ANSI_NEVER.lower():
549-
msg_str = ansi.strip_ansi(msg_str)
550-
551-
pager = self.pager
552-
if chop:
553-
pager = self.pager_chop
554-
555-
# Prevent KeyboardInterrupts while in the pager. The pager application will
556-
# still receive the SIGINT since it is in the same process group as us.
557-
with self.sigint_protection:
558-
pipe_proc = subprocess.Popen(pager, shell=True, stdin=subprocess.PIPE)
559-
pipe_proc.communicate(msg_str.encode('utf-8', 'replace'))
560-
else:
561-
self.poutput(msg_str, end='')
562-
except BrokenPipeError:
563-
# This occurs if a command's output is being piped to another process and that process closes before the
564-
# command is finished. If you would like your application to print a warning message, then set the
565-
# broken_pipe_warning attribute to the message you want printed.`
566-
if self.broken_pipe_warning:
567-
sys.stderr.write(self.broken_pipe_warning)
533+
# msg can be any type, so convert to string before checking if it's blank
534+
msg_str = str(msg)
535+
536+
# Consider None to be no data to print
537+
if msg is None or msg_str == '':
538+
return
539+
540+
try:
541+
import subprocess
542+
543+
# Attempt to detect if we are not running within a fully functional terminal.
544+
# Don't try to use the pager when being run by a continuous integration system like Jenkins + pexpect.
545+
functional_terminal = False
546+
547+
if self.stdin.isatty() and self.stdout.isatty():
548+
if sys.platform.startswith('win') or os.environ.get('TERM') is not None:
549+
functional_terminal = True
550+
551+
# Don't attempt to use a pager that can block if redirecting or running a script (either text or Python)
552+
# Also only attempt to use a pager if actually running in a real fully functional terminal
553+
if functional_terminal and not self._redirecting and not self.in_pyscript() and not self.in_script():
554+
if ansi.allow_ansi.lower() == ansi.ANSI_NEVER.lower():
555+
msg_str = ansi.strip_ansi(msg_str)
556+
msg_str += end
557+
558+
pager = self.pager
559+
if chop:
560+
pager = self.pager_chop
561+
562+
# Prevent KeyboardInterrupts while in the pager. The pager application will
563+
# still receive the SIGINT since it is in the same process group as us.
564+
with self.sigint_protection:
565+
pipe_proc = subprocess.Popen(pager, shell=True, stdin=subprocess.PIPE)
566+
pipe_proc.communicate(msg_str.encode('utf-8', 'replace'))
567+
else:
568+
self.poutput(msg_str, end=end)
569+
except BrokenPipeError:
570+
# This occurs if a command's output is being piped to another process and that process closes before the
571+
# command is finished. If you would like your application to print a warning message, then set the
572+
# broken_pipe_warning attribute to the message you want printed.`
573+
if self.broken_pipe_warning:
574+
sys.stderr.write(self.broken_pipe_warning)
568575

569576
# ----- Methods related to tab completion -----
570577

0 commit comments

Comments
 (0)