mirror of https://github.com/dbcli/pgcli
Add setting in config to control truncating field values. (#1285)
* Add setting in config to truncate field value. * Black. * Changelog. * Fix tests.
This commit is contained in:
parent
0f54b126b3
commit
c65495716d
|
@ -4,10 +4,12 @@ TBD
|
|||
Features:
|
||||
---------
|
||||
|
||||
* Add `max_field_width` setting to config, to enable more control over field truncation ([related issue](https://github.com/dbcli/pgcli/issues/1250)).
|
||||
|
||||
Bug fixes:
|
||||
----------
|
||||
|
||||
3.2.0
|
||||
3.2.0
|
||||
=====
|
||||
|
||||
Release date: 2021/08/23
|
||||
|
|
|
@ -86,6 +86,7 @@ from textwrap import dedent
|
|||
|
||||
# Ref: https://stackoverflow.com/questions/30425105/filter-special-chars-such-as-color-codes-from-shell-output
|
||||
COLOR_CODE_REGEX = re.compile(r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))")
|
||||
DEFAULT_MAX_FIELD_WIDTH = 500
|
||||
|
||||
# Query tuples are used for maintaining history
|
||||
MetaQuery = namedtuple(
|
||||
|
@ -106,7 +107,7 @@ MetaQuery.__new__.__defaults__ = ("", False, 0, 0, False, False, False, False)
|
|||
|
||||
OutputSettings = namedtuple(
|
||||
"OutputSettings",
|
||||
"table_format dcmlfmt floatfmt missingval expanded max_width case_function style_output",
|
||||
"table_format dcmlfmt floatfmt missingval expanded max_width case_function style_output max_field_width",
|
||||
)
|
||||
OutputSettings.__new__.__defaults__ = (
|
||||
None,
|
||||
|
@ -117,6 +118,7 @@ OutputSettings.__new__.__defaults__ = (
|
|||
None,
|
||||
lambda x: x,
|
||||
None,
|
||||
DEFAULT_MAX_FIELD_WIDTH,
|
||||
)
|
||||
|
||||
|
||||
|
@ -201,6 +203,16 @@ class PGCli:
|
|||
else:
|
||||
self.row_limit = c["main"].as_int("row_limit")
|
||||
|
||||
# if not specified, set to DEFAULT_MAX_FIELD_WIDTH
|
||||
# if specified but empty, set to None to disable truncation
|
||||
# ellipsis will take at least 3 symbols, so this can't be less than 3 if specified and > 0
|
||||
max_field_width = c["main"].get("max_field_width", DEFAULT_MAX_FIELD_WIDTH)
|
||||
if max_field_width and max_field_width.lower() != "none":
|
||||
max_field_width = max(3, abs(int(max_field_width)))
|
||||
else:
|
||||
max_field_width = None
|
||||
self.max_field_width = max_field_width
|
||||
|
||||
self.min_num_menu_lines = c["main"].as_int("min_num_menu_lines")
|
||||
self.multiline_continuation_char = c["main"]["multiline_continuation_char"]
|
||||
self.table_format = c["main"]["table_format"]
|
||||
|
@ -934,6 +946,7 @@ class PGCli:
|
|||
else lambda x: x
|
||||
),
|
||||
style_output=self.style_output,
|
||||
max_field_width=self.max_field_width,
|
||||
)
|
||||
execution = time() - start
|
||||
formatted = format_output(title, cur, headers, status, settings)
|
||||
|
@ -1444,6 +1457,7 @@ def format_output(title, cur, headers, status, settings):
|
|||
"disable_numparse": True,
|
||||
"preserve_whitespace": True,
|
||||
"style": settings.style_output,
|
||||
"max_field_width": settings.max_field_width,
|
||||
}
|
||||
if not settings.floatfmt:
|
||||
output_kwargs["preprocessors"] = (align_decimals,)
|
||||
|
|
|
@ -119,6 +119,12 @@ on_error = STOP
|
|||
# Set threshold for row limit. Use 0 to disable limiting.
|
||||
row_limit = 1000
|
||||
|
||||
# Truncate long text fields to this value for tabular display (does not apply to csv).
|
||||
# Leave unset to disable truncation. Example: "max_field_width = "
|
||||
# Be aware that formatting might get slow with values larger than 500 and tables with
|
||||
# lots of records.
|
||||
max_field_width = 500
|
||||
|
||||
# Skip intro on startup and goodbye on exit
|
||||
less_chatty = False
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@ def step_see_small_results(context):
|
|||
context,
|
||||
dedent(
|
||||
"""\
|
||||
+------------+\r
|
||||
| ?column? |\r
|
||||
|------------|\r
|
||||
| 1 |\r
|
||||
+------------+\r
|
||||
+----------+\r
|
||||
| ?column? |\r
|
||||
|----------|\r
|
||||
| 1 |\r
|
||||
+----------+\r
|
||||
SELECT 1\r
|
||||
"""
|
||||
),
|
||||
|
|
|
@ -118,11 +118,11 @@ def step_see_found(context):
|
|||
+ "\r"
|
||||
+ dedent(
|
||||
"""
|
||||
+------------+\r
|
||||
| ?column? |\r
|
||||
|------------|\r
|
||||
| found |\r
|
||||
+------------+\r
|
||||
+----------+\r
|
||||
| ?column? |\r
|
||||
|----------|\r
|
||||
| found |\r
|
||||
+----------+\r
|
||||
SELECT 1\r
|
||||
"""
|
||||
)
|
||||
|
|
|
@ -58,11 +58,11 @@ def step_see_data(context, which):
|
|||
context,
|
||||
dedent(
|
||||
"""\
|
||||
+-----+-----+--------+\r
|
||||
| x | y | z |\r
|
||||
|-----+-----+--------|\r
|
||||
| 1 | 1.0 | 1.0000 |\r
|
||||
+-----+-----+--------+\r
|
||||
+---+-----+--------+\r
|
||||
| x | y | z |\r
|
||||
|---+-----+--------|\r
|
||||
| 1 | 1.0 | 1.0000 |\r
|
||||
+---+-----+--------+\r
|
||||
SELECT 1\r
|
||||
"""
|
||||
),
|
||||
|
|
|
@ -61,16 +61,47 @@ def test_format_output():
|
|||
)
|
||||
expected = [
|
||||
"Title",
|
||||
"+---------+---------+",
|
||||
"| head1 | head2 |",
|
||||
"|---------+---------|",
|
||||
"| abc | def |",
|
||||
"+---------+---------+",
|
||||
"+-------+-------+",
|
||||
"| head1 | head2 |",
|
||||
"|-------+-------|",
|
||||
"| abc | def |",
|
||||
"+-------+-------+",
|
||||
"test status",
|
||||
]
|
||||
assert list(results) == expected
|
||||
|
||||
|
||||
def test_format_output_truncate_on():
|
||||
settings = OutputSettings(
|
||||
table_format="psql", dcmlfmt="d", floatfmt="g", max_field_width=10
|
||||
)
|
||||
results = format_output(
|
||||
None,
|
||||
[("first field value", "second field value")],
|
||||
["head1", "head2"],
|
||||
None,
|
||||
settings,
|
||||
)
|
||||
expected = [
|
||||
"+------------+------------+",
|
||||
"| head1 | head2 |",
|
||||
"|------------+------------|",
|
||||
"| first f... | second ... |",
|
||||
"+------------+------------+",
|
||||
]
|
||||
assert list(results) == expected
|
||||
|
||||
|
||||
def test_format_output_truncate_off():
|
||||
settings = OutputSettings(
|
||||
table_format="psql", dcmlfmt="d", floatfmt="g", max_field_width=None
|
||||
)
|
||||
long_field_value = ("first field " * 100).strip()
|
||||
results = format_output(None, [(long_field_value,)], ["head1"], None, settings)
|
||||
lines = list(results)
|
||||
assert lines[3] == f"| {long_field_value} |"
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_format_array_output(executor):
|
||||
statement = """
|
||||
|
@ -83,12 +114,12 @@ def test_format_array_output(executor):
|
|||
"""
|
||||
results = run(executor, statement)
|
||||
expected = [
|
||||
"+----------------+------------------------+--------------+",
|
||||
"| bigint_array | nested_numeric_array | 配列 |",
|
||||
"|----------------+------------------------+--------------|",
|
||||
"| {1,2,3} | {{1,2},{3,4}} | {å,魚,текст} |",
|
||||
"| {} | <null> | {<null>} |",
|
||||
"+----------------+------------------------+--------------+",
|
||||
"+--------------+----------------------+--------------+",
|
||||
"| bigint_array | nested_numeric_array | 配列 |",
|
||||
"|--------------+----------------------+--------------|",
|
||||
"| {1,2,3} | {{1,2},{3,4}} | {å,魚,текст} |",
|
||||
"| {} | <null> | {<null>} |",
|
||||
"+--------------+----------------------+--------------+",
|
||||
"SELECT 2",
|
||||
]
|
||||
assert list(results) == expected
|
||||
|
@ -128,11 +159,11 @@ def test_format_output_auto_expand():
|
|||
)
|
||||
table = [
|
||||
"Title",
|
||||
"+---------+---------+",
|
||||
"| head1 | head2 |",
|
||||
"|---------+---------|",
|
||||
"| abc | def |",
|
||||
"+---------+---------+",
|
||||
"+-------+-------+",
|
||||
"| head1 | head2 |",
|
||||
"|-------+-------|",
|
||||
"| abc | def |",
|
||||
"+-------+-------+",
|
||||
"test status",
|
||||
]
|
||||
assert list(table_results) == table
|
||||
|
|
Loading…
Reference in New Issue