flexablelib 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. flexablelib-2.0.0/CHANGELOG.md +176 -0
  2. flexablelib-2.0.0/LICENSE +21 -0
  3. flexablelib-2.0.0/MANIFEST.in +7 -0
  4. flexablelib-2.0.0/PKG-INFO +372 -0
  5. flexablelib-2.0.0/README.md +323 -0
  6. flexablelib-2.0.0/flexablelib/__init__.py +6 -0
  7. flexablelib-2.0.0/flexablelib/_speedups.c +475 -0
  8. flexablelib-2.0.0/flexablelib/_width_tables.h +524 -0
  9. flexablelib-2.0.0/flexablelib/cells.py +522 -0
  10. flexablelib-2.0.0/flexablelib/colors.py +195 -0
  11. flexablelib-2.0.0/flexablelib/columns.py +888 -0
  12. flexablelib-2.0.0/flexablelib/fast.py +81 -0
  13. flexablelib-2.0.0/flexablelib/merges.py +300 -0
  14. flexablelib-2.0.0/flexablelib/options.py +88 -0
  15. flexablelib-2.0.0/flexablelib/readers.py +370 -0
  16. flexablelib-2.0.0/flexablelib/style_compositions.py +872 -0
  17. flexablelib-2.0.0/flexablelib/table.py +4197 -0
  18. flexablelib-2.0.0/flexablelib/table_strings.py +711 -0
  19. flexablelib-2.0.0/flexablelib/text_width.py +480 -0
  20. flexablelib-2.0.0/flexablelib/utils.py +232 -0
  21. flexablelib-2.0.0/flexablelib/writers.py +560 -0
  22. flexablelib-2.0.0/flexablelib.egg-info/PKG-INFO +372 -0
  23. flexablelib-2.0.0/flexablelib.egg-info/SOURCES.txt +40 -0
  24. flexablelib-2.0.0/flexablelib.egg-info/dependency_links.txt +1 -0
  25. flexablelib-2.0.0/flexablelib.egg-info/requires.txt +14 -0
  26. flexablelib-2.0.0/flexablelib.egg-info/top_level.txt +1 -0
  27. flexablelib-2.0.0/package.json +47 -0
  28. flexablelib-2.0.0/setup.cfg +7 -0
  29. flexablelib-2.0.0/setup.py +58 -0
  30. flexablelib-2.0.0/tests/test_cells.py +249 -0
  31. flexablelib-2.0.0/tests/test_columns.py +302 -0
  32. flexablelib-2.0.0/tests/test_features.py +218 -0
  33. flexablelib-2.0.0/tests/test_issues.py +859 -0
  34. flexablelib-2.0.0/tests/test_merges.py +422 -0
  35. flexablelib-2.0.0/tests/test_readme_examples.py +266 -0
  36. flexablelib-2.0.0/tests/test_styles.py +189 -0
  37. flexablelib-2.0.0/tests/test_text_width.py +257 -0
  38. flexablelib-2.0.0/tests/test_two_pass_measurement.py +266 -0
  39. flexablelib-2.0.0/tests/test_upstream_issues.py +415 -0
  40. flexablelib-2.0.0/tools/benchmark.py +111 -0
  41. flexablelib-2.0.0/tools/generate_width_tables.py +112 -0
