diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-11-14 07:33:20 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-11-14 07:42:43 +0300 |
commit | be3f129280eabea23fd7feb5ab9637418d8fce34 (patch) | |
tree | 5c4d1f7357f0094f735a25c90f271257d81f9c1c | |
parent | 7de479157f34bbce462b90d7626676dc46b55382 (diff) | |
download | ydb-be3f129280eabea23fd7feb5ab9637418d8fce34.tar.gz |
Intermediate changes
commit_hash:3686ebe90c261233292d0ccb4dc131386ef2b33a
-rw-r--r-- | contrib/python/prettytable/py3/.dist-info/METADATA | 28 | ||||
-rw-r--r-- | contrib/python/prettytable/py3/README.md | 12 | ||||
-rw-r--r-- | contrib/python/prettytable/py3/prettytable/__init__.py | 45 | ||||
-rw-r--r-- | contrib/python/prettytable/py3/prettytable/_version.py | 16 | ||||
-rw-r--r-- | contrib/python/prettytable/py3/prettytable/colortable.py | 42 | ||||
-rw-r--r-- | contrib/python/prettytable/py3/prettytable/prettytable.py | 710 | ||||
-rw-r--r-- | contrib/python/prettytable/py3/tests/test_colortable.py | 39 | ||||
-rw-r--r-- | contrib/python/prettytable/py3/tests/test_prettytable.py | 169 | ||||
-rw-r--r-- | contrib/python/prettytable/py3/ya.make | 3 |
9 files changed, 695 insertions, 369 deletions
diff --git a/contrib/python/prettytable/py3/.dist-info/METADATA b/contrib/python/prettytable/py3/.dist-info/METADATA index 6df980cfd8..e44b80cd6e 100644 --- a/contrib/python/prettytable/py3/.dist-info/METADATA +++ b/contrib/python/prettytable/py3/.dist-info/METADATA @@ -1,18 +1,18 @@ Metadata-Version: 2.3 Name: prettytable -Version: 3.11.0 +Version: 3.12.0 Summary: A simple Python library for easily displaying tabular data in a visually appealing ASCII table format -Project-URL: Changelog, https://github.com/jazzband/prettytable/releases -Project-URL: Homepage, https://github.com/jazzband/prettytable -Project-URL: Source, https://github.com/jazzband/prettytable +Project-URL: Changelog, https://github.com/prettytable/prettytable/releases +Project-URL: Funding, https://tidelift.com/subscription/pkg/pypi-prettytable?utm_source=pypi-prettytable&utm_medium=pypi +Project-URL: Homepage, https://github.com/prettytable/prettytable +Project-URL: Source, https://github.com/prettytable/prettytable Author-email: Luke Maurits <luke@maurits.id.au> -Maintainer: Jazzband -License: BSD (3 clause) +Maintainer: Hugo van Kemenade +License-Expression: BSD-3-Clause License-File: LICENSE Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 @@ -22,7 +22,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Text Processing Classifier: Typing :: Typed -Requires-Python: >=3.8 +Requires-Python: >=3.9 Requires-Dist: wcwidth Provides-Extra: tests Requires-Dist: pytest; extra == 'tests' @@ -32,13 +32,13 @@ Description-Content-Type: text/markdown # PrettyTable -[![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/) [![PyPI version](https://img.shields.io/pypi/v/prettytable.svg?logo=pypi&logoColor=FFE873)](https://pypi.org/project/prettytable/) [![Supported Python versions](https://img.shields.io/pypi/pyversions/prettytable.svg?logo=python&logoColor=FFE873)](https://pypi.org/project/prettytable/) [![PyPI downloads](https://img.shields.io/pypi/dm/prettytable.svg)](https://pypistats.org/packages/prettytable) -[![GitHub Actions status](https://github.com/jazzband/prettytable/workflows/Test/badge.svg)](https://github.com/jazzband/prettytable/actions) -[![codecov](https://codecov.io/gh/jazzband/prettytable/branch/main/graph/badge.svg)](https://codecov.io/gh/jazzband/prettytable) -[![Code style: Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +[![GitHub Actions status](https://github.com/prettytable/prettytable/workflows/Test/badge.svg)](https://github.com/prettytable/prettytable/actions) +[![codecov](https://codecov.io/gh/prettytable/prettytable/branch/main/graph/badge.svg)](https://codecov.io/gh/prettytable/prettytable) +[![Code style: Black](https://img.shields.io/badge/code%20style-Black-000000.svg)](https://github.com/psf/black) +[![Tidelift](https://tidelift.com/badges/package/pypi/prettytable)](https://tidelift.com/subscription/pkg/pypi-prettytable?utm_source=pypi-prettytable&utm_medium=badge) PrettyTable lets you print tables in an attractive ASCII form: @@ -64,11 +64,11 @@ Install via pip: Install latest development version: - python -m pip install -U git+https://github.com/jazzband/prettytable + python -m pip install -U git+https://github.com/prettytable/prettytable Or from `requirements.txt`: - -e git://github.com/jazzband/prettytable.git#egg=prettytable + -e git://github.com/prettytable/prettytable.git#egg=prettytable ## Tutorial on how to use the PrettyTable API diff --git a/contrib/python/prettytable/py3/README.md b/contrib/python/prettytable/py3/README.md index bb365317da..0c89cbefbc 100644 --- a/contrib/python/prettytable/py3/README.md +++ b/contrib/python/prettytable/py3/README.md @@ -1,12 +1,12 @@ # PrettyTable -[![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/) [![PyPI version](https://img.shields.io/pypi/v/prettytable.svg?logo=pypi&logoColor=FFE873)](https://pypi.org/project/prettytable/) [![Supported Python versions](https://img.shields.io/pypi/pyversions/prettytable.svg?logo=python&logoColor=FFE873)](https://pypi.org/project/prettytable/) [![PyPI downloads](https://img.shields.io/pypi/dm/prettytable.svg)](https://pypistats.org/packages/prettytable) -[![GitHub Actions status](https://github.com/jazzband/prettytable/workflows/Test/badge.svg)](https://github.com/jazzband/prettytable/actions) -[![codecov](https://codecov.io/gh/jazzband/prettytable/branch/main/graph/badge.svg)](https://codecov.io/gh/jazzband/prettytable) -[![Code style: Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +[![GitHub Actions status](https://github.com/prettytable/prettytable/workflows/Test/badge.svg)](https://github.com/prettytable/prettytable/actions) +[![codecov](https://codecov.io/gh/prettytable/prettytable/branch/main/graph/badge.svg)](https://codecov.io/gh/prettytable/prettytable) +[![Code style: Black](https://img.shields.io/badge/code%20style-Black-000000.svg)](https://github.com/psf/black) +[![Tidelift](https://tidelift.com/badges/package/pypi/prettytable)](https://tidelift.com/subscription/pkg/pypi-prettytable?utm_source=pypi-prettytable&utm_medium=badge) PrettyTable lets you print tables in an attractive ASCII form: @@ -32,11 +32,11 @@ Install via pip: Install latest development version: - python -m pip install -U git+https://github.com/jazzband/prettytable + python -m pip install -U git+https://github.com/prettytable/prettytable Or from `requirements.txt`: - -e git://github.com/jazzband/prettytable.git#egg=prettytable + -e git://github.com/prettytable/prettytable.git#egg=prettytable ## Tutorial on how to use the PrettyTable API diff --git a/contrib/python/prettytable/py3/prettytable/__init__.py b/contrib/python/prettytable/py3/prettytable/__init__.py index 7f9bbe27eb..29ffbe8d97 100644 --- a/contrib/python/prettytable/py3/prettytable/__init__.py +++ b/contrib/python/prettytable/py3/prettytable/__init__.py @@ -2,21 +2,27 @@ from __future__ import annotations from typing import Any -from .prettytable import ( - ALL, - DEFAULT, - DOUBLE_BORDER, - FRAME, - HEADER, - MARKDOWN, - MSWORD_FRIENDLY, - NONE, - ORGMODE, - PLAIN_COLUMNS, - RANDOM, - SINGLE_BORDER, +from ._version import __version__ +from .prettytable import ( # noqa: F401 + _DEPRECATED_ALL, + _DEPRECATED_DEFAULT, + _DEPRECATED_DOUBLE_BORDER, + _DEPRECATED_FRAME, + _DEPRECATED_HEADER, + _DEPRECATED_MARKDOWN, + _DEPRECATED_MSWORD_FRIENDLY, + _DEPRECATED_NONE, + _DEPRECATED_ORGMODE, + _DEPRECATED_PLAIN_COLUMNS, + _DEPRECATED_RANDOM, + _DEPRECATED_SINGLE_BORDER, + HRuleStyle, PrettyTable, + RowType, TableHandler, + TableStyle, + VRuleStyle, + _warn_deprecation, from_csv, from_db_cursor, from_html, @@ -37,21 +43,20 @@ __all__ = [ "ORGMODE", "PLAIN_COLUMNS", "RANDOM", + "HRuleStyle", "PrettyTable", + "RowType", "TableHandler", + "TableStyle", + "VRuleStyle", "from_csv", "from_db_cursor", "from_html", "from_html_one", "from_json", + "__version__", ] def __getattr__(name: str) -> Any: - if name == "__version__": - import importlib.metadata - - return importlib.metadata.version(__name__) - - msg = f"module '{__name__}' has no attribute '{name}'" - raise AttributeError(msg) + return _warn_deprecation(name, module_globals=globals()) diff --git a/contrib/python/prettytable/py3/prettytable/_version.py b/contrib/python/prettytable/py3/prettytable/_version.py new file mode 100644 index 0000000000..9e1a89958d --- /dev/null +++ b/contrib/python/prettytable/py3/prettytable/_version.py @@ -0,0 +1,16 @@ +# file generated by setuptools_scm +# don't change, don't track in version control +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Tuple, Union + VERSION_TUPLE = Tuple[Union[int, str], ...] +else: + VERSION_TUPLE = object + +version: str +__version__: str +__version_tuple__: VERSION_TUPLE +version_tuple: VERSION_TUPLE + +__version__ = version = '3.12.0' +__version_tuple__ = version_tuple = (3, 12, 0) diff --git a/contrib/python/prettytable/py3/prettytable/colortable.py b/contrib/python/prettytable/py3/prettytable/colortable.py index 3df50c63d8..52e1fa20a4 100644 --- a/contrib/python/prettytable/py3/prettytable/colortable.py +++ b/contrib/python/prettytable/py3/prettytable/colortable.py @@ -45,12 +45,54 @@ class Theme: class Themes: DEFAULT = Theme() + DYSLEXIA_FRIENDLY = Theme( + default_color="38;5;223", + vertical_color="38;5;22", + horizontal_color="38;5;22", + junction_color="38;5;58", + ) + EARTH = Theme( + default_color="33", + vertical_color="38;5;94", + horizontal_color="38;5;22", + junction_color="38;5;130", + ) + GLARE_REDUCTION = Theme( + default_color="38;5;252", + vertical_color="38;5;240", + horizontal_color="38;5;240", + junction_color="38;5;246", + ) + HIGH_CONTRAST = Theme( + default_color="97", + vertical_color="91", + horizontal_color="94", + junction_color="93", + ) + LAVENDER = Theme( + default_color="38;5;183", + vertical_color="35", + horizontal_color="38;5;147", + junction_color="38;5;219", + ) OCEAN = Theme( default_color="96", vertical_color="34", horizontal_color="34", junction_color="36", ) + OCEAN_DEEP = Theme( + default_color="96", + vertical_color="34", + horizontal_color="36", + junction_color="94", + ) + PASTEL = Theme( + default_color="38;5;223", + vertical_color="38;5;152", + horizontal_color="38;5;187", + junction_color="38;5;157", + ) class ColorTable(PrettyTable): diff --git a/contrib/python/prettytable/py3/prettytable/prettytable.py b/contrib/python/prettytable/py3/prettytable/prettytable.py index 7f5dacb58a..818a5203bb 100644 --- a/contrib/python/prettytable/py3/prettytable/prettytable.py +++ b/contrib/python/prettytable/py3/prettytable/prettytable.py @@ -35,30 +35,120 @@ from __future__ import annotations import io import re +import warnings +from collections.abc import Callable, Iterable, Mapping, Sequence +from enum import IntEnum from html.parser import HTMLParser -from typing import Any - -# hrule styles -FRAME = 0 -ALL = 1 -NONE = 2 -HEADER = 3 - -# Table styles -DEFAULT = 10 -MSWORD_FRIENDLY = 11 -PLAIN_COLUMNS = 12 -MARKDOWN = 13 -ORGMODE = 14 -DOUBLE_BORDER = 15 -SINGLE_BORDER = 16 -RANDOM = 20 -BASE_ALIGN_VALUE = "base_align_value" +from typing import TYPE_CHECKING, Any, Final, Literal, TypedDict, cast + +if TYPE_CHECKING: + from sqlite3 import Cursor + + from _typeshed import SupportsRichComparison + from typing_extensions import Self, TypeAlias + + +class HRuleStyle(IntEnum): + FRAME = 0 + ALL = 1 + NONE = 2 + HEADER = 3 + + +class VRuleStyle(IntEnum): + FRAME = 0 + ALL = 1 + NONE = 2 + + +class TableStyle(IntEnum): + DEFAULT = 10 + MSWORD_FRIENDLY = 11 + PLAIN_COLUMNS = 12 + MARKDOWN = 13 + ORGMODE = 14 + DOUBLE_BORDER = 15 + SINGLE_BORDER = 16 + RANDOM = 20 + + +# keep for backwards compatibility +_DEPRECATED_FRAME: Final = 0 +_DEPRECATED_ALL: Final = 1 +_DEPRECATED_NONE: Final = 2 +_DEPRECATED_HEADER: Final = 3 +_DEPRECATED_DEFAULT: Final = TableStyle.DEFAULT +_DEPRECATED_MSWORD_FRIENDLY: Final = TableStyle.MSWORD_FRIENDLY +_DEPRECATED_PLAIN_COLUMNS: Final = TableStyle.PLAIN_COLUMNS +_DEPRECATED_MARKDOWN: Final = TableStyle.MARKDOWN +_DEPRECATED_ORGMODE: Final = TableStyle.ORGMODE +_DEPRECATED_DOUBLE_BORDER: Final = TableStyle.DOUBLE_BORDER +_DEPRECATED_SINGLE_BORDER: Final = TableStyle.SINGLE_BORDER +_DEPRECATED_RANDOM: Final = TableStyle.RANDOM +# -------------------------------- + +BASE_ALIGN_VALUE: Final = "base_align_value" + +RowType: TypeAlias = list[Any] +AlignType: TypeAlias = Literal["l", "c", "r"] +VAlignType: TypeAlias = Literal["t", "m", "b"] +HeaderStyleType: TypeAlias = Literal["cap", "title", "upper", "lower", None] + + +class OptionsType(TypedDict): + title: str | None + start: int + end: int | None + fields: Sequence[str | None] | None + header: bool + border: bool + preserve_internal_border: bool + sortby: str | None + reversesort: bool + sort_key: Callable[[RowType], SupportsRichComparison] + attributes: dict[str, str] + format: bool + hrules: HRuleStyle + vrules: VRuleStyle + int_format: str | dict[str, str] | None + float_format: str | dict[str, str] | None + custom_format: ( + Callable[[str, Any], str] | dict[str, Callable[[str, Any], str]] | None + ) + min_table_width: int | None + max_table_width: int | None + padding_width: int + left_padding_width: int | None + right_padding_width: int | None + vertical_char: str + horizontal_char: str + horizontal_align_char: str + junction_char: str + header_style: HeaderStyleType + xhtml: bool + print_empty: bool + oldsortslice: bool + top_junction_char: str + bottom_junction_char: str + right_junction_char: str + left_junction_char: str + top_right_junction_char: str + top_left_junction_char: str + bottom_right_junction_char: str + bottom_left_junction_char: str + align: dict[str, AlignType] + valign: dict[str, VAlignType] + min_width: int | dict[str, int] | None + max_width: int | dict[str, int] | None + none_format: str | dict[str, str | None] | None + escape_header: bool + escape_data: bool + _re = re.compile(r"\033\[[0-9;]*m|\033\(B") -def _get_size(text): +def _get_size(text: str) -> tuple[int, int]: lines = text.split("\n") height = len(lines) width = max(_str_block_width(line) for line in lines) @@ -66,7 +156,56 @@ def _get_size(text): class PrettyTable: - def __init__(self, field_names=None, **kwargs) -> None: + _xhtml: bool + _align: dict[str, AlignType] + _valign: dict[str, VAlignType] + _min_width: dict[str, int] + _max_width: dict[str, int] + _min_table_width: int | None + _max_table_width: int | None + _fields: Sequence[str | None] | None + _title: str | None + _start: int + _end: int | None + _sortby: str | None + _reversesort: bool + _sort_key: Callable[[RowType], SupportsRichComparison] + _header: bool + _header_style: HeaderStyleType + _border: bool + _preserve_internal_border: bool + _hrules: HRuleStyle + _vrules: VRuleStyle + _int_format: dict[str, str] + _float_format: dict[str, str] + _custom_format: dict[str, Callable[[str, Any], str]] + _padding_width: int + _left_padding_width: int | None + _right_padding_width: int | None + _vertical_char: str + _horizontal_char: str + _horizontal_align_char: str | None + _junction_char: str + _top_junction_char: str | None + _bottom_junction_char: str | None + _right_junction_char: str | None + _left_junction_char: str | None + _top_right_junction_char: str | None + _top_left_junction_char: str | None + _bottom_right_junction_char: str | None + _bottom_left_junction_char: str | None + _format: bool + _print_empty: bool + _oldsortslice: bool + _attributes: dict[str, str] + _escape_header: bool + _escape_data: bool + _style: TableStyle | None + orgmode: bool + _widths: list[int] + _hrule: str + + def __init__(self, field_names: Sequence[str] | None = None, **kwargs) -> None: """Return a new PrettyTable instance Arguments: @@ -84,9 +223,9 @@ class PrettyTable: preserve_internal_border - print a border inside the table even if border is disabled (True or False) hrules - controls printing of horizontal rules after rows. - Allowed values: FRAME, HEADER, ALL, NONE + Allowed values: HRuleStyle vrules - controls printing of vertical rules between columns. - Allowed values: FRAME, ALL, NONE + Allowed values: VRuleStyle int_format - controls formatting of integer data float_format - controls formatting of floating point data custom_format - controls formatting of any column using callable @@ -126,7 +265,7 @@ class PrettyTable: # Data self._field_names: list[str] = [] - self._rows: list[list] = [] + self._rows: list[RowType] = [] self._dividers: list[bool] = [] self.align = {} self.valign = {} @@ -171,7 +310,6 @@ class PrettyTable: "horizontal_align_char", "junction_char", "header_style", - "valign", "xhtml", "print_empty", "oldsortslice", @@ -201,7 +339,7 @@ class PrettyTable: self._start = kwargs["start"] or 0 self._end = kwargs["end"] or None self._fields = kwargs["fields"] or None - self._none_format: dict[None, None] = {} + self._none_format: dict[str, str | None] = {} if kwargs["header"] in (True, False): self._header = kwargs["header"] @@ -216,8 +354,8 @@ class PrettyTable: self._preserve_internal_border = kwargs["preserve_internal_border"] else: self._preserve_internal_border = False - self._hrules = kwargs["hrules"] or FRAME - self._vrules = kwargs["vrules"] or ALL + self._hrules = kwargs["hrules"] or HRuleStyle.FRAME + self._vrules = kwargs["vrules"] or VRuleStyle.ALL self._sortby = kwargs["sortby"] or None if kwargs["reversesort"] in (True, False): @@ -278,7 +416,7 @@ class PrettyTable: self._xhtml = kwargs["xhtml"] or False self._attributes = kwargs["attributes"] or {} - def _justify(self, text, width, align): + def _justify(self, text: str, width: int, align: AlignType) -> str: excess = width - _str_block_width(text) if align == "l": return text + excess * " " @@ -312,7 +450,7 @@ class PrettyTable: else: raise AttributeError(name) - def __getitem__(self, index): + def __getitem__(self, index: int | slice) -> PrettyTable: new = PrettyTable() new.field_names = self.field_names for attr in self._options: @@ -334,7 +472,7 @@ class PrettyTable: def __repr__(self) -> str: return self.get_string() - def _repr_html_(self): + def _repr_html_(self) -> str: """ Returns get_html_string value by default as the repr call in Jupyter notebook environment @@ -369,7 +507,6 @@ class PrettyTable: "padding_width", "left_padding_width", "right_padding_width", - "format", ): self._validate_nonnegative_int(option, val) elif option == "sortby": @@ -388,6 +525,7 @@ class PrettyTable: "preserve_internal_border", "reversesort", "xhtml", + "format", "print_empty", "oldsortslice", "escape_header", @@ -472,9 +610,9 @@ class PrettyTable: def _validate_valign(self, val): try: - assert val in ["t", "m", "b", None] + assert val in ["t", "m", "b"] except AssertionError: - msg = f"Alignment {val} is invalid, use t, m, b or None" + msg = f"Alignment {val} is invalid, use t, m, b" raise ValueError(msg) def _validate_nonnegative_int(self, name, val): @@ -528,16 +666,16 @@ class PrettyTable: def _validate_hrules(self, name, val): try: - assert val in (ALL, FRAME, HEADER, NONE) + assert val in list(HRuleStyle) except AssertionError: - msg = f"Invalid value for {name}. Must be ALL, FRAME, HEADER or NONE." + msg = f"Invalid value for {name}. Must be HRuleStyle." raise ValueError(msg) def _validate_vrules(self, name, val): try: - assert val in (ALL, FRAME, NONE) + assert val in list(VRuleStyle) except AssertionError: - msg = f"Invalid value for {name}. Must be ALL, FRAME, or NONE." + msg = f"Invalid value for {name}. Must be VRuleStyle." raise ValueError(msg) def _validate_field_name(self, name, val): @@ -573,7 +711,7 @@ class PrettyTable: # ATTRIBUTE MANAGEMENT # ############################## @property - def rows(self) -> list[Any]: + def rows(self) -> list[RowType]: return self._rows[:] @property @@ -586,7 +724,7 @@ class PrettyTable: return self._xhtml @xhtml.setter - def xhtml(self, val) -> None: + def xhtml(self, val: bool) -> None: self._validate_option("xhtml", val) self._xhtml = val @@ -722,35 +860,35 @@ class PrettyTable: self._min_width[field] = val @property - def min_table_width(self): + def min_table_width(self) -> int | None: return self._min_table_width @min_table_width.setter - def min_table_width(self, val) -> None: + def min_table_width(self, val: int) -> None: self._validate_option("min_table_width", val) self._min_table_width = val @property - def max_table_width(self): + def max_table_width(self) -> int | None: return self._max_table_width @max_table_width.setter - def max_table_width(self, val) -> None: + def max_table_width(self, val: int) -> None: self._validate_option("max_table_width", val) self._max_table_width = val @property - def fields(self): + def fields(self) -> Sequence[str | None] | None: """List or tuple of field names to include in displays""" return self._fields @fields.setter - def fields(self, val) -> None: + def fields(self, val: Sequence[str | None]) -> None: self._validate_option("fields", val) self._fields = val @property - def title(self): + def title(self) -> str | None: """Optional table title Arguments: @@ -759,11 +897,11 @@ class PrettyTable: return self._title @title.setter - def title(self, val) -> None: + def title(self, val: str) -> None: self._title = str(val) @property - def start(self): + def start(self) -> int: """Start index of the range of rows to print Arguments: @@ -772,12 +910,12 @@ class PrettyTable: return self._start @start.setter - def start(self, val) -> None: + def start(self, val: int) -> None: self._validate_option("start", val) self._start = val @property - def end(self): + def end(self) -> int | None: """End index of the range of rows to print Arguments: @@ -786,12 +924,12 @@ class PrettyTable: return self._end @end.setter - def end(self, val) -> None: + def end(self, val: int) -> None: self._validate_option("end", val) self._end = val @property - def sortby(self): + def sortby(self) -> str | None: """Name of field by which to sort rows Arguments: @@ -800,12 +938,12 @@ class PrettyTable: return self._sortby @sortby.setter - def sortby(self, val) -> None: + def sortby(self, val: str | None) -> None: self._validate_option("sortby", val) self._sortby = val @property - def reversesort(self): + def reversesort(self) -> bool: """Controls direction of sorting (ascending vs descending) Arguments: @@ -815,12 +953,12 @@ class PrettyTable: return self._reversesort @reversesort.setter - def reversesort(self, val) -> None: + def reversesort(self, val: bool) -> None: self._validate_option("reversesort", val) self._reversesort = val @property - def sort_key(self): + def sort_key(self) -> Callable[[RowType], SupportsRichComparison]: """Sorting key function, applied to data points before sorting Arguments: @@ -830,12 +968,12 @@ class PrettyTable: return self._sort_key @sort_key.setter - def sort_key(self, val) -> None: + def sort_key(self, val: Callable[[RowType], SupportsRichComparison]) -> None: self._validate_option("sort_key", val) self._sort_key = val @property - def header(self): + def header(self) -> bool: """Controls printing of table header with field names Arguments: @@ -844,12 +982,12 @@ class PrettyTable: return self._header @header.setter - def header(self, val) -> None: + def header(self, val: bool) -> None: self._validate_option("header", val) self._header = val @property - def header_style(self): + def header_style(self) -> HeaderStyleType: """Controls stylisation applied to field names in header Arguments: @@ -859,12 +997,12 @@ class PrettyTable: return self._header_style @header_style.setter - def header_style(self, val) -> None: + def header_style(self, val: HeaderStyleType) -> None: self._validate_header_style(val) self._header_style = val @property - def border(self): + def border(self) -> bool: """Controls printing of border around table Arguments: @@ -873,12 +1011,12 @@ class PrettyTable: return self._border @border.setter - def border(self, val) -> None: + def border(self, val: bool) -> None: self._validate_option("border", val) self._border = val @property - def preserve_internal_border(self): + def preserve_internal_border(self) -> bool: """Controls printing of border inside table Arguments: @@ -888,35 +1026,35 @@ class PrettyTable: return self._preserve_internal_border @preserve_internal_border.setter - def preserve_internal_border(self, val) -> None: + def preserve_internal_border(self, val: bool) -> None: self._validate_option("preserve_internal_border", val) self._preserve_internal_border = val @property - def hrules(self): + def hrules(self) -> HRuleStyle: """Controls printing of horizontal rules after rows Arguments: - hrules - horizontal rules style. Allowed values: FRAME, ALL, HEADER, NONE""" + hrules - horizontal rules style. Allowed values: HRuleStyle""" return self._hrules @hrules.setter - def hrules(self, val) -> None: + def hrules(self, val: HRuleStyle) -> None: self._validate_option("hrules", val) self._hrules = val @property - def vrules(self): + def vrules(self) -> VRuleStyle: """Controls printing of vertical rules between columns Arguments: - vrules - vertical rules style. Allowed values: FRAME, ALL, NONE""" + vrules - vertical rules style. Allowed values: VRuleStyle""" return self._vrules @vrules.setter - def vrules(self, val) -> None: + def vrules(self, val: VRuleStyle) -> None: self._validate_option("vrules", val) self._vrules = val @@ -979,7 +1117,7 @@ class PrettyTable: raise TypeError(msg) @property - def padding_width(self): + def padding_width(self) -> int: """The number of empty spaces between a column's edge and its content Arguments: @@ -988,12 +1126,12 @@ class PrettyTable: return self._padding_width @padding_width.setter - def padding_width(self, val) -> None: + def padding_width(self, val: int) -> None: self._validate_option("padding_width", val) self._padding_width = val @property - def left_padding_width(self): + def left_padding_width(self) -> int | None: """The number of empty spaces between a column's left edge and its content Arguments: @@ -1002,12 +1140,12 @@ class PrettyTable: return self._left_padding_width @left_padding_width.setter - def left_padding_width(self, val) -> None: + def left_padding_width(self, val: int) -> None: self._validate_option("left_padding_width", val) self._left_padding_width = val @property - def right_padding_width(self): + def right_padding_width(self) -> int | None: """The number of empty spaces between a column's right edge and its content Arguments: @@ -1016,12 +1154,12 @@ class PrettyTable: return self._right_padding_width @right_padding_width.setter - def right_padding_width(self, val) -> None: + def right_padding_width(self, val: int) -> None: self._validate_option("right_padding_width", val) self._right_padding_width = val @property - def vertical_char(self): + def vertical_char(self) -> str: """The character used when printing table borders to draw vertical lines Arguments: @@ -1030,13 +1168,13 @@ class PrettyTable: return self._vertical_char @vertical_char.setter - def vertical_char(self, val) -> None: + def vertical_char(self, val: str) -> None: val = str(val) self._validate_option("vertical_char", val) self._vertical_char = val @property - def horizontal_char(self): + def horizontal_char(self) -> str: """The character used when printing table borders to draw horizontal lines Arguments: @@ -1045,13 +1183,13 @@ class PrettyTable: return self._horizontal_char @horizontal_char.setter - def horizontal_char(self, val) -> None: + def horizontal_char(self, val: str) -> None: val = str(val) self._validate_option("horizontal_char", val) self._horizontal_char = val @property - def horizontal_align_char(self): + def horizontal_align_char(self) -> str: """The character used to indicate column alignment in horizontal lines Arguments: @@ -1060,13 +1198,13 @@ class PrettyTable: return self._bottom_left_junction_char or self.junction_char @horizontal_align_char.setter - def horizontal_align_char(self, val) -> None: + def horizontal_align_char(self, val: str) -> None: val = str(val) self._validate_option("horizontal_align_char", val) self._horizontal_align_char = val @property - def junction_char(self): + def junction_char(self) -> str: """The character used when printing table borders to draw line junctions Arguments: @@ -1075,13 +1213,13 @@ class PrettyTable: return self._junction_char @junction_char.setter - def junction_char(self, val) -> None: + def junction_char(self, val: str) -> None: val = str(val) self._validate_option("junction_char", val) self._junction_char = val @property - def top_junction_char(self): + def top_junction_char(self) -> str: """The character used when printing table borders to draw top line junctions Arguments: @@ -1090,13 +1228,13 @@ class PrettyTable: return self._top_junction_char or self.junction_char @top_junction_char.setter - def top_junction_char(self, val) -> None: + def top_junction_char(self, val: str) -> None: val = str(val) self._validate_option("top_junction_char", val) self._top_junction_char = val @property - def bottom_junction_char(self): + def bottom_junction_char(self) -> str: """The character used when printing table borders to draw bottom line junctions Arguments: @@ -1106,13 +1244,13 @@ class PrettyTable: return self._bottom_junction_char or self.junction_char @bottom_junction_char.setter - def bottom_junction_char(self, val) -> None: + def bottom_junction_char(self, val: str) -> None: val = str(val) self._validate_option("bottom_junction_char", val) self._bottom_junction_char = val @property - def right_junction_char(self): + def right_junction_char(self) -> str: """The character used when printing table borders to draw right line junctions Arguments: @@ -1122,13 +1260,13 @@ class PrettyTable: return self._right_junction_char or self.junction_char @right_junction_char.setter - def right_junction_char(self, val) -> None: + def right_junction_char(self, val: str) -> None: val = str(val) self._validate_option("right_junction_char", val) self._right_junction_char = val @property - def left_junction_char(self): + def left_junction_char(self) -> str: """The character used when printing table borders to draw left line junctions Arguments: @@ -1137,13 +1275,13 @@ class PrettyTable: return self._left_junction_char or self.junction_char @left_junction_char.setter - def left_junction_char(self, val) -> None: + def left_junction_char(self, val: str) -> None: val = str(val) self._validate_option("left_junction_char", val) self._left_junction_char = val @property - def top_right_junction_char(self): + def top_right_junction_char(self) -> str: """ The character used when printing table borders to draw top-right line junctions @@ -1154,13 +1292,13 @@ class PrettyTable: return self._top_right_junction_char or self.junction_char @top_right_junction_char.setter - def top_right_junction_char(self, val) -> None: + def top_right_junction_char(self, val: str) -> None: val = str(val) self._validate_option("top_right_junction_char", val) self._top_right_junction_char = val @property - def top_left_junction_char(self): + def top_left_junction_char(self) -> str: """ The character used when printing table borders to draw top-left line junctions @@ -1171,13 +1309,13 @@ class PrettyTable: return self._top_left_junction_char or self.junction_char @top_left_junction_char.setter - def top_left_junction_char(self, val) -> None: + def top_left_junction_char(self, val: str) -> None: val = str(val) self._validate_option("top_left_junction_char", val) self._top_left_junction_char = val @property - def bottom_right_junction_char(self): + def bottom_right_junction_char(self) -> str: """The character used when printing table borders to draw bottom-right line junctions @@ -1188,13 +1326,13 @@ class PrettyTable: return self._bottom_right_junction_char or self.junction_char @bottom_right_junction_char.setter - def bottom_right_junction_char(self, val) -> None: + def bottom_right_junction_char(self, val: str) -> None: val = str(val) self._validate_option("bottom_right_junction_char", val) self._bottom_right_junction_char = val @property - def bottom_left_junction_char(self): + def bottom_left_junction_char(self) -> str: """The character used when printing table borders to draw bottom-left line junctions @@ -1205,13 +1343,13 @@ class PrettyTable: return self._bottom_left_junction_char or self.junction_char @bottom_left_junction_char.setter - def bottom_left_junction_char(self, val) -> None: + def bottom_left_junction_char(self, val: str) -> None: val = str(val) self._validate_option("bottom_left_junction_char", val) self._bottom_left_junction_char = val @property - def format(self): + def format(self) -> bool: """Controls whether or not HTML tables are formatted to match styling options Arguments: @@ -1220,12 +1358,12 @@ class PrettyTable: return self._format @format.setter - def format(self, val) -> None: + def format(self, val: bool) -> None: self._validate_option("format", val) self._format = val @property - def print_empty(self): + def print_empty(self) -> bool: """Controls whether or not empty tables produce a header and frame or just an empty string @@ -1235,12 +1373,12 @@ class PrettyTable: return self._print_empty @print_empty.setter - def print_empty(self, val) -> None: + def print_empty(self, val: bool) -> None: self._validate_option("print_empty", val) self._print_empty = val @property - def attributes(self): + def attributes(self) -> dict[str, str]: """A dictionary of HTML attribute name/value pairs to be included in the <table> tag when printing HTML @@ -1250,37 +1388,37 @@ class PrettyTable: return self._attributes @attributes.setter - def attributes(self, val) -> None: + def attributes(self, val: dict[str, str]) -> None: self._validate_option("attributes", val) self._attributes = val @property - def oldsortslice(self): + def oldsortslice(self) -> bool: """oldsortslice - Slice rows before sorting in the "old style" """ return self._oldsortslice @oldsortslice.setter - def oldsortslice(self, val) -> None: + def oldsortslice(self, val: bool) -> None: self._validate_option("oldsortslice", val) self._oldsortslice = val @property - def escape_header(self): + def escape_header(self) -> bool: """Escapes the text within a header (True or False)""" return self._escape_header @escape_header.setter - def escape_header(self, val): + def escape_header(self, val: bool) -> None: self._validate_option("escape_header", val) self._escape_header = val @property - def escape_data(self): + def escape_data(self) -> bool: """Escapes the text within a data field (True or False)""" return self._escape_data @escape_data.setter - def escape_data(self, val): + def escape_data(self, val: bool) -> None: self._validate_option("escape_data", val) self._escape_data = val @@ -1288,37 +1426,37 @@ class PrettyTable: # OPTION MIXER # ############################## - def _get_options(self, kwargs): - options = {} + def _get_options(self, kwargs: Mapping[str, Any]) -> OptionsType: + options: dict[str, Any] = {} for option in self._options: if option in kwargs: self._validate_option(option, kwargs[option]) options[option] = kwargs[option] else: options[option] = getattr(self, option) - return options + return cast(OptionsType, options) ############################## # PRESET STYLE LOGIC # ############################## - def set_style(self, style) -> None: + def set_style(self, style: TableStyle) -> None: self._style = style - if style == DEFAULT: + if style == TableStyle.DEFAULT: self._set_default_style() - elif style == MSWORD_FRIENDLY: + elif style == TableStyle.MSWORD_FRIENDLY: self._set_msword_style() - elif style == PLAIN_COLUMNS: + elif style == TableStyle.PLAIN_COLUMNS: self._set_columns_style() - elif style == MARKDOWN: + elif style == TableStyle.MARKDOWN: self._set_markdown_style() - elif style == ORGMODE: + elif style == TableStyle.ORGMODE: self._set_orgmode_style() - elif style == DOUBLE_BORDER: + elif style == TableStyle.DOUBLE_BORDER: self._set_double_border_style() - elif style == SINGLE_BORDER: + elif style == TableStyle.SINGLE_BORDER: self._set_single_border_style() - elif style == RANDOM: + elif style == TableStyle.RANDOM: self._set_random_style() else: msg = "Invalid pre-set style" @@ -1331,7 +1469,7 @@ class PrettyTable: def _set_markdown_style(self) -> None: self.header = True self.border = True - self._hrules = None + self._hrules = HRuleStyle.HEADER self.padding_width = 1 self.left_padding_width = 1 self.right_padding_width = 1 @@ -1342,8 +1480,8 @@ class PrettyTable: def _set_default_style(self) -> None: self.header = True self.border = True - self._hrules = FRAME - self._vrules = ALL + self._hrules = HRuleStyle.FRAME + self._vrules = VRuleStyle.ALL self.padding_width = 1 self.left_padding_width = 1 self.right_padding_width = 1 @@ -1363,7 +1501,7 @@ class PrettyTable: def _set_msword_style(self) -> None: self.header = True self.border = True - self._hrules = NONE + self._hrules = HRuleStyle.NONE self.padding_width = 1 self.left_padding_width = 1 self.right_padding_width = 1 @@ -1408,8 +1546,8 @@ class PrettyTable: self.header = random.choice((True, False)) self.border = random.choice((True, False)) - self._hrules = random.choice((ALL, FRAME, HEADER, NONE)) - self._vrules = random.choice((ALL, FRAME, NONE)) + self._hrules = random.choice(list(HRuleStyle)) + self._vrules = random.choice(list(VRuleStyle)) self.left_padding_width = random.randint(0, 5) self.right_padding_width = random.randint(0, 5) self.vertical_char = random.choice(r"~!@#$%^&*()_+|-=\{}[];':\",./;<>?") @@ -1421,7 +1559,7 @@ class PrettyTable: # DATA INPUT METHODS # ############################## - def add_rows(self, rows) -> None: + def add_rows(self, rows: Iterable[RowType]) -> None: """Add rows to the table Arguments: @@ -1431,7 +1569,7 @@ class PrettyTable: for row in rows: self.add_row(row) - def add_row(self, row, *, divider: bool = False) -> None: + def add_row(self, row: RowType, *, divider: bool = False) -> None: """Add a row to the table Arguments: @@ -1450,7 +1588,7 @@ class PrettyTable: self._rows.append(list(row)) self._dividers.append(divider) - def del_row(self, row_index) -> None: + def del_row(self, row_index: int) -> None: """Delete a row from the table Arguments: @@ -1467,7 +1605,11 @@ class PrettyTable: del self._dividers[row_index] def add_column( - self, fieldname, column, align: str = "c", valign: str = "t" + self, + fieldname: str, + column: Sequence[Any], + align: AlignType = "c", + valign: VAlignType = "t", ) -> None: """Add a column to the table. @@ -1509,7 +1651,7 @@ class PrettyTable: for i, row in enumerate(self._rows): row.insert(0, i + 1) - def del_column(self, fieldname) -> None: + def del_column(self, fieldname: str) -> None: """Delete a column from the table Arguments: @@ -1549,7 +1691,7 @@ class PrettyTable: # MISC PUBLIC METHODS # ############################## - def copy(self): + def copy(self) -> Self: import copy return copy.deepcopy(self) @@ -1582,7 +1724,7 @@ class PrettyTable: # MISC PRIVATE METHODS # ############################## - def _format_value(self, field, value): + def _format_value(self, field: str, value: Any) -> str: if isinstance(value, int) and field in self._int_format: return (f"%{self._int_format[field]}d") % value elif isinstance(value, float) and field in self._float_format: @@ -1591,10 +1733,10 @@ class PrettyTable: formatter = self._custom_format.get(field, (lambda f, v: str(v))) return formatter(field, value) - def _compute_table_width(self, options): - if options["vrules"] == FRAME: + def _compute_table_width(self, options) -> int: + if options["vrules"] == VRuleStyle.FRAME: table_width = 2 - if options["vrules"] == ALL: + if options["vrules"] == VRuleStyle.ALL: table_width = 1 else: table_width = 0 @@ -1606,7 +1748,7 @@ class PrettyTable: table_width += self._widths[index] + per_col_padding + 1 return table_width - def _compute_widths(self, rows, options) -> None: + def _compute_widths(self, rows: list[list[str]], options: OptionsType) -> None: if options["header"]: widths = [_get_size(field)[0] for field in self._field_names] else: @@ -1615,9 +1757,11 @@ class PrettyTable: for row in rows: for index, value in enumerate(row): fieldname = self.field_names[index] - if self.none_format.get(fieldname) is not None: - if value == "None" or value is None: - value = self.none_format.get(fieldname) + if ( + value == "None" + and (none_val := self.none_format.get(fieldname)) is not None + ): + value = none_val if fieldname in self.max_width: widths[index] = max( widths[index], @@ -1628,7 +1772,7 @@ class PrettyTable: if fieldname in self.min_width: widths[index] = max(widths[index], self.min_width[fieldname]) - if self._style == MARKDOWN: + if self._style == TableStyle.MARKDOWN: # Markdown needs at least one hyphen in the divider if self._align[fieldname] in ("l", "r"): min_width = 1 @@ -1654,7 +1798,7 @@ class PrettyTable: if self._min_table_width or options["title"]: if options["title"]: title_width = len(options["title"]) + per_col_padding - if options["vrules"] in (FRAME, ALL): + if options["vrules"] in (VRuleStyle.FRAME, VRuleStyle.ALL): title_width += 2 else: title_width = 0 @@ -1680,7 +1824,7 @@ class PrettyTable: widths[-1] += min_width - sum(widths) self._widths = widths - def _get_padding_widths(self, options): + def _get_padding_widths(self, options: OptionsType) -> tuple[int, int]: if options["left_padding_width"] is not None: lpad = options["left_padding_width"] else: @@ -1691,7 +1835,7 @@ class PrettyTable: rpad = options["padding_width"] return lpad, rpad - def _get_rows(self, options): + def _get_rows(self, options: OptionsType) -> list[RowType]: """Return only those data rows that should be printed, based on slicing and sorting. @@ -1721,7 +1865,7 @@ class PrettyTable: return rows - def _get_dividers(self, options): + def _get_dividers(self, options: OptionsType) -> list[bool]: """Return only those dividers that should be printed, based on slicing. Arguments: @@ -1739,13 +1883,13 @@ class PrettyTable: return dividers - def _format_row(self, row): + def _format_row(self, row: RowType) -> list[str]: return [ self._format_value(field, value) for (field, value) in zip(self._field_names, row) ] - def _format_rows(self, rows): + def _format_rows(self, rows: list[RowType]) -> list[list[str]]: return [self._format_row(row) for row in rows] ############################## @@ -1766,9 +1910,9 @@ class PrettyTable: preserve_internal_border - print a border inside the table even if border is disabled (True or False) hrules - controls printing of horizontal rules after rows. - Allowed values: ALL, FRAME, HEADER, NONE + Allowed values: HRuleStyle vrules - controls printing of vertical rules between columns. - Allowed values: FRAME, ALL, NONE + Allowed values: VRuleStyle int_format - controls formatting of integer data float_format - controls formatting of floating point data custom_format - controls formatting of any column using callable @@ -1802,7 +1946,7 @@ class PrettyTable: options = self._get_options(kwargs) - lines = [] + lines: list[str] = [] # Don't think too hard about an empty table # Is this the desired behaviour? Maybe we should still print the header? @@ -1828,11 +1972,18 @@ class PrettyTable: # Add header or top of border if options["header"]: lines.append(self._stringify_header(options)) - elif options["border"] and options["hrules"] in (ALL, FRAME): + elif options["border"] and options["hrules"] in ( + HRuleStyle.ALL, + HRuleStyle.FRAME, + ): lines.append(self._stringify_hrule(options, where="top_")) - if title and options["vrules"] in (ALL, FRAME): + if title and options["vrules"] in (VRuleStyle.ALL, VRuleStyle.FRAME): + left_j_len = len(self.left_junction_char) + right_j_len = len(self.right_junction_char) lines[-1] = ( - self.left_junction_char + lines[-1][1:-1] + self.right_junction_char + self.left_junction_char + + lines[-1][left_j_len:-right_j_len] + + self.right_junction_char ) # Add rows @@ -1850,29 +2001,33 @@ class PrettyTable: ) # Add bottom of border - if options["border"] and options["hrules"] == FRAME: + if options["border"] and options["hrules"] == HRuleStyle.FRAME: lines.append(self._stringify_hrule(options, where="bottom_")) if "orgmode" in self.__dict__ and self.orgmode: + left_j_len = len(self.left_junction_char) + right_j_len = len(self.right_junction_char) lines = [ - "|" + new_line[1:-1] + "|" + "|" + new_line[left_j_len:-right_j_len] + "|" for old_line in lines for new_line in old_line.split("\n") ] return "\n".join(lines) - def _stringify_hrule(self, options, where: str = ""): + def _stringify_hrule( + self, options: OptionsType, where: Literal["top_", "bottom_", ""] = "" + ) -> str: if not options["border"] and not options["preserve_internal_border"]: return "" lpad, rpad = self._get_padding_widths(options) - if options["vrules"] in (ALL, FRAME): - bits = [options[where + "left_junction_char"]] + if options["vrules"] in (VRuleStyle.ALL, VRuleStyle.FRAME): + bits = [options[where + "left_junction_char"]] # type: ignore[literal-required] else: bits = [options["horizontal_char"]] # For tables with no data or fieldnames if not self._field_names: - bits.append(options[where + "right_junction_char"]) + bits.append(options[where + "right_junction_char"]) # type: ignore[literal-required] return "".join(bits) for field, width in zip(self._field_names, self._widths): if options["fields"] and field not in options["fields"]: @@ -1888,33 +2043,34 @@ class PrettyTable: line = line[:-2] + self._horizontal_align_char + " " bits.append(line) - if options["vrules"] == ALL: - bits.append(options[where + "junction_char"]) + if options["vrules"] == VRuleStyle.ALL: + bits.append(options[where + "junction_char"]) # type: ignore[literal-required] else: bits.append(options["horizontal_char"]) - if options["vrules"] in (ALL, FRAME): + if options["vrules"] in (VRuleStyle.ALL, VRuleStyle.FRAME): bits.pop() - bits.append(options[where + "right_junction_char"]) + bits.append(options[where + "right_junction_char"]) # type: ignore[literal-required] if options["preserve_internal_border"] and not options["border"]: bits = bits[1:-1] return "".join(bits) - def _stringify_title(self, title, options): - lines = [] + def _stringify_title(self, title: str, options: OptionsType) -> str: + lines: list[str] = [] lpad, rpad = self._get_padding_widths(options) if options["border"]: - if options["vrules"] == ALL: - options["vrules"] = FRAME + if options["vrules"] == VRuleStyle.ALL: + options["vrules"] = VRuleStyle.FRAME lines.append(self._stringify_hrule(options, "top_")) - options["vrules"] = ALL - elif options["vrules"] == FRAME: + options["vrules"] = VRuleStyle.ALL + elif options["vrules"] == VRuleStyle.FRAME: lines.append(self._stringify_hrule(options, "top_")) - bits = [] + bits: list[str] = [] endpoint = ( options["vertical_char"] - if options["vrules"] in (ALL, FRAME) and options["border"] + if options["vrules"] in (VRuleStyle.ALL, VRuleStyle.FRAME) + and options["border"] else " " ) bits.append(endpoint) @@ -1927,13 +2083,16 @@ class PrettyTable: lines.append("".join(bits)) return "\n".join(lines) - def _stringify_header(self, options): - bits = [] + def _stringify_header(self, options: OptionsType) -> str: + bits: list[str] = [] lpad, rpad = self._get_padding_widths(options) if options["border"]: - if options["hrules"] in (ALL, FRAME): + if options["hrules"] in (HRuleStyle.ALL, HRuleStyle.FRAME): bits.append(self._stringify_hrule(options, "top_")) - if options["title"] and options["vrules"] in (ALL, FRAME): + if options["title"] and options["vrules"] in ( + VRuleStyle.ALL, + VRuleStyle.FRAME, + ): left_j_len = len(self.left_junction_char) right_j_len = len(self.right_junction_char) bits[-1] = ( @@ -1942,13 +2101,13 @@ class PrettyTable: + self.right_junction_char ) bits.append("\n") - if options["vrules"] in (ALL, FRAME): + if options["vrules"] in (VRuleStyle.ALL, VRuleStyle.FRAME): bits.append(options["vertical_char"]) else: bits.append(" ") # For tables with no data or field names if not self._field_names: - if options["vrules"] in (ALL, FRAME): + if options["vrules"] in (VRuleStyle.ALL, VRuleStyle.FRAME): bits.append(options["vertical_char"]) else: bits.append(" ") @@ -1973,7 +2132,7 @@ class PrettyTable: + " " * rpad ) if options["border"] or options["preserve_internal_border"]: - if options["vrules"] == ALL: + if options["vrules"] == VRuleStyle.ALL: bits.append(options["vertical_char"]) else: bits.append(" ") @@ -1985,17 +2144,17 @@ class PrettyTable: bits.append(" ") # If vrules is FRAME, then we just appended a space at the end # of the last field, when we really want a vertical character - if options["border"] and options["vrules"] == FRAME: + if options["border"] and options["vrules"] == VRuleStyle.FRAME: bits.pop() bits.append(options["vertical_char"]) if (options["border"] or options["preserve_internal_border"]) and options[ "hrules" - ] != NONE: + ] != HRuleStyle.NONE: bits.append("\n") bits.append(self._hrule) return "".join(bits) - def _stringify_row(self, row, options, hrule): + def _stringify_row(self, row: list[str], options: OptionsType, hrule: str) -> str: import textwrap for index, field, value, width in zip( @@ -2003,10 +2162,13 @@ class PrettyTable: ): # Enforce max widths lines = value.split("\n") - new_lines = [] + new_lines: list[str] = [] for line in lines: - if line == "None" and self.none_format.get(field) is not None: - line = self.none_format[field] + if ( + line == "None" + and (none_val := self.none_format.get(field)) is not None + ): + line = none_val if _str_block_width(line) > width: line = textwrap.fill(line, width) new_lines.append(line) @@ -2020,12 +2182,12 @@ class PrettyTable: if h > row_height: row_height = h - bits = [] + bits: list[list[str]] = [] lpad, rpad = self._get_padding_widths(options) for y in range(0, row_height): bits.append([]) if options["border"]: - if options["vrules"] in (ALL, FRAME): + if options["vrules"] in (VRuleStyle.ALL, VRuleStyle.FRAME): bits[y].append(self.vertical_char) else: bits[y].append(" ") @@ -2046,8 +2208,7 @@ class PrettyTable: else: lines = lines + [""] * d_height - y = 0 - for line in lines: + for y, line in enumerate(lines): if options["fields"] and field not in options["fields"]: continue @@ -2057,11 +2218,10 @@ class PrettyTable: + " " * rpad ) if options["border"] or options["preserve_internal_border"]: - if options["vrules"] == ALL: + if options["vrules"] == VRuleStyle.ALL: bits[y].append(self.vertical_char) else: bits[y].append(" ") - y += 1 # If only preserve_internal_border is true, then we just appended # a vertical character at the end when we wanted a space @@ -2072,21 +2232,19 @@ class PrettyTable: # If vrules is FRAME, then we just appended a space at the end # of the last field, when we really want a vertical character for y in range(0, row_height): - if options["border"] and options["vrules"] == FRAME: + if options["border"] and options["vrules"] == VRuleStyle.FRAME: bits[y].pop() bits[y].append(options["vertical_char"]) - if options["border"] and options["hrules"] == ALL: + if options["border"] and options["hrules"] == HRuleStyle.ALL: bits[row_height - 1].append("\n") bits[row_height - 1].append(hrule) - for y in range(0, row_height): - bits[y] = "".join(bits[y]) - - return "\n".join(bits) + bits_str = ["".join(bits_y) for bits_y in bits] + return "\n".join(bits_str) - def paginate(self, page_length: int = 58, line_break: str = "\f", **kwargs): - pages = [] + def paginate(self, page_length: int = 58, line_break: str = "\f", **kwargs) -> str: + pages: list[str] = [] kwargs["start"] = kwargs.get("start", 0) true_end = kwargs.get("end", self.rowcount) while True: @@ -2152,7 +2310,11 @@ class PrettyTable: import json options = self._get_options(kwargs) - json_options: Any = {"indent": 4, "separators": (",", ": "), "sort_keys": True} + json_options: dict[str, Any] = { + "indent": 4, + "separators": (",", ": "), + "sort_keys": True, + } json_options.update( {key: value for key, value in kwargs.items() if key not in options} ) @@ -2199,9 +2361,9 @@ class PrettyTable: preserve_internal_border - print a border inside the table even if border is disabled (True or False) hrules - controls printing of horizontal rules after rows. - Allowed values: ALL, FRAME, HEADER, NONE + Allowed values: HRuleStyle vrules - controls printing of vertical rules between columns. - Allowed values: FRAME, ALL, NONE + Allowed values: VRuleStyle int_format - controls formatting of integer data float_format - controls formatting of floating point data custom_format - controls formatting of any column using callable @@ -2227,10 +2389,10 @@ class PrettyTable: return string - def _get_simple_html_string(self, options): + def _get_simple_html_string(self, options: OptionsType) -> str: from html import escape - lines = [] + lines: list[str] = [] if options["xhtml"]: linebreak = "<br/>" else: @@ -2238,10 +2400,8 @@ class PrettyTable: open_tag = ["<table"] if options["attributes"]: - for attr_name in options["attributes"]: - open_tag.append( - f' {escape(attr_name)}="{escape(options["attributes"][attr_name])}"' - ) + for attr_name, attr_value in options["attributes"].items(): + open_tag.append(f' {escape(attr_name)}="{escape(attr_value)}"') open_tag.append(">") lines.append("".join(open_tag)) @@ -2288,10 +2448,10 @@ class PrettyTable: return "\n".join(lines) - def _get_formatted_html_string(self, options): + def _get_formatted_html_string(self, options: OptionsType) -> str: from html import escape - lines = [] + lines: list[str] = [] lpad, rpad = self._get_padding_widths(options) if options["xhtml"]: linebreak = "<br/>" @@ -2300,27 +2460,34 @@ class PrettyTable: open_tag = ["<table"] if options["border"]: - if options["hrules"] == ALL and options["vrules"] == ALL: + if ( + options["hrules"] == HRuleStyle.ALL + and options["vrules"] == VRuleStyle.ALL + ): open_tag.append(' frame="box" rules="all"') - elif options["hrules"] == FRAME and options["vrules"] == FRAME: + elif ( + options["hrules"] == HRuleStyle.FRAME + and options["vrules"] == VRuleStyle.FRAME + ): open_tag.append(' frame="box"') - elif options["hrules"] == FRAME and options["vrules"] == ALL: + elif ( + options["hrules"] == HRuleStyle.FRAME + and options["vrules"] == VRuleStyle.ALL + ): open_tag.append(' frame="box" rules="cols"') - elif options["hrules"] == FRAME: + elif options["hrules"] == HRuleStyle.FRAME: open_tag.append(' frame="hsides"') - elif options["hrules"] == ALL: + elif options["hrules"] == HRuleStyle.ALL: open_tag.append(' frame="hsides" rules="rows"') - elif options["vrules"] == FRAME: + elif options["vrules"] == VRuleStyle.FRAME: open_tag.append(' frame="vsides"') - elif options["vrules"] == ALL: + elif options["vrules"] == VRuleStyle.ALL: open_tag.append(' frame="vsides" rules="cols"') if not options["border"] and options["preserve_internal_border"]: open_tag.append(' rules="cols"') if options["attributes"]: - for attr_name in options["attributes"]: - open_tag.append( - f' {escape(attr_name)}="{escape(options["attributes"][attr_name])}"' - ) + for attr_name, attr_value in options["attributes"].items(): + open_tag.append(f' {escape(attr_name)}="{escape(attr_value)}"') open_tag.append(">") lines.append("".join(open_tag)) @@ -2350,8 +2517,8 @@ class PrettyTable: lines.append(" <tbody>") rows = self._get_rows(options) formatted_rows = self._format_rows(rows) - aligns = [] - valigns = [] + aligns: list[str] = [] + valigns: list[str] = [] for field in self._field_names: aligns.append( {"l": "left", "r": "right", "c": "center"}[self._align[field]] @@ -2403,9 +2570,9 @@ class PrettyTable: preserve_internal_border - print a border inside the table even if border is disabled (True or False) hrules - controls printing of horizontal rules after rows. - Allowed values: ALL, FRAME, HEADER, NONE + Allowed values: HRuleStyle vrules - controls printing of vertical rules between columns. - Allowed values: FRAME, ALL, NONE + Allowed values: VRuleStyle int_format - controls formatting of integer data float_format - controls formatting of floating point data sortby - name of field to sort rows by @@ -2421,8 +2588,8 @@ class PrettyTable: string = self._get_simple_latex_string(options) return string - def _get_simple_latex_string(self, options): - lines = [] + def _get_simple_latex_string(self, options: OptionsType) -> str: + lines: list[str] = [] wanted_fields = [] if options["fields"]: @@ -2454,10 +2621,10 @@ class PrettyTable: return "\r\n".join(lines) - def _get_formatted_latex_string(self, options): - lines = [] + def _get_formatted_latex_string(self, options: OptionsType) -> str: + lines: list[str] = [] - wanted_fields = [] + wanted_fields: list[str] = [] if options["fields"]: wanted_fields = [ field for field in self._field_names if field in options["fields"] @@ -2466,19 +2633,25 @@ class PrettyTable: wanted_fields = self._field_names wanted_alignments = [self._align[field] for field in wanted_fields] - if options["border"] and options["vrules"] == ALL: + if options["border"] and options["vrules"] == VRuleStyle.ALL: alignment_str = "|".join(wanted_alignments) elif not options["border"] and options["preserve_internal_border"]: alignment_str = "|".join(wanted_alignments) else: alignment_str = "".join(wanted_alignments) - if options["border"] and options["vrules"] in [ALL, FRAME]: + if options["border"] and options["vrules"] in [ + VRuleStyle.ALL, + VRuleStyle.FRAME, + ]: alignment_str = "|" + alignment_str + "|" begin_cmd = f"\\begin{{tabular}}{{{alignment_str}}}" lines.append(begin_cmd) - if options["border"] and options["hrules"] in [ALL, FRAME]: + if options["border"] and options["hrules"] in [ + HRuleStyle.ALL, + HRuleStyle.FRAME, + ]: lines.append("\\hline") # Headers @@ -2486,7 +2659,7 @@ class PrettyTable: lines.append(" & ".join(wanted_fields) + " \\\\") if (options["border"] or options["preserve_internal_border"]) and options[ "hrules" - ] in [ALL, HEADER]: + ] in [HRuleStyle.ALL, HRuleStyle.HEADER]: lines.append("\\hline") # Data @@ -2498,10 +2671,10 @@ class PrettyTable: d for f, d in zip(self._field_names, row) if f in wanted_fields ] lines.append(" & ".join(wanted_data) + " \\\\") - if options["border"] and options["hrules"] == ALL: + if options["border"] and options["hrules"] == HRuleStyle.ALL: lines.append("\\hline") - if options["border"] and options["hrules"] == FRAME: + if options["border"] and options["hrules"] == HRuleStyle.FRAME: lines.append("\\hline") lines.append("\\end{tabular}") @@ -2514,8 +2687,8 @@ class PrettyTable: ############################## -def _str_block_width(val): - import wcwidth # type: ignore[import-not-found] +def _str_block_width(val: str) -> int: + import wcwidth # type: ignore[import-untyped] return wcwidth.wcswidth(_re.sub("", val)) @@ -2525,7 +2698,7 @@ def _str_block_width(val): ############################## -def from_csv(fp, field_names: Any | None = None, **kwargs): +def from_csv(fp, field_names: Sequence[str] | None = None, **kwargs) -> PrettyTable: import csv fmtparams = {} @@ -2560,16 +2733,17 @@ def from_csv(fp, field_names: Any | None = None, **kwargs): return table -def from_db_cursor(cursor, **kwargs): +def from_db_cursor(cursor: Cursor, **kwargs) -> PrettyTable | None: if cursor.description: table = PrettyTable(**kwargs) table.field_names = [col[0] for col in cursor.description] for row in cursor.fetchall(): table.add_row(row) return table + return None -def from_json(json_string, **kwargs): +def from_json(json_string: str | bytes, **kwargs) -> PrettyTable: import json table = PrettyTable(**kwargs) @@ -2585,29 +2759,29 @@ class TableHandler(HTMLParser): def __init__(self, **kwargs) -> None: HTMLParser.__init__(self) self.kwargs = kwargs - self.tables: list[list] = [] + self.tables: list[PrettyTable] = [] self.last_row: list[str] = [] - self.rows: list[Any] = [] + self.rows: list[tuple[list[str], bool]] = [] self.max_row_width = 0 - self.active = None + self.active: str | None = None self.last_content = "" self.is_last_row_header = False self.colspan = 0 - def handle_starttag(self, tag, attrs) -> None: + def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: self.active = tag if tag == "th": self.is_last_row_header = True for key, value in attrs: if key == "colspan": - self.colspan = int(value) + self.colspan = int(value) # type: ignore[arg-type] - def handle_endtag(self, tag) -> None: + def handle_endtag(self, tag: str) -> None: if tag in ["th", "td"]: stripped_content = self.last_content.strip() self.last_row.append(stripped_content) if self.colspan: - for i in range(1, self.colspan): + for _ in range(1, self.colspan): self.last_row.append("") self.colspan = 0 @@ -2623,10 +2797,10 @@ class TableHandler(HTMLParser): self.last_content = " " self.active = None - def handle_data(self, data) -> None: + def handle_data(self, data: str) -> None: self.last_content += data - def generate_table(self, rows): + def generate_table(self, rows: list[tuple[list[str], bool]]) -> PrettyTable: """ Generates from a list of rows a PrettyTable object. """ @@ -2644,7 +2818,7 @@ class TableHandler(HTMLParser): table.add_row(row[0]) return table - def make_fields_unique(self, fields) -> None: + def make_fields_unique(self, fields: list[str]) -> None: """ iterates over the row and make each field unique """ @@ -2654,7 +2828,7 @@ class TableHandler(HTMLParser): fields[j] += "'" -def from_html(html_code, **kwargs): +def from_html(html_code: str, **kwargs) -> list[PrettyTable]: """ Generates a list of PrettyTables from a string of HTML code. Each <table> in the HTML becomes one PrettyTable object. @@ -2665,9 +2839,9 @@ def from_html(html_code, **kwargs): return parser.tables -def from_html_one(html_code, **kwargs): +def from_html_one(html_code: str, **kwargs) -> PrettyTable: """ - Generates a PrettyTables from a string of HTML code which contains only a + Generates a PrettyTable from a string of HTML code which contains only a single <table> """ @@ -2678,3 +2852,23 @@ def from_html_one(html_code, **kwargs): msg = "More than one <table> in provided HTML code. Use from_html instead." raise ValueError(msg) return tables[0] + + +def _warn_deprecation(name: str, module_globals: dict[str, Any]) -> Any: + if (val := module_globals.get(f"_DEPRECATED_{name}")) is None: + msg = f"module '{__name__}' has no attribute '{name}" + raise AttributeError(msg) + module_globals[name] = val + if name in {"FRAME", "ALL", "NONE", "HEADER"}: + msg = ( + f"the '{name}' constant is deprecated, " + "use the 'HRuleStyle' and 'VRuleStyle' enums instead" + ) + else: + msg = f"the '{name}' constant is deprecated, use the 'TableStyle' enum instead" + warnings.warn(msg, DeprecationWarning, stacklevel=3) + return val + + +def __getattr__(name: str) -> Any: + return _warn_deprecation(name, module_globals=globals()) diff --git a/contrib/python/prettytable/py3/tests/test_colortable.py b/contrib/python/prettytable/py3/tests/test_colortable.py index 4668ed54dd..5055638438 100644 --- a/contrib/python/prettytable/py3/tests/test_colortable.py +++ b/contrib/python/prettytable/py3/tests/test_colortable.py @@ -105,7 +105,16 @@ class TestColorTableRendering: Tests the color table rendering using the default alignment (`'c'`) """ - def test_color_table_rendering(self) -> None: + @pytest.mark.parametrize( + ["with_title", "with_header"], + [ + (False, True), # the default + (True, True), # titled + (True, False), # titled, no header + (True, True), # both title and header + ], + ) + def test_color_table_rendering(self, with_title: bool, with_header: bool) -> None: """Tests the color table rendering using the default alignment (`'c'`)""" chars = { "+": "\x1b[36m+\x1b[0m\x1b[96m", @@ -140,18 +149,40 @@ class TestColorTableRendering: (plus + minus * 3) * 6 + plus, ) - header_str = str("\n".join(header)) - body_str = str("\n".join(body)) + if with_title: + header_str = str("\n".join(header)) + else: + header_str = str(header[2]) + if with_header: + body_str = str("\n".join(body)) + else: + body_str = str("\n".join(body[2:])) table = ColorTable( ("A", "B", "C", "D", "E", "F"), theme=Themes.OCEAN, ) - table.title = "Efforts" + if with_title: + table.title = "Efforts" + table.header = with_header table.add_row([1, 2, 3, 4, 5, 6]) expected = header_str + "\n" + body_str + "\x1b[0m" result = str(table) assert expected == result + + def test_all_themes(self) -> None: + """Tests rendering with all available themes""" + table = ColorTable( + ("A", "B", "C", "D", "E", "F"), + ) + table.title = "Theme Test" + table.add_row([1, 2, 3, 4, 5, 6]) + + for theme_name, theme in vars(Themes).items(): + if isinstance(theme, Theme): + table.theme = theme + result = str(table) + assert result # Simple check to ensure rendering doesn't fail diff --git a/contrib/python/prettytable/py3/tests/test_prettytable.py b/contrib/python/prettytable/py3/tests/test_prettytable.py index 5cebb89521..75254ca89a 100644 --- a/contrib/python/prettytable/py3/tests/test_prettytable.py +++ b/contrib/python/prettytable/py3/tests/test_prettytable.py @@ -12,19 +12,10 @@ from pytest_lazy_fixtures import lf import prettytable from prettytable import ( - ALL, - DEFAULT, - DOUBLE_BORDER, - FRAME, - HEADER, - MARKDOWN, - MSWORD_FRIENDLY, - NONE, - ORGMODE, - PLAIN_COLUMNS, - RANDOM, - SINGLE_BORDER, + HRuleStyle, PrettyTable, + TableStyle, + VRuleStyle, from_csv, from_db_cursor, from_html, @@ -314,22 +305,22 @@ def field_name_less_table() -> PrettyTable: class TestFieldNameLessTable: """Make sure that building and stringing a table with no fieldnames works fine""" - def test_can_string_ascii(self, field_name_less_table: prettytable) -> None: + def test_can_string_ascii(self, field_name_less_table: PrettyTable) -> None: output = field_name_less_table.get_string() assert "| Field 1 | Field 2 | Field 3 | Field 4 |" in output assert "| Adelaide | 1295 | 1158259 | 600.5 |" in output - def test_can_string_html(self, field_name_less_table: prettytable) -> None: + def test_can_string_html(self, field_name_less_table: PrettyTable) -> None: output = field_name_less_table.get_html_string() assert "<th>Field 1</th>" in output assert "<td>Adelaide</td>" in output - def test_can_string_latex(self, field_name_less_table: prettytable) -> None: + def test_can_string_latex(self, field_name_less_table: PrettyTable) -> None: output = field_name_less_table.get_latex_string() assert "Field 1 & Field 2 & Field 3 & Field 4 \\\\" in output assert "Adelaide & 1295 & 1158259 & 600.5 \\\\" in output - def test_add_field_names_later(self, field_name_less_table: prettytable) -> None: + def test_add_field_names_later(self, field_name_less_table: PrettyTable) -> None: field_name_less_table.field_names = [ "City name", "Area", @@ -376,21 +367,21 @@ class TestAlignment: """Make sure alignment works regardless of when it was set""" def test_aligned_ascii( - self, aligned_before_table: prettytable, aligned_after_table: prettytable + self, aligned_before_table: PrettyTable, aligned_after_table: PrettyTable ) -> None: before = aligned_before_table.get_string() after = aligned_after_table.get_string() assert before == after def test_aligned_html( - self, aligned_before_table: prettytable, aligned_after_table: prettytable + self, aligned_before_table: PrettyTable, aligned_after_table: PrettyTable ) -> None: before = aligned_before_table.get_html_string() after = aligned_after_table.get_html_string() assert before == after def test_aligned_latex( - self, aligned_before_table: prettytable, aligned_after_table: prettytable + self, aligned_before_table: PrettyTable, aligned_after_table: PrettyTable ) -> None: before = aligned_before_table.get_latex_string() after = aligned_after_table.get_latex_string() @@ -428,7 +419,7 @@ def city_data_from_csv() -> PrettyTable: class TestOptionOverride: """Make sure all options are properly overwritten by get_string.""" - def test_border(self, city_data_prettytable: prettytable) -> None: + def test_border(self, city_data_prettytable: PrettyTable) -> None: default = city_data_prettytable.get_string() override = city_data_prettytable.get_string(border=False) assert default != override @@ -440,12 +431,12 @@ class TestOptionOverride: def test_hrules_all(self, city_data_prettytable) -> None: default = city_data_prettytable.get_string() - override = city_data_prettytable.get_string(hrules=ALL) + override = city_data_prettytable.get_string(hrules=HRuleStyle.ALL) assert default != override def test_hrules_none(self, city_data_prettytable) -> None: default = city_data_prettytable.get_string() - override = city_data_prettytable.get_string(hrules=NONE) + override = city_data_prettytable.get_string(hrules=HRuleStyle.NONE) assert default != override @@ -535,12 +526,12 @@ class TestBasic: assert len(rows) == 7 assert rows[0] == ["Adelaide", 1295, 1158259, 600.5] - def _test_no_blank_lines(self, table: prettytable) -> None: + def _test_no_blank_lines(self, table: PrettyTable) -> None: string = table.get_string() lines = string.split("\n") assert "" not in lines - def _test_all_length_equal(self, table: prettytable) -> None: + def _test_all_length_equal(self, table: PrettyTable) -> None: string = table.get_string() lines = string.split("\n") lengths = [len(line) for line in lines] @@ -608,42 +599,42 @@ class TestBasic: self, city_data_prettytable: PrettyTable ) -> None: """No table should ever have blank lines in it.""" - city_data_prettytable.hrules = NONE + city_data_prettytable.hrules = HRuleStyle.NONE self._test_no_blank_lines(city_data_prettytable) def test_all_lengths_equal_with_hrules_none( self, city_data_prettytable: PrettyTable ) -> None: """All lines in a table should be of the same length.""" - city_data_prettytable.hrules = NONE + city_data_prettytable.hrules = HRuleStyle.NONE self._test_all_length_equal(city_data_prettytable) def test_no_blank_lines_with_hrules_all( self, city_data_prettytable: PrettyTable ) -> None: """No table should ever have blank lines in it.""" - city_data_prettytable.hrules = ALL + city_data_prettytable.hrules = HRuleStyle.ALL self._test_no_blank_lines(city_data_prettytable) def test_all_lengths_equal_with_hrules_all( self, city_data_prettytable: PrettyTable ) -> None: """All lines in a table should be of the same length.""" - city_data_prettytable.hrules = ALL + city_data_prettytable.hrules = HRuleStyle.ALL self._test_all_length_equal(city_data_prettytable) def test_no_blank_lines_with_style_msword( self, city_data_prettytable: PrettyTable ) -> None: """No table should ever have blank lines in it.""" - city_data_prettytable.set_style(MSWORD_FRIENDLY) + city_data_prettytable.set_style(TableStyle.MSWORD_FRIENDLY) self._test_no_blank_lines(city_data_prettytable) def test_all_lengths_equal_with_style_msword( self, city_data_prettytable: PrettyTable ) -> None: """All lines in a table should be of the same length.""" - city_data_prettytable.set_style(MSWORD_FRIENDLY) + city_data_prettytable.set_style(TableStyle.MSWORD_FRIENDLY) self._test_all_length_equal(city_data_prettytable) def test_no_blank_lines_with_int_format( @@ -850,7 +841,7 @@ class TestBreakLine: [ ( [["value 1", "value2\nsecond line"], ["value 3", "value4"]], - ALL, + HRuleStyle.ALL, """ +---------+-------------+ | Field 1 | Field 2 | @@ -867,7 +858,7 @@ class TestBreakLine: ["value 1", "value2\nsecond line"], ["value 3\n\nother line", "value4\n\n\nvalue5"], ], - ALL, + HRuleStyle.ALL, """ +------------+-------------+ | Field 1 | Field 2 | @@ -887,7 +878,7 @@ class TestBreakLine: ["value 1", "value2\nsecond line"], ["value 3\n\nother line", "value4\n\n\nvalue5"], ], - FRAME, + HRuleStyle.FRAME, """ +------------+-------------+ | Field 1 | Field 2 | @@ -916,7 +907,7 @@ class TestBreakLine: table = PrettyTable(["Field 1", "Field 2"]) table.add_row(["value 1", "value2\nsecond line"]) table.add_row(["value 3", "value4"]) - result = table.get_html_string(hrules=ALL) + result = table.get_html_string(hrules=HRuleStyle.ALL) assert ( result.strip() == """ @@ -1455,7 +1446,7 @@ class TestPositionalJunctions: """Verify different cases for positional-junction characters""" def test_default(self, city_data_prettytable: PrettyTable) -> None: - city_data_prettytable.set_style(DOUBLE_BORDER) + city_data_prettytable.set_style(TableStyle.DOUBLE_BORDER) assert ( city_data_prettytable.get_string().strip() @@ -1474,7 +1465,7 @@ class TestPositionalJunctions: ) def test_no_header(self, city_data_prettytable: PrettyTable) -> None: - city_data_prettytable.set_style(DOUBLE_BORDER) + city_data_prettytable.set_style(TableStyle.DOUBLE_BORDER) city_data_prettytable.header = False assert ( @@ -1492,7 +1483,7 @@ class TestPositionalJunctions: ) def test_with_title(self, city_data_prettytable: PrettyTable) -> None: - city_data_prettytable.set_style(DOUBLE_BORDER) + city_data_prettytable.set_style(TableStyle.DOUBLE_BORDER) city_data_prettytable.title = "Title" assert ( @@ -1514,7 +1505,7 @@ class TestPositionalJunctions: ) def test_with_title_no_header(self, city_data_prettytable: PrettyTable) -> None: - city_data_prettytable.set_style(DOUBLE_BORDER) + city_data_prettytable.set_style(TableStyle.DOUBLE_BORDER) city_data_prettytable.title = "Title" city_data_prettytable.header = False assert ( @@ -1534,9 +1525,9 @@ class TestPositionalJunctions: ) def test_hrule_all(self, city_data_prettytable: PrettyTable) -> None: - city_data_prettytable.set_style(DOUBLE_BORDER) + city_data_prettytable.set_style(TableStyle.DOUBLE_BORDER) city_data_prettytable.title = "Title" - city_data_prettytable.hrules = ALL + city_data_prettytable.hrules = HRuleStyle.ALL assert ( city_data_prettytable.get_string().strip() == """ @@ -1562,8 +1553,8 @@ class TestPositionalJunctions: ) def test_vrules_none(self, city_data_prettytable: PrettyTable) -> None: - city_data_prettytable.set_style(DOUBLE_BORDER) - city_data_prettytable.vrules = NONE + city_data_prettytable.set_style(TableStyle.DOUBLE_BORDER) + city_data_prettytable.vrules = VRuleStyle.NONE assert ( city_data_prettytable.get_string().strip() == "═══════════════════════════════════════════════════\n" @@ -1580,8 +1571,8 @@ class TestPositionalJunctions: ) def test_vrules_frame_with_title(self, city_data_prettytable: PrettyTable) -> None: - city_data_prettytable.set_style(DOUBLE_BORDER) - city_data_prettytable.vrules = FRAME + city_data_prettytable.set_style(TableStyle.DOUBLE_BORDER) + city_data_prettytable.vrules = VRuleStyle.FRAME city_data_prettytable.title = "Title" assert ( city_data_prettytable.get_string().strip() @@ -1607,7 +1598,7 @@ class TestStyle: "style, expected", [ pytest.param( - DEFAULT, + TableStyle.DEFAULT, """ +---+---------+---------+---------+ | | Field 1 | Field 2 | Field 3 | @@ -1620,7 +1611,7 @@ class TestStyle: id="DEFAULT", ), pytest.param( - MARKDOWN, # TODO fix + TableStyle.MARKDOWN, # TODO fix """ | | Field 1 | Field 2 | Field 3 | | :-: | :-----: | :-----: | :-----: | @@ -1631,7 +1622,7 @@ class TestStyle: id="MARKDOWN", ), pytest.param( - MSWORD_FRIENDLY, + TableStyle.MSWORD_FRIENDLY, """ | | Field 1 | Field 2 | Field 3 | | 1 | value 1 | value2 | value3 | @@ -1641,7 +1632,7 @@ class TestStyle: id="MSWORD_FRIENDLY", ), pytest.param( - ORGMODE, + TableStyle.ORGMODE, """ |---+---------+---------+---------| | | Field 1 | Field 2 | Field 3 | @@ -1654,7 +1645,7 @@ class TestStyle: id="ORGMODE", ), pytest.param( - PLAIN_COLUMNS, + TableStyle.PLAIN_COLUMNS, """ Field 1 Field 2 Field 3 1 value 1 value2 value3 @@ -1664,20 +1655,18 @@ class TestStyle: id="PLAIN_COLUMNS", ), pytest.param( - RANDOM, + TableStyle.RANDOM, """ -'^^^^^'^^^^^^^^^^^'^^^^^^^^^^'^^^^^^^^^^' -% 1% value 1% value2% value3% -'^^^^^'^^^^^^^^^^^'^^^^^^^^^^'^^^^^^^^^^' -% 4% value 4% value5% value6% -'^^^^^'^^^^^^^^^^^'^^^^^^^^^^'^^^^^^^^^^' -% 7% value 7% value8% value9% -'^^^^^'^^^^^^^^^^^'^^^^^^^^^^'^^^^^^^^^^' +'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^' +% 1 value 1 value2 value3% +% 4 value 4 value5 value6% +% 7 value 7 value8 value9% +'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^' """, id="RANDOM", ), pytest.param( - DOUBLE_BORDER, + TableStyle.DOUBLE_BORDER, """ ╔═══╦═════════╦═════════╦═════════╗ ║ ║ Field 1 ║ Field 2 ║ Field 3 ║ @@ -1689,7 +1678,7 @@ class TestStyle: """, ), pytest.param( - SINGLE_BORDER, + TableStyle.SINGLE_BORDER, """ ┌───┬─────────┬─────────┬─────────┐ │ │ Field 1 │ Field 2 │ Field 3 │ @@ -1721,13 +1710,13 @@ class TestStyle: # Act / Assert # This is an hrule style, not a table style with pytest.raises(ValueError): - t.set_style(ALL) + t.set_style(HRuleStyle.ALL) # type: ignore[arg-type] @pytest.mark.parametrize( "style, expected", [ pytest.param( - MARKDOWN, + TableStyle.MARKDOWN, """ | l | c | r | Align left | Align centre | Align right | | :-| :-: |-: | :----------| :----------: |-----------: | @@ -1829,7 +1818,7 @@ class TestLatexOutput: "\\end{tabular}" ) - options = {"vrules": FRAME} + options = {"vrules": VRuleStyle.FRAME} assert t.get_latex_string(format=True, **options) == ( "\\begin{tabular}{|cccc|}\r\n" "\\hline\r\n" @@ -1841,7 +1830,7 @@ class TestLatexOutput: "\\end{tabular}" ) - options = {"hrules": ALL} + options = {"hrules": HRuleStyle.ALL} assert t.get_latex_string(format=True, **options) == ( "\\begin{tabular}{|c|c|c|c|}\r\n" "\\hline\r\n" @@ -1858,7 +1847,7 @@ class TestLatexOutput: def test_latex_output_header(self) -> None: t = helper_table() - assert t.get_latex_string(format=True, hrules=HEADER) == ( + assert t.get_latex_string(format=True, hrules=HRuleStyle.HEADER) == ( "\\begin{tabular}{|c|c|c|c|}\r\n" " & Field 1 & Field 2 & Field 3 \\\\\r\n" "\\hline\r\n" @@ -2368,7 +2357,7 @@ class TestMaxTableWidth: def test_max_table_width_wide_vrules_frame(self) -> None: table = PrettyTable() table.max_table_width = 52 - table.vrules = FRAME + table.vrules = VRuleStyle.FRAME table.add_row( [ 0, @@ -2400,7 +2389,7 @@ class TestMaxTableWidth: def test_max_table_width_wide_vrules_none(self) -> None: table = PrettyTable() table.max_table_width = 52 - table.vrules = NONE + table.vrules = VRuleStyle.NONE table.add_row( [ 0, @@ -2608,3 +2597,51 @@ class TestGeneralOutput: t = helper_table() with pytest.raises(ValueError): t.get_formatted_string("pdf") + + +class TestDeprecations: + @pytest.mark.parametrize( + "module_name", + [ + "prettytable", + "prettytable.prettytable", + ], + ) + @pytest.mark.parametrize( + "name", + [ + "FRAME", + "ALL", + "NONE", + "HEADER", + ], + ) + def test_hrule_constant_deprecations(self, module_name: str, name: str) -> None: + with pytest.deprecated_call(match=f"the '{name}' constant is deprecated"): + exec(f"from {module_name} import {name}") + + @pytest.mark.parametrize( + "module_name", + [ + "prettytable", + "prettytable.prettytable", + ], + ) + @pytest.mark.parametrize( + "name", + [ + "DEFAULT", + "MSWORD_FRIENDLY", + "PLAIN_COLUMNS", + "MARKDOWN", + "ORGMODE", + "DOUBLE_BORDER", + "SINGLE_BORDER", + "RANDOM", + ], + ) + def test_table_style_constant_deprecations( + self, module_name: str, name: str + ) -> None: + with pytest.deprecated_call(match=f"the '{name}' constant is deprecated"): + exec(f"from {module_name} import {name}") diff --git a/contrib/python/prettytable/py3/ya.make b/contrib/python/prettytable/py3/ya.make index 108de3e08a..6f495203a6 100644 --- a/contrib/python/prettytable/py3/ya.make +++ b/contrib/python/prettytable/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(3.11.0) +VERSION(3.12.0) LICENSE(BSD-3-Clause) @@ -15,6 +15,7 @@ NO_LINT() PY_SRCS( TOP_LEVEL prettytable/__init__.py + prettytable/_version.py prettytable/colortable.py prettytable/prettytable.py ) |