colify.py: get rid of **kwargs (#35641)

`colify` is an old module in Spack that still uses `**kwargs` liberally. 

We should be more explicit. Doing this eliminates the need for many 
checks (can't pass the wrong arg if it isn't allowed) and makes the 
function documentation more clear.
This commit is contained in:
Todd Gamblin 2023-02-23 11:18:54 -08:00 committed by GitHub
parent 5c7cccd052
commit 6b27aebeb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -11,6 +11,7 @@
import io import io
import os import os
import sys import sys
from typing import IO, Any, List, Optional
from llnl.util.tty import terminal_size from llnl.util.tty import terminal_size
from llnl.util.tty.color import cextra, clen from llnl.util.tty.color import cextra, clen
@ -97,7 +98,16 @@ def config_uniform_cols(elts, console_width, padding, cols=0):
return config return config
def colify(elts, **options): def colify(
elts: List[Any],
cols: int = 0,
output: Optional[IO] = None,
indent: int = 0,
padding: int = 2,
tty: Optional[bool] = None,
method: str = "variable",
console_cols: Optional[int] = None,
):
"""Takes a list of elements as input and finds a good columnization """Takes a list of elements as input and finds a good columnization
of them, similar to how gnu ls does. This supports both of them, similar to how gnu ls does. This supports both
uniform-width and variable-width (tighter) columns. uniform-width and variable-width (tighter) columns.
@ -106,31 +116,21 @@ def colify(elts, **options):
using ``str()``. using ``str()``.
Keyword Arguments: Keyword Arguments:
output (typing.IO): A file object to write to. Default is ``sys.stdout`` output: A file object to write to. Default is ``sys.stdout``
indent (int): Optionally indent all columns by some number of spaces indent: Optionally indent all columns by some number of spaces
padding (int): Spaces between columns. Default is 2 padding: Spaces between columns. Default is 2
width (int): Width of the output. Default is 80 if tty not detected width: Width of the output. Default is 80 if tty not detected
cols (int): Force number of columns. Default is to size to terminal, or cols: Force number of columns. Default is to size to terminal, or
single-column if no tty single-column if no tty
tty (bool): Whether to attempt to write to a tty. Default is to autodetect a tty: Whether to attempt to write to a tty. Default is to autodetect a
tty. Set to False to force single-column output tty. Set to False to force single-column output
method (str): Method to use to fit columns. Options are variable or uniform. method: Method to use to fit columns. Options are variable or uniform.
Variable-width columns are tighter, uniform columns are all the same width Variable-width columns are tighter, uniform columns are all the same width
and fit less data on the screen and fit less data on the screen
console_cols: number of columns on this console (default: autodetect)
""" """
# Get keyword arguments or set defaults if output is None:
cols = options.pop("cols", 0) output = sys.stdout
output = options.pop("output", sys.stdout)
indent = options.pop("indent", 0)
padding = options.pop("padding", 2)
tty = options.pop("tty", None)
method = options.pop("method", "variable")
console_cols = options.pop("width", None)
if options:
raise TypeError(
"'%s' is an invalid keyword argument for this function." % next(options.iterkeys())
)
# elts needs to be an array of strings so we can count the elements # elts needs to be an array of strings so we can count the elements
elts = [str(elt) for elt in elts] elts = [str(elt) for elt in elts]
@ -153,10 +153,11 @@ def colify(elts, **options):
cols = 1 cols = 1
# Specify the number of character columns to use. # Specify the number of character columns to use.
if not console_cols: if console_cols is None:
console_rows, console_cols = terminal_size() console_rows, console_cols = terminal_size()
elif type(console_cols) != int: elif not isinstance(console_cols, int):
raise ValueError("Number of columns must be an int") raise ValueError("Number of columns must be an int")
console_cols = max(1, console_cols - indent) console_cols = max(1, console_cols - indent)
# Choose a method. Variable-width colums vs uniform-width. # Choose a method. Variable-width colums vs uniform-width.
@ -192,7 +193,13 @@ def colify(elts, **options):
return (config.cols, tuple(config.widths)) return (config.cols, tuple(config.widths))
def colify_table(table, **options): def colify_table(
table: List[List[Any]],
output: Optional[IO] = None,
indent: int = 0,
padding: int = 2,
console_cols: Optional[int] = None,
):
"""Version of ``colify()`` for data expressed in rows, (list of lists). """Version of ``colify()`` for data expressed in rows, (list of lists).
Same as regular colify but: Same as regular colify but:
@ -218,20 +225,38 @@ def transpose():
for row in table: for row in table:
yield row[i] yield row[i]
if "cols" in options: colify(
raise ValueError("Cannot override columsn in colify_table.") transpose(),
options["cols"] = columns cols=columns, # this is always the number of cols in the table
tty=True, # don't reduce to 1 column for non-tty
# don't reduce to 1 column for non-tty output=output,
options["tty"] = True indent=indent,
padding=padding,
colify(transpose(), **options) console_cols=console_cols,
)
def colified(elts, **options): def colified(
elts: List[Any],
cols: int = 0,
output: Optional[IO] = None,
indent: int = 0,
padding: int = 2,
tty: Optional[bool] = None,
method: str = "variable",
console_cols: Optional[int] = None,
):
"""Invokes the ``colify()`` function but returns the result as a string """Invokes the ``colify()`` function but returns the result as a string
instead of writing it to an output string.""" instead of writing it to an output string."""
sio = io.StringIO() sio = io.StringIO()
options["output"] = sio colify(
colify(elts, **options) elts,
cols=cols,
output=sio,
indent=indent,
padding=padding,
tty=tty,
method=method,
console_cols=console_cols,
)
return sio.getvalue() return sio.getvalue()