@@ -0,0 +1,176 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ ## [2.0.0](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.4.1...v2.0.0) (2026-10-28)
6
+
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ * package renamed from `prettyTables` to `flexablelib` (`from flexablelib import Table`)
11
+
12
+
13
+ ### Features
14
+
15
+ * Flexible Table Library identity: PyPI name `flexablelib`, C extension `flexablelib._speedups`
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * colour merge tests pin `use_colors=True` so CI without a TTY still asserts ANSI codes
21
+
22
+ ## [1.4.1](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.4.0...v1.4.1) (2026-08-03)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * `column_max_width` now wraps or trims cell content to the cap (was only
28
+ changing the measured width number, so long cells still overflowed)
29
+
30
+ ## [1.4.0](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.3.0...v1.4.0) (2026-08-03)
31
+
32
+
33
+ ### Features
34
+
35
+ * cell formatters: `float_format`, `int_format`, `custom_format`, and `leading_zeros`
36
+ * per-column `column_min_width` / `column_max_width`
37
+ * `header_align` independent of body alignment
38
+ * `add_divider()` / `clear_dividers()` for horizontal rules between rows
39
+ * table `title` drawn above the frame
40
+ * `sort_by` / `sort_reverse` and `row_filter` at render time (storage unchanged)
41
+ * Jupyter `_repr_html_()` via a bare HTML table
42
+ * `shape` property `(rows, columns)`
43
+ * `table_align` and `expand_to_window` wired into render
44
+
45
+
46
+ ### Bug Fixes
47
+
48
+ * float columns keep decimal alignment when the table is shrunk ([#23](https://github.com/Opus-Perpetuus/prettyTables/issues/23))
49
+ * alignment options are actually applied; `bool_align` no longer wrote the float slot ([#4](https://github.com/Opus-Perpetuus/prettyTables/issues/4))
50
+ * empty rows and columns share one emptiness criterion ([#9](https://github.com/Opus-Perpetuus/prettyTables/issues/9))
51
+ * column named `"i"` no longer collides with the index column
52
+ * exponential numbers align with the float column
53
+ * tabs, emoji VS16, empty header-only tables, markdown alignment colons, and other upstream regressions
54
+ * wide-character wrap at width 1 no longer invents a blank line
55
+ * header-only tables survive a narrow `max_width` without `IndexError`
56
+
57
+
58
+ ### Documentation
59
+
60
+ * `docs/ISSUES.md` maps every tracker issue to its fix and tests
61
+ * README Known Issues and ARCHITECTURE Known gaps brought in line with current behaviour
62
+
63
+ ## [1.3.0](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.2.0...v1.3.0) (2026-08-03)
64
+
65
+
66
+ ### Features
67
+
68
+ * merge cells across columns, down rows, or both, via `merge_cells()` ([39f6e56](https://github.com/Opus-Perpetuus/prettyTables/commit/39f6e56))
69
+
70
+
71
+ ### Performance Improvements
72
+
73
+ * skip the redundant second measuring pass when the table already fits, and cut per-cell helper overhead; 2000x4 renders in 16.9ms against 30.6ms, making this the fastest of flexablelib, prettytable, tabulate and pandas .to_string() on the same data ([88b01f0](https://github.com/Opus-Perpetuus/prettyTables/commit/88b01f0))
74
+
75
+
76
+ ### Bug Fixes
77
+
78
+ * the index column no longer continues counting across renders; it is reset explicitly rather than by a side effect of deep-copying the table ([88b01f0](https://github.com/Opus-Perpetuus/prettyTables/commit/88b01f0))
79
+ * `is_some_instance` returned None instead of False when nothing matched ([88b01f0](https://github.com/Opus-Perpetuus/prettyTables/commit/88b01f0))
80
+
81
+ ## [1.2.0](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.1.5...v1.2.0) (2026-08-03)
82
+
83
+
84
+ ### Features
85
+
86
+ * ANSI colour for headers, borders, columns, rows and individual cells, with NO_COLOR and TTY detection ([f7ea1c9](https://github.com/Opus-Perpetuus/prettyTables/commit/f7ea1c9))
87
+ * read from CSV, HTML, dicts, pandas and Excel; write CSV, Markdown, self-contained paginated HTML and Excel ([c54fa06](https://github.com/Opus-Perpetuus/prettyTables/commit/c54fa06))
88
+ * parse numeric strings via `parse_str_numbers`, absorbing celulartable's type parsing ([ce5362b](https://github.com/Opus-Perpetuus/prettyTables/commit/ce5362b))
89
+ * `max_width` and `too_narrow_message` for tables that cannot fit ([f8309b8](https://github.com/Opus-Perpetuus/prettyTables/commit/f8309b8))
90
+ * `Table.missing` sentinel for building tables with gaps ([c54fa06](https://github.com/Opus-Perpetuus/prettyTables/commit/c54fa06))
91
+
92
+
93
+ ### Bug Fixes
94
+
95
+ * measure and pad cells by visible width, fixing alignment for CJK, Hangul and emoji ([7a350d2](https://github.com/Opus-Perpetuus/prettyTables/commit/7a350d2))
96
+ * exclude hidden rows from column width measurement ([#22](https://github.com/Opus-Perpetuus/prettyTables/issues/22)) ([e480f4e](https://github.com/Opus-Perpetuus/prettyTables/commit/e480f4e))
97
+ * shrink the widest column first instead of every column in proportion ([#16](https://github.com/Opus-Perpetuus/prettyTables/issues/16)) ([842f64e](https://github.com/Opus-Perpetuus/prettyTables/commit/842f64e))
98
+ * never hand a column a width budget of zero, which raised from textwrap ([#14](https://github.com/Opus-Perpetuus/prettyTables/issues/14)) ([842f64e](https://github.com/Opus-Perpetuus/prettyTables/commit/842f64e))
99
+ * with auto_wrap off, the trimmed table now fits the terminal (Known Issue #2) ([842f64e](https://github.com/Opus-Perpetuus/prettyTables/commit/842f64e))
100
+
101
+
102
+ ### Performance Improvements
103
+
104
+ * C extension for text measurement, 17-34x on the hot path, with a pure-Python fallback ([23981d4](https://github.com/Opus-Perpetuus/prettyTables/commit/23981d4))
105
+
106
+ ### [1.1.5](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.1.4...v1.1.5) (2022-07-11)
107
+
108
+
109
+ ### Bug Fixes
110
+
111
+ * Wasn't possible to add empty rows. ([7a94a3f](https://github.com/Opus-Perpetuus/prettyTables/commit/7a94a3f94438ebdab16d21dd80d4c1bc66be872e))
112
+
113
+ ### [1.1.4](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.1.3...v1.1.4) (2022-07-11)
114
+
115
+
116
+ ### Bug Fixes
117
+
118
+ * Accidental import. ([47e798a](https://github.com/Opus-Perpetuus/prettyTables/commit/47e798a9019b918b47ace50d5fe5683864e5e886))
119
+ * Auto trimming fixed. ([92e3a66](https://github.com/Opus-Perpetuus/prettyTables/commit/92e3a668fb931da0225b375d03c72f2ce9e357d0))
120
+ * Auto-wrapping fixed. ([4b8d631](https://github.com/Opus-Perpetuus/prettyTables/commit/4b8d631dc9f7dbe65053e25b854dc61c7d6fbb64))
121
+ * Autwrapping with index shown fixed. ([cbcb70c](https://github.com/Opus-Perpetuus/prettyTables/commit/cbcb70c8a08c5572553a3b46cad822cc316d5025))
122
+ * Columns not showing wen passing less headers in class args. ([1559fe4](https://github.com/Opus-Perpetuus/prettyTables/commit/1559fe41f347130e44f07c67cdd464ca23f0cf68))
123
+ * Passing extra headers causes an IndexError. ([e5a3e42](https://github.com/Opus-Perpetuus/prettyTables/commit/e5a3e427cf226d6eb4e58fb658d5068be1700edd))
124
+ * Using rows and headers arguments gives error. ([0479cd5](https://github.com/Opus-Perpetuus/prettyTables/commit/0479cd569396db5a08c9b51be7816b53e0e0f8f9))
125
+
126
+ ### [1.1.3](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.1.2...v1.1.3) (2022-05-07)
127
+
128
+
129
+ ### Bug Fixes
130
+
131
+ * more accidental imports ([25e4c88](https://github.com/Opus-Perpetuus/prettyTables/commit/25e4c88e0feab8f154547ae159d0d7d8fff0750b))
132
+
133
+ ### [1.1.2](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.1.1...v1.1.2) (2022-05-07)
134
+
135
+
136
+ ### Bug Fixes
137
+
138
+ * accidental import. ([736ab4d](https://github.com/Opus-Perpetuus/prettyTables/commit/736ab4dc281cb766f9726512e3505a5bb17fc0cc))
139
+
140
+ ### [1.1.1](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.1.0...v1.1.1) (2022-05-07)
141
+
142
+
143
+ ### Bug Fixes
144
+
145
+ * adding column of different size causing misplaced missing values. ([66abc50](https://github.com/Opus-Perpetuus/prettyTables/commit/66abc5082488c734ffd9329be09f9dc6ea86683b))
146
+ * unintended info printing on console. ([560af0a](https://github.com/Opus-Perpetuus/prettyTables/commit/560af0aa8016ab71ad11f9f7ce29375543c192a9))
147
+
148
+ ## [1.1.0](https://github.com/Opus-Perpetuus/prettyTables/compare/v1.0.0...v1.1.0) (2022-05-07)
149
+
150
+
151
+ ### Features
152
+
153
+ * added auto-wrapping for string columns. ([0cacdef](https://github.com/Opus-Perpetuus/prettyTables/commit/0cacdef34c738d0d611440ab393f474f37858ae3))
154
+ * added float parsing and alignment ([1a65acd](https://github.com/Opus-Perpetuus/prettyTables/commit/1a65acd7a3fc7deb7331de4bed20a9d276d1a87d))
155
+ * added show_index option ([8b8d328](https://github.com/Opus-Perpetuus/prettyTables/commit/8b8d328af591a7d0edd288d80af029837f300f81))
156
+ * auto-wrap depends on the auto_wrap option. ([a1e09e5](https://github.com/Opus-Perpetuus/prettyTables/commit/a1e09e50ec913343b5b48b679cf08128ba74a383))
157
+ * column data trimming added. ([f53503b](https://github.com/Opus-Perpetuus/prettyTables/commit/f53503bc0b1bf3bd342286ba5cb16354ab8ee4ab))
158
+ * show_empty_columns, show_empty_rows options ([a7e4288](https://github.com/Opus-Perpetuus/prettyTables/commit/a7e428845254d68368e9bce6a7fbb4a59fe4046f))
159
+
160
+
161
+ ### Bug Fixes
162
+
163
+ * add_column omitting columns_with_i ([4cc900d](https://github.com/Opus-Perpetuus/prettyTables/commit/4cc900d25c494fbc2dcf4b58a7c7794c42d22b81))
164
+ * auto-wrapping doesn't wrap columns "equally". ([9ba68ab](https://github.com/Opus-Perpetuus/prettyTables/commit/9ba68aba7c8c7494c33682368921802bc5167436))
165
+ * empty column and row hiding working bad ([76979e9](https://github.com/Opus-Perpetuus/prettyTables/commit/76979e9b803491e6335cdcca8f7417f99abf8542))
166
+ * float columns weren't considering header size ([f8ffce3](https://github.com/Opus-Perpetuus/prettyTables/commit/f8ffce38a2b97d409ca7ba37677280d8ff329c68))
167
+ * header wrapping wasn't working ([09b5136](https://github.com/Opus-Perpetuus/prettyTables/commit/09b513653f89dc61331301c2be5b1506366d0fdc))
168
+ * hiding empty r/c when showing i behaving bad ([823776a](https://github.com/Opus-Perpetuus/prettyTables/commit/823776ae5b1ca9b9210a8cd8337847a79fd5625f))
169
+ * index displays incorrectly when hiding empty rows ([6054dda](https://github.com/Opus-Perpetuus/prettyTables/commit/6054ddae743df58907802c1467f8993d937c7df7))
170
+ * large missing val. in float col. causes bad alignment ([565d58c](https://github.com/Opus-Perpetuus/prettyTables/commit/565d58c9db550d63d634c1f49c972a7c8beb7b8f))
171
+ * missing value was a normal value and was affecting alignment ([a01d4fa](https://github.com/Opus-Perpetuus/prettyTables/commit/a01d4fa1b7dcc03f3ba78f31b9984ba7a7f4d334))
172
+ * read_json not closing json ([6702f53](https://github.com/Opus-Perpetuus/prettyTables/commit/6702f5330f11d1f2a70b811e68f9a26447a065f6))
173
+ * table with index wasn't auto-wrapping ([23457a5](https://github.com/Opus-Perpetuus/prettyTables/commit/23457a542733a40931f875db76f2a62939ffa93e))
174
+ * when displaying index and adding rows table data messes up. ([3c0a724](https://github.com/Opus-Perpetuus/prettyTables/commit/3c0a7245dd09597ac46028bf31a03d37014c0ccc))
175
+ * when showing i table data displays incomplete. ([b33ed42](https://github.com/Opus-Perpetuus/prettyTables/commit/b33ed42d064b1875e70357dedc1b2005ba396379))
176
+ * wrapping wasn't working ([cf63647](https://github.com/Opus-Perpetuus/prettyTables/commit/cf63647a741dec0867cb702d75d16c3b0301d3e1))
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021-2022 Benjamin Ramirez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ include README.md
2
+ include LICENSE
3
+ include CHANGELOG.md
4
+ include package.json
5
+ include flexablelib/_speedups.c
6
+ include flexablelib/_width_tables.h
7
+ recursive-include tools *.py
@@ -0,0 +1,372 @@
1
+ Metadata-Version: 2.4
2
+ Name: flexablelib
3
+ Version: 2.0.0
4
+ Summary: Flexible Table Library — console tables
5
+ Home-page: https://github.com/Opus-Perpetuus/prettyTables
6
+ Download-URL:
7
+ Author: Benjamin Ramirez
8
+ Author-email: chilerito12@gmail.com
9
+ License: MIT
10
+ Keywords: console,graphics
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Software Development :: Build Tools
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Programming Language :: Python :: 3 :: Only
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Provides-Extra: pandas
28
+ Requires-Dist: pandas>=1.0; extra == "pandas"
29
+ Provides-Extra: excel
30
+ Requires-Dist: openpyxl>=3.0; extra == "excel"
31
+ Provides-Extra: html
32
+ Requires-Dist: lxml>=4.0; extra == "html"
33
+ Provides-Extra: all
34
+ Requires-Dist: pandas>=1.0; extra == "all"
35
+ Requires-Dist: openpyxl>=3.0; extra == "all"
36
+ Requires-Dist: lxml>=4.0; extra == "all"
37
+ Dynamic: author
38
+ Dynamic: author-email
39
+ Dynamic: classifier
40
+ Dynamic: description
41
+ Dynamic: description-content-type
42
+ Dynamic: home-page
43
+ Dynamic: keywords
44
+ Dynamic: license
45
+ Dynamic: license-file
46
+ Dynamic: provides-extra
47
+ Dynamic: requires-python
48
+ Dynamic: summary
49
+
50
+ <p align="center">
51
+ <img src="logos/export/logo.svg" alt="flexablelib" width="440">
52
+ </p>
53
+
54
+ <p align="center">
55
+ <em>Flexible Table Library — format tabular data with pretty styles.</em>
56
+ </p>
57
+
58
+ <p align="center">
59
+ <a href="https://pypi.org/project/flexablelib/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/flexablelib?style=flat-square&color=4338CA&logo=pypi&logoColor=white"></a>
60
+ <a href="https://pypi.org/project/flexablelib/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/flexablelib?style=flat-square&color=4338CA&logo=python&logoColor=white"></a>
61
+ <a href="https://pypi.org/project/flexablelib/"><img alt="Downloads per month" src="https://img.shields.io/pypi/dm/flexablelib?style=flat-square&color=F59E0B"></a>
62
+ <a href="https://pypi.org/project/flexablelib/"><img alt="Development status" src="https://img.shields.io/pypi/status/flexablelib?style=flat-square&color=F59E0B"></a>
63
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/flexablelib?style=flat-square&color=64748B"></a>
64
+ </p>
65
+
66
+ ---
67
+
68
+ # **flexablelib**
69
+
70
+ Flexible Table Library
71
+
72
+ This is a python package that aims to provide a simple and pretty way of printing tables to the console making use of a class.
73
+
74
+ The idea started as an attempt to reproduce the behavior of the [PM2](https://pm2.keymetrics.io) package when it displays tables to show data. Later, heavy inspiration came
75
+ of two other python packages:
76
+
77
+ - [Jazzband's](https://github.com/jazzband) [prettytable](https://github.com/jazzband/prettytable) (The names are similar by accident). Uses a class too.
78
+ - [Astanin's](https://github.com/astanin) [tabulate](https://github.com/astanin/python-tabulate). A very simple to use and efficient package.
79
+
80
+ A big part of the behavior of this package was replicated from these.
81
+
82
+ # Installation
83
+ ``pip install flexablelib`` on Windows.
84
+
85
+ ``pip3 install flexablelib`` on Linux
86
+
87
+ # Usage
88
+ Creating a table is simple.
89
+ ### Code Example
90
+ ```
91
+ from flexablelib import Table
92
+
93
+ new_table = Table()
94
+ print(new_table)
95
+ ```
96
+ ### Output
97
+ ```
98
+ ++
99
+ ++
100
+ ++
101
+ ```
102
+ This is an empty table. It has no data so it only displays this strange thing.
103
+
104
+ A table that has columns but no rows — a query that came back empty — shows
105
+ its headers rather than raising:
106
+
107
+ ```
108
+ ┌──────┬───────┐
109
+ │ name │ value │
110
+ ╞══════╪═══════╡
111
+ └──────┴───────┘
112
+ ```
113
+
114
+ It's possible to add data as columns or rows, or even alternating each one. Any untitled column will be named automatically.
115
+
116
+ ### Code Example
117
+ ```
118
+ new_table.add_column('Name', ['Jade', 'John', 'Jane'])
119
+ new_table.add_column('Age', [20, 30, 40])
120
+ new_table.add_column('Results', [9.651, 3, 245.7])
121
+ print(new_table)
122
+ ```
123
+
124
+ ### Output
125
+ ```
126
+ +----------------------+
127
+ | Name Age Results |
128
+ +======+=====+=========+
129
+ | Jade | 20 | 9.651 |
130
+ | John | 30 | 3 |
131
+ | Jane | 40 | 245.7 |
132
+ +------+-----+---------+
133
+ ```
134
+
135
+ ### Code Example
136
+ ```
137
+ new_table = Table()
138
+ new_table.add_column('Name', ['Jade', 'John', 'Jane'])
139
+ new_table.add_column('Age', [20, 30, 40])
140
+ new_table.add_column('Test\nResults', [9.651, 3, 245.7])
141
+ new_table.add_row(['Piotr\nBaltimore', 27, 3.5])
142
+ new_table.add_row(['Sam', 21, 0.6519])
143
+ print(new_table)
144
+ ```
145
+
146
+ ### Output
147
+ ```
148
+ +----------------------------+
149
+ | Name Age Test |
150
+ | Results |
151
+ +===========+=====+==========+
152
+ | Jade | 20 | 9.651 |
153
+ | John | 30 | 3 |
154
+ | Jane | 40 | 245.7 |
155
+ | Piotr | 27 | 3.5 |
156
+ | Baltimore | | |
157
+ | Sam | 21 | 0.6519 |
158
+ +-----------+-----+----------+
159
+ ```
160
+ As it is visible, the table will format automatically new lines and data types, for now without trying to parse strings that could be converted to another type.
161
+
162
+ The ``Table`` class offers a variety of options that allow things like showing the index of each row, changing the style of the table, hiding the headers, etc.
163
+
164
+ See style examples [here](/style_examples.md).
165
+
166
+ ### Code Example
167
+ ```
168
+ new_table = Table()
169
+ new_table.add_column('Name', ['Jade', 'John'])
170
+ new_table.add_column('Age', [20, 30])
171
+ new_table.add_column('Test\nResults', [9.651, 3, 245.7])
172
+ new_table.add_row(['Piotr\nBaltimore', 27, 3.5])
173
+ new_table.add_row(['Sam', 21])
174
+ new_table.show_index = True
175
+ new_table.style_name = 'pretty_columns'
176
+ new_table.missing_value = '?'
177
+ print(new_table)
178
+ ```
179
+
180
+ ### Output
181
+ ```
182
+ ╒═══╤═══════════╤═════╤═════════╕
183
+ │ i │ Name │ Age │ Test │
184
+ │ │ │ │ Results │
185
+ ╞═══╪═══════════╪═════╪═════════╡
186
+ │ 0 │ Jade │ 20 │ 9.651 │
187
+ │ 1 │ John │ 30 │ 3 │
188
+ │ 2 │ ? │ ? │ 245.7 │
189
+ │ 3 │ Piotr │ 27 │ 3.5 │
190
+ │ │ Baltimore │ │ │
191
+ │ 4 │ Sam │ 21 │ ? │
192
+ ╘═══╧═══════════╧═════╧═════════╛
193
+ ```
194
+ The missing value aligns as if it was of the same type of the other data in the column.
195
+
196
+ This shows how to get the row and column count. If the index is shown, this count remains unaffected by that column, although, you can get the internal count.
197
+
198
+ ### Code Example
199
+ ```
200
+ new_table.show_index = False
201
+ new_table.show_headers = False
202
+ print(new_table)
203
+ print('row:', new_table.row_count)
204
+ print('columns:', new_table.column_count)
205
+ new_table.show_index = True
206
+ print(new_table)
207
+ print('internal_row_count:', new_table.internal_row_count)
208
+ print('internal_column_count:', new_table.internal_column_count)
209
+ ```
210
+
211
+ ### Output
212
+ ```
213
+ ╒═══════════╤════╤═════════╕
214
+ │ Jade │ 20 │ 9.651 │
215
+ │ John │ 30 │ 3 │
216
+ │ ? │ ? │ 245.7 │
217
+ │ Piotr │ 27 │ 3.5 │
218
+ │ Baltimore │ │ │
219
+ │ Sam │ 21 │ ? │
220
+ ╘═══════════╧════╧═════════╛
221
+ row: 5
222
+ columns: 3
223
+ ╒═══╤═══════════╤════╤═════════╕
224
+ │ 0 │ Jade │ 20 │ 9.651 │
225
+ │ 1 │ John │ 30 │ 3 │
226
+ │ 2 │ ? │ ? │ 245.7 │
227
+ │ 3 │ Piotr │ 27 │ 3.5 │
228
+ │ │ Baltimore │ │ │
229
+ │ 4 │ Sam │ 21 │ ? │
230
+ ╘═══╧═══════════╧════╧═════════╛
231
+ internal_row_count: 5
232
+ internal_column_count: 4
233
+ ```
234
+
235
+ # Colour
236
+
237
+ Colour the header, the borders, whole columns, whole rows, or individual cells.
238
+ Specs accept names, attributes, 256-colour indexes and hex triples.
239
+
240
+ ```python
241
+ table.header_color = 'bold cyan'
242
+ table.border_color = 'grey'
243
+ table.column_colors = {'Service': 'bright_white'}
244
+ table.color_rule = lambda value, row, column: (
245
+ 'red' if column == 'Delta' and value < 0 else None
246
+ )
247
+ ```
248
+
249
+ `color_rule` receives the original value, so numeric comparisons work directly.
250
+
251
+ Colour is emitted only to a terminal by default, and never when `NO_COLOR` is
252
+ set. `FORCE_COLOR` or `table.use_colors = True` overrides that. Because
253
+ `compose()` returns a string you may send anywhere, the default errs toward not
254
+ embedding escape sequences in something bound for a file.
255
+
256
+ Widths are measured in terminal columns, not characters, so coloured cells and
257
+ CJK or emoji data stay aligned.
258
+
259
+ # Reading and writing
260
+
261
+ ```python
262
+ Table.from_csv('sales.csv') # numeric columns parsed and aligned
263
+ Table.from_html(markup) # standard library parser, no dependency
264
+ Table.from_dicts(records)
265
+ Table.from_pandas(dataframe) # pip install flexablelib[pandas]
266
+ Table.from_excel('report.xlsx') # pip install flexablelib[excel]
267
+
268
+ table.to_csv('out.csv')
269
+ table.to_markdown()
270
+ table.to_html('report.html', paginate=25)
271
+ table.to_excel('report.xlsx')
272
+ ```
273
+
274
+ `to_html` writes one self-contained file — the stylesheet and the sorting,
275
+ filtering and pagination script are inline — so it works offline and from a
276
+ `file://` URL.
277
+
278
+ Text formats deliver everything as strings, and a column of strings is
279
+ left-aligned. `parse_str_numbers` converts numeric-looking text so it aligns as
280
+ numbers; the readers turn it on for you:
281
+
282
+ ```python
283
+ table.parse_str_numbers = True
284
+ ```
285
+
286
+ Values with leading zeros are left alone, so `'007'` stays a string.
287
+
288
+ # Merging cells
289
+
290
+ Render a rectangular block as a single cell, across columns, down rows, or
291
+ both. Coordinates are inclusive, zero-based, and ignore the index column.
292
+
293
+ ```python
294
+ table.merge_cells(0, 0, last_column=2, value='Quarter summary')
295
+ table.merge_cells(1, 0, last_row=3) # keeps the top-left content
296
+ table.merge_cells(0, 0, 2, 2, value='Total', align='r')
297
+ ```
298
+
299
+ A merge never widens the table -- columns are still sized by their unmerged
300
+ content -- so text longer than its span is truncated.
301
+
302
+ # Performance
303
+
304
+ An optional C extension accelerates text measurement, and the render pipeline
305
+ avoids the second measuring pass when the table already fits. On identical
306
+ data:
307
+
308
+ | Library | 100x4 | 2000x4 | 10000x6 |
309
+ | --- | ---: | ---: | ---: |
310
+ | **flexablelib** | **1.0 ms** | **16.9 ms** | **147 ms** |
311
+ | prettytable | 1.4 ms | 23.2 ms | 174 ms |
312
+ | tabulate | 1.7 ms | 27.5 ms | 193 ms |
313
+ | pandas `.to_string()` | 1.7 ms | 22.9 ms | 228 ms |
314
+
315
+ Reproduce with `python3 tools/benchmark.py`. This measures one job: turning
316
+ data already in memory into formatted text. pandas is an analysis engine and
317
+ `to_string` is a convenience within it, so this says nothing about groupby or
318
+ joins.
319
+
320
+ The extension is built automatically where a compiler is available and falls
321
+ back to pure Python where it is not, so installation never fails for want of a
322
+ toolchain.
323
+
324
+ ```python
325
+ from flexablelib.fast import implementation
326
+ print(implementation()) # 'C extension' or 'pure Python'
327
+ ```
328
+
329
+ # Known Issues
330
+
331
+ None of the three historical known issues remain:
332
+
333
+ - A column named ``"i"`` no longer collides with the index column
334
+ (`utils.IndexColumnTitle`).
335
+ - Exponential numbers align on the decimal / exponent axis with the rest of
336
+ the float column.
337
+ - Shrinking a float column drops decimals instead of chopping characters, so
338
+ decimal alignment survives a terminal fit ([#23](https://github.com/Opus-Perpetuus/prettyTables/issues/23)).
339
+
340
+ Open work and the full issue map live in [docs/ISSUES.md](docs/ISSUES.md).
341
+
342
+ # Project Layout
343
+
344
+ ```
345
+ prettyTables/ # GitHub repository (name unchanged)
346
+ ├── flexablelib/ the Python package (no runtime dependencies)
347
+ │ ├── __init__.py public API: Table, TableComposition, SeparatorLine
348
+ │ ├── table.py the Table class — state and render orchestration
349
+ │ ├── columns.py type inference, alignment, column widths
350
+ │ ├── style_compositions.py the 42 border styles, as data
351
+ │ ├── table_strings.py separator lines and data rows
352
+ │ ├── cells.py cell padding, justification, wrapping
353
+ │ ├── options.py constants and defaults
354
+ │ └── utils.py type predicates and small helpers
355
+ ├── tests/ pytest suite — see ARCHITECTURE.md#testing
356
+ ├── docs/ issue history and design notes
357
+ ├── logos/ brand assets — see logos/README.md
358
+ ├── ARCHITECTURE.md how it all fits together
359
+ ├── style_examples.md all 42 styles rendered
360
+ ├── package.json canonical version number; drives the release
361
+ └── setup.py reads the version from package.json
362
+ ```
363
+
364
+ Run the tests from the repository root:
365
+
366
+ ```
367
+ pip install -r requirements-dev.txt
368
+ python -m pytest
369
+ ```
370
+
371
+ See [**ARCHITECTURE.md**](ARCHITECTURE.md) for the rendering pipeline, how styles are defined,
372
+ and how to add one.