Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding column_date_formats config option #1486

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Contributors:
* Chris Rose (offbyone/offby1)
* Mathieu Dupuy (deronnax)
* Chris Novakovic
* Doug Harris (dougharris)

Creator:
--------
Expand Down
1 change: 1 addition & 0 deletions changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Features
--------
* Add a `--ping` command line option; allows pgcli to replace `pg_isready`
* Changed the packaging metadata from setup.py to pyproject.toml
* Added support for per-column date/time formatting using `column_date_formats` in config

Bug fixes:
----------
Expand Down
15 changes: 13 additions & 2 deletions pgcli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
from typing import Optional

from cli_helpers.tabular_output import TabularOutputFormatter
from cli_helpers.tabular_output.preprocessors import align_decimals, format_numbers
from cli_helpers.tabular_output.preprocessors import (
align_decimals,
format_numbers,
format_timestamps,
)
from cli_helpers.utils import strip_ansi
from .explain_output_formatter import ExplainOutputFormatter
import click
Expand Down Expand Up @@ -111,12 +115,13 @@

OutputSettings = namedtuple(
"OutputSettings",
"table_format dcmlfmt floatfmt missingval expanded max_width case_function style_output max_field_width",
"table_format dcmlfmt floatfmt column_date_formats missingval expanded max_width case_function style_output max_field_width",
)
OutputSettings.__new__.__defaults__ = (
None,
None,
None,
None,
"<null>",
False,
None,
Expand Down Expand Up @@ -264,6 +269,7 @@ def __init__(
self.on_error = c["main"]["on_error"].upper()
self.decimal_format = c["data_formats"]["decimal"]
self.float_format = c["data_formats"]["float"]
self.column_date_formats = c["column_date_formats"]
auth.keyring_initialize(c["main"].as_bool("keyring"), logger=self.logger)
self.show_bottom_toolbar = c["main"].as_bool("show_bottom_toolbar")

Expand Down Expand Up @@ -1179,6 +1185,7 @@ def _evaluate_command(self, text):
table_format=self.table_format,
dcmlfmt=self.decimal_format,
floatfmt=self.float_format,
column_date_formats=self.column_date_formats,
missingval=self.null_string,
expanded=expanded,
max_width=max_width,
Expand Down Expand Up @@ -1830,6 +1837,7 @@ def format_status(cur, status):
"missing_value": settings.missingval,
"integer_format": settings.dcmlfmt,
"float_format": settings.floatfmt,
"column_date_formats": settings.column_date_formats,
"preprocessors": (format_numbers, format_arrays),
"disable_numparse": True,
"preserve_whitespace": True,
Expand All @@ -1839,6 +1847,9 @@ def format_status(cur, status):
if not settings.floatfmt:
output_kwargs["preprocessors"] = (align_decimals,)

if settings.column_date_formats:
output_kwargs["preprocessors"] += (format_timestamps,)

if table_format == "csv":
# The default CSV dialect is "excel" which is not handling newline values correctly
# Nevertheless, we want to keep on using "excel" on Windows since it uses '\r\n'
Expand Down
5 changes: 5 additions & 0 deletions pgcli/pgclirc
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,8 @@ output.null = "#808080"
[data_formats]
decimal = ""
float = ""

# Per column formats for date/timestamp columns
[column_date_formats]
# use strftime format, e.g.
# created = "%Y-%m-%d"
51 changes: 51 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,57 @@ def test_format_output():
assert list(results) == expected


def test_column_date_formats():
settings = OutputSettings(
table_format="psql",
column_date_formats={
"date_col": "%Y-%m-%d",
"datetime_col": "%I:%M:%S %m/%d/%y",
},
)
data = [
("name1", "2024-12-13T18:32:22", "2024-12-13T19:32:22", "2024-12-13T20:32:22"),
("name2", "2025-02-13T02:32:22", "2025-02-13T02:32:22", "2025-02-13T02:32:22"),
]
headers = ["name", "date_col", "datetime_col", "unchanged_col"]

results = format_output("Title", data, headers, "test status", settings)
expected = [
"Title",
"+-------+------------+-------------------+---------------------+",
"| name | date_col | datetime_col | unchanged_col |",
"|-------+------------+-------------------+---------------------|",
"| name1 | 2024-12-13 | 07:32:22 12/13/24 | 2024-12-13T20:32:22 |",
"| name2 | 2025-02-13 | 02:32:22 02/13/25 | 2025-02-13T02:32:22 |",
"+-------+------------+-------------------+---------------------+",
"test status",
]
assert list(results) == expected


def test_no_column_date_formats():
"""Test that not setting any column date formats returns unaltered datetime columns"""
settings = OutputSettings(table_format="psql")
data = [
("name1", "2024-12-13T18:32:22", "2024-12-13T19:32:22", "2024-12-13T20:32:22"),
("name2", "2025-02-13T02:32:22", "2025-02-13T02:32:22", "2025-02-13T02:32:22"),
]
headers = ["name", "date_col", "datetime_col", "unchanged_col"]

results = format_output("Title", data, headers, "test status", settings)
expected = [
"Title",
"+-------+---------------------+---------------------+---------------------+",
"| name | date_col | datetime_col | unchanged_col |",
"|-------+---------------------+---------------------+---------------------|",
"| name1 | 2024-12-13T18:32:22 | 2024-12-13T19:32:22 | 2024-12-13T20:32:22 |",
"| name2 | 2025-02-13T02:32:22 | 2025-02-13T02:32:22 | 2025-02-13T02:32:22 |",
"+-------+---------------------+---------------------+---------------------+",
"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
Expand Down