1
0
Fork 0

Adding upstream version 2.4.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-03-12 11:11:09 +01:00
parent c905e7ab8c
commit 8f9294000b
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
7 changed files with 120 additions and 4 deletions

41
.github/workflows/codeql.yml vendored Normal file
View file

@ -0,0 +1,41 @@
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: "36 4 * * 1"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ python ]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
queries: +security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{ matrix.language }}"

1
.gitignore vendored
View file

@ -11,3 +11,4 @@ __pycache__
/cli_helpers_dev /cli_helpers_dev
.idea/ .idea/
.cache/ .cache/
.vscode/

View file

@ -25,6 +25,7 @@ This project receives help from these awesome contributors:
- Mel Dafert - Mel Dafert
- Andrii Kohut - Andrii Kohut
- Roland Walker - Roland Walker
- Doug Harris
Thanks Thanks
------ ------

View file

@ -1,5 +1,11 @@
# Changelog # Changelog
## Version 2.4.0
(released on 2025-03-10)
- Added format_timestamps preprocessor for per-column date/time formatting.
## Version 2.3.1 ## Version 2.3.1
- Don't escape newlines in `ascii` tables, and add `ascii_escaped` table format. - Don't escape newlines in `ascii` tables, and add `ascii_escaped` table format.

View file

@ -1 +1 @@
__version__ = "2.3.1" __version__ = "2.4.0"

View file

@ -2,6 +2,7 @@
"""These preprocessor functions are used to process data prior to output.""" """These preprocessor functions are used to process data prior to output."""
import string import string
from datetime import datetime
from cli_helpers import utils from cli_helpers import utils
from cli_helpers.compat import text_type, int_types, float_types, HAS_PYGMENTS, Token from cli_helpers.compat import text_type, int_types, float_types, HAS_PYGMENTS, Token
@ -125,9 +126,11 @@ def escape_newlines(data, headers, **_):
return ( return (
( (
[ [
v.replace("\r", r"\r").replace("\n", r"\n") (
if isinstance(v, text_type) v.replace("\r", r"\r").replace("\n", r"\n")
else v if isinstance(v, text_type)
else v
)
for v in row for v in row
] ]
for row in data for row in data
@ -351,3 +354,44 @@ def format_numbers(
[_format_number(v, column_types[i]) for i, v in enumerate(row)] for row in data [_format_number(v, column_types[i]) for i, v in enumerate(row)] for row in data
) )
return data, headers return data, headers
def format_timestamps(data, headers, column_date_formats=None, **_):
"""Format timestamps according to user preference.
This allows for per-column formatting for date, time, or datetime like data.
Add a `column_date_formats` section to your config file with separate lines for each column
that you'd like to specify a format using `name=format`. Use standard Python strftime
formatting strings
Example: `signup_date = "%Y-%m-%d"`
:param iterable data: An :term:`iterable` (e.g. list) of rows.
:param iterable headers: The column headers.
:param str column_date_format: The format strings to use for specific columns.
:return: The processed data and headers.
:rtype: tuple
"""
if column_date_formats is None:
return iter(data), headers
def _format_timestamp(value, name, column_date_formats):
if name not in column_date_formats:
return value
try:
dt = datetime.fromisoformat(value)
return dt.strftime(column_date_formats[name])
except (ValueError, TypeError):
# not a date
return value
data = (
[
_format_timestamp(v, headers[i], column_date_formats)
for i, v in enumerate(row)
]
for row in data
)
return data, headers

View file

@ -16,6 +16,7 @@ from cli_helpers.tabular_output.preprocessors import (
override_tab_value, override_tab_value,
style_output, style_output,
format_numbers, format_numbers,
format_timestamps,
) )
if HAS_PYGMENTS: if HAS_PYGMENTS:
@ -348,3 +349,25 @@ def test_enforce_iterable():
assert False, "{} doesn't return iterable".format(name) assert False, "{} doesn't return iterable".format(name)
if isinstance(preprocessed[1], types.GeneratorType): if isinstance(preprocessed[1], types.GeneratorType):
assert False, "{} returns headers as iterator".format(name) assert False, "{} returns headers as iterator".format(name)
def test_format_timestamps():
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"),
("name3", None, "not-actually-timestamp", "2025-02-13T02:32:22"),
)
headers = ["name", "date_col", "datetime_col", "unchanged_col"]
column_date_formats = {
"date_col": "%Y-%m-%d",
"datetime_col": "%I:%M:%S %m/%d/%y",
}
result_data, result_headers = format_timestamps(data, headers, column_date_formats)
expected = [
["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"],
["name3", None, "not-actually-timestamp", "2025-02-13T02:32:22"],
]
assert expected == list(result_data)
assert headers == result_headers