From 8e9a16ec279363a4bbc4f7e3a2915c51e760c856 Mon Sep 17 00:00:00 2001 From: Lukáš Růžička Date: May 15 2025 13:38:41 +0000 Subject: Merge all wrapping methods into one Previously, users could set the wrapping width for the output, but they would have to use three different swithces to achieve a useful setting to wrap the output, i.e. they would have to set the --wrap-width and --wrap-bugs and --wrap-rpms. This PR removes the three options, merging them into --width. By default, the width is set to 0 which triggers auto-detection based on the width of the terminal window, i.e. --width=0. If you resize the terminal window while the application is running, the next update will automatically adjust to the new width of the terminal. On non-terminal environments, where the window width cannot be figured, the default width is 80. Users can override this by using an explicit value using --width=. Fixes: https://pagure.io/fedora-easy-karma/issue/53 Merges: https://pagure.io/fedora-easy-karma/pull-request/54 Do not fail on width < 0 and more This PR fixes problems of the rebased PR. It adds protection to the code when user choose negative value for width. Everything is now taken. It renames self.twidth into self.termwidth for better readibility, as well as term_width() into determine_termwidth, dtto. It removes whitespace from the config file creation text. It adds error message to self.debug, but this change also required to remove @classmethod and @staticmethod from affected functions. --- diff --git a/fedora-easy-karma.py b/fedora-easy-karma.py index afbddb1..d7e3e5e 100755 --- a/fedora-easy-karma.py +++ b/fedora-easy-karma.py @@ -21,6 +21,7 @@ import argparse import datetime import fnmatch import itertools +import io import os import pickle import readline @@ -74,8 +75,7 @@ class FEK_helper(object): bodhi_base_url="https://bodhi.fedoraproject.org/", bugzilla_bug_url="https://bugzilla.redhat.com/", test_cases_url="https://fedoraproject.org/wiki/", - wrap_bugs=True, - width=80, + width=0, bodhi_comments="important", colorize = True): @@ -140,14 +140,9 @@ class FEK_helper(object): bz_title = bug["title"] bugs.append("%s - %s" % (bug_id, bz_title)) - if wrap_bugs: - values["bugs"] = "%s\n" % FEK_helper.wrap_paragraphs_prefix( - bugs, first_prefix=" Bugs: ", width=width, - extra_newline=True - ) - else: - values["bugs"] = " Bugs: %s\n" % ( - "\n" + " " * 11 + ": ").join(bugs) + values["bugs"] = "%s\n" % FEK_helper.wrap_paragraphs_prefix( + bugs, first_prefix=" Bugs: ", width=width, + extra_newline=True) else: values["bugs"] = "" @@ -351,7 +346,6 @@ class PkgHelper(object): def installed_packages(self): return self.my.sack.query().installed() - class FedoraEasyKarma(object): def __init__(self): @@ -367,6 +361,14 @@ class FedoraEasyKarma(object): self.options = self.parse_args(parser, config_args) self.setup_options() + # Set the width for wrapping text. The self.autowidth + # holds the information about this feature. + self.autowidth = False + self.termwidth = self.options.width + if self.termwidth <= 0: + self.termwidth = self.determine_termwidth() + self.autowidth = True + # log into Bodhi self.bc = BodhiClient() print("Logging into Bodhi...") @@ -384,7 +386,12 @@ class FedoraEasyKarma(object): # Pasting the login token into terminal can contain some extra newlines at the end, which # are queued on stdin and then interact with our input prompts. Drop everything currently # on stdin. - termios.tcflush(sys.stdin, termios.TCIFLUSH) + # Note: If the application does not run in a terminal, the following code would crash, + # therefore we need to use the exception here. + try: + termios.tcflush(sys.stdin, termios.TCIFLUSH) + except io.UnsupportedOperation: + self.warning("We are not on a terminal, terminal flushing was skipped.") pkghelper = PkgHelper() @@ -538,21 +545,20 @@ class FedoraEasyKarma(object): import ipdb ipdb.set_trace() if not self.options.list_rpms_only: + # To be sure, update the terminal width to fit nicely + # if the terminal has been resized in between. + if self.autowidth: + self.termwidth = self.determine_termwidth() print(FEK_helper.bodhi_update_str( update, bodhi_base_url=self.bc.base_url, - width=self.options.wrap_width, - wrap_bugs=self.options.wrap_bugs, + width=self.termwidth, bodhi_comments=self.options.bodhi_comments, colorize=not self.options.no_color )) - if self.options.wrap_rpms: - print(FEK_helper.wrap_paragraphs_prefix( - installed_rpms, first_prefix=" inst. RPMS: ", - width=self.options.wrap_width)) - else: - indentation = "\n" + " " * 11 + ": " - rpmlist = indentation.join(installed_rpms) - print(" inst. RPMS: %s\n" % rpmlist) + fprefix = " inst. RPMS: " + print(FEK_helper.wrap_paragraphs_prefix( + installed_rpms, first_prefix=fprefix, + width=self.termwidth-len(fprefix))) if self.already_commented(update, self.bc.username): print("!!! You have already commented on this update !!!") @@ -611,10 +617,10 @@ class FedoraEasyKarma(object): try: with open(self.config_filename, 'w') as config_file: config_file.write('''\ - # Specify command-line options that you want to activate by default. You can use one or more lines. - # Options stated here can be later overriden on the command line itself. See --help for more info. - # E.g.: --pages --wrap-width=120 - ''' +# Specify command-line options that you want to activate by default. You can use one or more lines. +# Options stated here can be later overriden on the command line itself. See --help for more info. +# E.g.: --pages --wrap-width=120 +''' ) except IOError as e: self.warning(f"Can't create config file {self.config_filename}: {e}") @@ -638,14 +644,13 @@ class FedoraEasyKarma(object): self.warning(f"Can't read config file {self.config_filename}: {e}") return [] - @staticmethod - def create_argparser() -> argparse.ArgumentParser: + def create_argparser(self) -> argparse.ArgumentParser: """Create an ArgumentParser. """ usage = FEK_helper.wrap_paragraphs_prefix( USAGE, first_prefix="", - width=80, + width=self.determine_termwidth(), extra_newline=False) parser = argparse.ArgumentParser(description=usage, @@ -753,22 +758,13 @@ class FedoraEasyKarma(object): help="Decide which bodhi comments to show (default: %(default)s)", choices=["all", "important", "none"], default="important") - parser.add_argument("--wrap-bugs", - dest="wrap_bugs", - help="Apply line-wrapping to bugs", - action="store_true", - default=False) - parser.add_argument("--wrap-rpms", - dest="wrap_rpms", - help="Apply line-wrapping to list of installed rpms", - action="store_true", - default=False) - parser.add_argument("--wrap-width", - dest="wrap_width", - help="Width to use for line wrapping of updates " - "(default: %(default)d)", - default=80, - type=int) + parser.add_argument("--width", + dest="width", + help="width to use for line wrapping of updates " + "(default: %(default)s), use '0' to set" + "width based on the terminal width.", + default=0, + type=int) parser.add_argument("--bodhi-request-limit", dest="bodhi_request_limit", help="Maximum number of updates to request at " @@ -787,7 +783,6 @@ class FedoraEasyKarma(object): parser.add_argument("pattern", help="Show only updates matching one or more package name patterns", nargs="*") - return parser def parse_args(self, parser: argparse.ArgumentParser, config_args: list[str]) -> argparse.Namespace: @@ -967,6 +962,19 @@ class FedoraEasyKarma(object): self.refresh_csrf() return (False, 'too many errors') + def determine_termwidth(self): + """Returns the actual width of the terminal.""" + # Try to get the terminal size and if that fails, we are not + # on a terminal. In that case, set the width to 80. + try: + termsize = os.get_terminal_size() + width = termsize[0] + except OSError as e: + self.debug(f"Terminal width could not be determined. See --help to set width manually.") + width = 80 + return width + + def karma_info(karma, colorize=True): """Takes a list of various karma values, counts single values and returns an info string that will be printed out when the info is requested."""