tksheet 7.4.11__tar.gz → 7.4.13__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.
- {tksheet-7.4.11/tksheet.egg-info → tksheet-7.4.13}/PKG-INFO +7 -7
- {tksheet-7.4.11 → tksheet-7.4.13}/README.md +6 -6
- {tksheet-7.4.11 → tksheet-7.4.13}/pyproject.toml +1 -1
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/__init__.py +1 -1
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/column_headers.py +44 -65
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/functions.py +109 -38
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/main_table.py +325 -316
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/other_classes.py +4 -2
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/row_index.py +177 -167
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/sheet.py +16 -10
- {tksheet-7.4.11 → tksheet-7.4.13/tksheet.egg-info}/PKG-INFO +7 -7
- {tksheet-7.4.11 → tksheet-7.4.13}/LICENSE.txt +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/setup.cfg +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/colors.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/constants.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/find_window.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/formatters.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/sheet_options.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/sorting.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/text_editor.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/themes.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/tksheet_types.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet/top_left_rectangle.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet.egg-info/SOURCES.txt +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet.egg-info/dependency_links.txt +0 -0
- {tksheet-7.4.11 → tksheet-7.4.13}/tksheet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: tksheet
|
3
|
-
Version: 7.4.
|
3
|
+
Version: 7.4.13
|
4
4
|
Summary: Tkinter table / sheet and treeview widget
|
5
5
|
Author-email: ragardner <github@ragardner.simplelogin.com>
|
6
6
|
License: Copyright (c) 2019 ragardner and open source contributors
|
@@ -63,23 +63,23 @@ License-File: LICENSE.txt
|
|
63
63
|
<tbody>
|
64
64
|
<tr>
|
65
65
|
<td style="color: LightCoral">Versions 6.x.x →</td>
|
66
|
-
<td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation
|
66
|
+
<td><a href="https://github.com/ragardner/tksheet/wiki/Version-6" target="_blank">Documentation</a></td>
|
67
67
|
</tr>
|
68
68
|
<tr>
|
69
69
|
<td style="color: lightgreen">Versions 7.x.x →</td>
|
70
|
-
<td><a href="https://github.
|
70
|
+
<td><a href="https://ragardner.github.io/tksheet/DOCUMENTATION.html" target="_blank">Documentation</a></td>
|
71
71
|
</tr>
|
72
72
|
<tr>
|
73
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md">Changelog</a></td>
|
73
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md" target="_blank">Changelog</a></td>
|
74
74
|
</tr>
|
75
75
|
<tr>
|
76
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#asking-questions">Questions</a></td>
|
76
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#asking-questions" target="_blank">Questions</a></td>
|
77
77
|
</tr>
|
78
78
|
<tr>
|
79
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#issues">Issues</a></td>
|
79
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#issues" target="_blank">Issues</a></td>
|
80
80
|
</tr>
|
81
81
|
<tr>
|
82
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#enhancements-or-suggestions">Suggestions and Contributors</a></td>
|
82
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#enhancements-or-suggestions" target="_blank">Suggestions and Contributors</a></td>
|
83
83
|
</tr>
|
84
84
|
</tbody>
|
85
85
|
</table>
|
@@ -18,23 +18,23 @@
|
|
18
18
|
<tbody>
|
19
19
|
<tr>
|
20
20
|
<td style="color: LightCoral">Versions 6.x.x →</td>
|
21
|
-
<td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation
|
21
|
+
<td><a href="https://github.com/ragardner/tksheet/wiki/Version-6" target="_blank">Documentation</a></td>
|
22
22
|
</tr>
|
23
23
|
<tr>
|
24
24
|
<td style="color: lightgreen">Versions 7.x.x →</td>
|
25
|
-
<td><a href="https://github.
|
25
|
+
<td><a href="https://ragardner.github.io/tksheet/DOCUMENTATION.html" target="_blank">Documentation</a></td>
|
26
26
|
</tr>
|
27
27
|
<tr>
|
28
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md">Changelog</a></td>
|
28
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md" target="_blank">Changelog</a></td>
|
29
29
|
</tr>
|
30
30
|
<tr>
|
31
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#asking-questions">Questions</a></td>
|
31
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#asking-questions" target="_blank">Questions</a></td>
|
32
32
|
</tr>
|
33
33
|
<tr>
|
34
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#issues">Issues</a></td>
|
34
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#issues" target="_blank">Issues</a></td>
|
35
35
|
</tr>
|
36
36
|
<tr>
|
37
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#enhancements-or-suggestions">Suggestions and Contributors</a></td>
|
37
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#enhancements-or-suggestions" target="_blank">Suggestions and Contributors</a></td>
|
38
38
|
</tr>
|
39
39
|
</tbody>
|
40
40
|
</table>
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
6
6
|
name = "tksheet"
|
7
7
|
description = "Tkinter table / sheet and treeview widget"
|
8
8
|
readme = "README.md"
|
9
|
-
version = "7.4.
|
9
|
+
version = "7.4.13"
|
10
10
|
authors = [{ name = "ragardner", email = "github@ragardner.simplelogin.com" }]
|
11
11
|
requires-python = ">=3.8"
|
12
12
|
license = {file = "LICENSE.txt"}
|
@@ -5,7 +5,7 @@ from collections import defaultdict
|
|
5
5
|
from collections.abc import Callable, Hashable, Iterator, Sequence
|
6
6
|
from functools import partial
|
7
7
|
from itertools import cycle, islice, repeat
|
8
|
-
from math import ceil
|
8
|
+
from math import ceil
|
9
9
|
from operator import itemgetter
|
10
10
|
from typing import Any, Literal
|
11
11
|
|
@@ -741,7 +741,7 @@ class ColumnHeaders(tk.Canvas):
|
|
741
741
|
if size < self.ops.min_column_width:
|
742
742
|
new_col_pos = ceil(self.MT.col_positions[self.rsz_w - 1] + self.ops.min_column_width)
|
743
743
|
elif size > self.ops.max_column_width:
|
744
|
-
new_col_pos =
|
744
|
+
new_col_pos = int(self.MT.col_positions[self.rsz_w - 1] + self.ops.max_column_width)
|
745
745
|
increment = new_col_pos - self.MT.col_positions[self.rsz_w]
|
746
746
|
self.MT.col_positions[self.rsz_w + 1 :] = [
|
747
747
|
e + increment for e in islice(self.MT.col_positions, self.rsz_w + 1, None)
|
@@ -1058,44 +1058,6 @@ class ColumnHeaders(tk.Canvas):
|
|
1058
1058
|
self.MT.run_selection_binding("columns")
|
1059
1059
|
return fill_iid
|
1060
1060
|
|
1061
|
-
def display_box(
|
1062
|
-
self,
|
1063
|
-
x1: int,
|
1064
|
-
y1: int,
|
1065
|
-
x2: int,
|
1066
|
-
y2: int,
|
1067
|
-
fill: str,
|
1068
|
-
outline: str,
|
1069
|
-
state: str,
|
1070
|
-
tags: str | tuple[str],
|
1071
|
-
iid: None | int = None,
|
1072
|
-
) -> int:
|
1073
|
-
coords = rounded_box_coords(
|
1074
|
-
x1,
|
1075
|
-
y1,
|
1076
|
-
x2,
|
1077
|
-
y2,
|
1078
|
-
radius=5 if self.ops.rounded_boxes else 0,
|
1079
|
-
)
|
1080
|
-
if isinstance(iid, int):
|
1081
|
-
self.coords(iid, coords)
|
1082
|
-
self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
|
1083
|
-
else:
|
1084
|
-
if self.hidd_boxes:
|
1085
|
-
iid = self.hidd_boxes.pop()
|
1086
|
-
self.coords(iid, coords)
|
1087
|
-
self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
|
1088
|
-
else:
|
1089
|
-
iid = self.create_polygon(coords, fill=fill, outline=outline, state=state, tags=tags, smooth=True)
|
1090
|
-
self.disp_boxes.add(iid)
|
1091
|
-
return iid
|
1092
|
-
|
1093
|
-
def hide_box(self, item: int) -> None:
|
1094
|
-
if isinstance(item, int):
|
1095
|
-
self.disp_boxes.discard(item)
|
1096
|
-
self.hidd_boxes.add(item)
|
1097
|
-
self.itemconfig(item, state="hidden")
|
1098
|
-
|
1099
1061
|
def get_cell_dimensions(self, datacn: int) -> tuple[int, int]:
|
1100
1062
|
txt = self.cell_str(datacn, fix=False)
|
1101
1063
|
if txt:
|
@@ -1279,6 +1241,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1279
1241
|
sel_cols_bg: str,
|
1280
1242
|
selections: dict,
|
1281
1243
|
datacn: int,
|
1244
|
+
has_dd: bool,
|
1282
1245
|
) -> tuple[str, bool]:
|
1283
1246
|
redrawn = False
|
1284
1247
|
kwargs = self.get_cell_kwargs(datacn, key="highlight")
|
@@ -1319,18 +1282,32 @@ class ColumnHeaders(tk.Canvas):
|
|
1319
1282
|
sc,
|
1320
1283
|
self.current_height - 1,
|
1321
1284
|
fill=fill,
|
1322
|
-
outline=
|
1323
|
-
self.ops.header_fg
|
1324
|
-
if self.get_cell_kwargs(datacn, key="dropdown") and self.ops.show_dropdown_borders
|
1325
|
-
else ""
|
1326
|
-
),
|
1285
|
+
outline=self.ops.header_fg if has_dd and self.ops.show_dropdown_borders else "",
|
1327
1286
|
tag="hi",
|
1328
1287
|
)
|
1329
1288
|
elif not kwargs:
|
1330
1289
|
if "columns" in selections and c in selections["columns"]:
|
1331
1290
|
txtfg = self.ops.header_selected_columns_fg
|
1291
|
+
redrawn = self.redraw_highlight(
|
1292
|
+
fc + 1,
|
1293
|
+
0,
|
1294
|
+
sc,
|
1295
|
+
self.current_height - 1,
|
1296
|
+
fill=self.ops.header_selected_columns_bg,
|
1297
|
+
outline=self.ops.header_fg if has_dd and self.ops.show_dropdown_borders else "",
|
1298
|
+
tag="hi",
|
1299
|
+
)
|
1332
1300
|
elif "cells" in selections and c in selections["cells"]:
|
1333
1301
|
txtfg = self.ops.header_selected_cells_fg
|
1302
|
+
redrawn = self.redraw_highlight(
|
1303
|
+
fc + 1,
|
1304
|
+
0,
|
1305
|
+
sc,
|
1306
|
+
self.current_height - 1,
|
1307
|
+
fill=self.ops.header_selected_cells_bg,
|
1308
|
+
outline=self.ops.header_fg if has_dd and self.ops.show_dropdown_borders else "",
|
1309
|
+
tag="hi",
|
1310
|
+
)
|
1334
1311
|
else:
|
1335
1312
|
txtfg = self.ops.header_fg
|
1336
1313
|
return txtfg, redrawn
|
@@ -1396,7 +1373,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1396
1373
|
if draw_arrow:
|
1397
1374
|
mod = (self.MT.header_txt_height - 1) if self.MT.header_txt_height % 2 else self.MT.header_txt_height
|
1398
1375
|
small_mod = int(mod / 5)
|
1399
|
-
mid_y =
|
1376
|
+
mid_y = int(self.MT.min_header_height / 2)
|
1400
1377
|
if open_:
|
1401
1378
|
# up arrow
|
1402
1379
|
points = (
|
@@ -1559,6 +1536,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1559
1536
|
cleftgridln = self.MT.col_positions[c]
|
1560
1537
|
crightgridln = self.MT.col_positions[c + 1]
|
1561
1538
|
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
1539
|
+
kwargs = self.get_cell_kwargs(datacn, key="dropdown")
|
1562
1540
|
fill, dd_drawn = self.redraw_highlight_get_text_fg(
|
1563
1541
|
fc=cleftgridln,
|
1564
1542
|
sc=crightgridln,
|
@@ -1567,19 +1545,20 @@ class ColumnHeaders(tk.Canvas):
|
|
1567
1545
|
sel_cols_bg=sel_cols_bg,
|
1568
1546
|
selections=selections,
|
1569
1547
|
datacn=datacn,
|
1548
|
+
has_dd=bool(kwargs),
|
1570
1549
|
)
|
1571
1550
|
if datacn in self.cell_options and "align" in self.cell_options[datacn]:
|
1572
1551
|
align = self.cell_options[datacn]["align"]
|
1573
1552
|
else:
|
1574
1553
|
align = self.align
|
1575
|
-
if kwargs
|
1576
|
-
max_width = crightgridln - cleftgridln - txt_h -
|
1577
|
-
if align
|
1554
|
+
if kwargs:
|
1555
|
+
max_width = crightgridln - cleftgridln - txt_h - 5
|
1556
|
+
if align[-1] == "w":
|
1578
1557
|
draw_x = cleftgridln + 2
|
1579
|
-
elif align
|
1558
|
+
elif align[-1] == "e":
|
1580
1559
|
draw_x = crightgridln - 5 - txt_h
|
1581
|
-
elif align
|
1582
|
-
draw_x = cleftgridln +
|
1560
|
+
elif align[-1] == "n":
|
1561
|
+
draw_x = cleftgridln + (crightgridln - cleftgridln - txt_h) / 2
|
1583
1562
|
self.redraw_dropdown(
|
1584
1563
|
cleftgridln,
|
1585
1564
|
0,
|
@@ -1594,18 +1573,18 @@ class ColumnHeaders(tk.Canvas):
|
|
1594
1573
|
)
|
1595
1574
|
else:
|
1596
1575
|
max_width = crightgridln - cleftgridln - 2
|
1597
|
-
if align
|
1576
|
+
if align[-1] == "w":
|
1598
1577
|
draw_x = cleftgridln + 2
|
1599
|
-
elif align
|
1578
|
+
elif align[-1] == "e":
|
1600
1579
|
draw_x = crightgridln - 2
|
1601
|
-
elif align
|
1602
|
-
draw_x = cleftgridln +
|
1580
|
+
elif align[-1] == "n":
|
1581
|
+
draw_x = cleftgridln + (crightgridln - cleftgridln) / 2
|
1603
1582
|
if (kwargs := self.get_cell_kwargs(datacn, key="checkbox")) and max_width > txt_h + 1:
|
1604
1583
|
box_w = txt_h + 1
|
1605
|
-
if align
|
1584
|
+
if align[-1] == "w":
|
1606
1585
|
draw_x += box_w + 3
|
1607
|
-
elif align
|
1608
|
-
draw_x +=
|
1586
|
+
elif align[-1] == "n":
|
1587
|
+
draw_x += box_w / 2 + 1
|
1609
1588
|
max_width -= box_w + 4
|
1610
1589
|
try:
|
1611
1590
|
draw_check = (
|
@@ -1627,9 +1606,9 @@ class ColumnHeaders(tk.Canvas):
|
|
1627
1606
|
)
|
1628
1607
|
if (
|
1629
1608
|
max_width < self.MT.header_txt_width
|
1630
|
-
or (align
|
1631
|
-
or (align
|
1632
|
-
or (align
|
1609
|
+
or (align[-1] == "w" and draw_x > scrollpos_right)
|
1610
|
+
or (align[-1] == "e" and cleftgridln + 5 > scrollpos_right)
|
1611
|
+
or (align[-1] == "n" and cleftgridln + 5 > scrollpos_right)
|
1633
1612
|
):
|
1634
1613
|
continue
|
1635
1614
|
text = self.cell_str(datacn, fix=False)
|
@@ -1664,7 +1643,6 @@ class ColumnHeaders(tk.Canvas):
|
|
1664
1643
|
anchor=align,
|
1665
1644
|
state="normal",
|
1666
1645
|
)
|
1667
|
-
self.tag_raise(iid)
|
1668
1646
|
else:
|
1669
1647
|
iid = self.create_text(
|
1670
1648
|
draw_x,
|
@@ -1709,6 +1687,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1709
1687
|
if showing:
|
1710
1688
|
self.itemconfig(iid, state="hidden")
|
1711
1689
|
dct[iid] = False
|
1690
|
+
self.tag_raise("t")
|
1712
1691
|
if self.disp_resize_lines:
|
1713
1692
|
self.tag_raise("rw")
|
1714
1693
|
return True
|
@@ -2314,8 +2293,8 @@ class ColumnHeaders(tk.Canvas):
|
|
2314
2293
|
kwargs = self.get_cell_kwargs(datacn, key=None, cell=c_ops)
|
2315
2294
|
if "checkbox" in kwargs:
|
2316
2295
|
return False
|
2317
|
-
elif
|
2318
|
-
return kwargs["values"][0]
|
2296
|
+
elif "dropdown" in kwargs and kwargs["dropdown"]["validate_input"] and kwargs["dropdown"]["values"]:
|
2297
|
+
return kwargs["dropdown"]["values"][0]
|
2319
2298
|
else:
|
2320
2299
|
return ""
|
2321
2300
|
|
@@ -9,7 +9,7 @@ from bisect import bisect_left
|
|
9
9
|
from collections import deque
|
10
10
|
from collections.abc import Callable, Generator, Hashable, Iterable, Iterator, Sequence
|
11
11
|
from difflib import SequenceMatcher
|
12
|
-
from itertools import islice, repeat
|
12
|
+
from itertools import chain, islice, repeat
|
13
13
|
from typing import Any, Literal
|
14
14
|
|
15
15
|
from .colors import color_map
|
@@ -31,34 +31,16 @@ def wrap_text(
|
|
31
31
|
wrap: Literal["", "c", "w"] = "",
|
32
32
|
start_line: int = 0,
|
33
33
|
) -> Generator[str]:
|
34
|
-
lines = (match.group() for match in lines_re.finditer(text))
|
35
|
-
current_line = []
|
36
34
|
total_lines = 0
|
37
35
|
line_width = 0
|
38
|
-
|
39
|
-
|
40
|
-
for
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
if line_width >= max_width:
|
47
|
-
break
|
48
|
-
current_line.append(char)
|
49
|
-
|
50
|
-
if total_lines >= start_line:
|
51
|
-
yield "".join(current_line)
|
52
|
-
|
53
|
-
# Count the line whether it's empty or not
|
54
|
-
total_lines += 1
|
55
|
-
if total_lines >= max_lines:
|
56
|
-
return
|
57
|
-
|
58
|
-
elif wrap == "c":
|
59
|
-
for line in lines:
|
60
|
-
for char in line:
|
61
|
-
char_width = widths.get(char, char_width_fn(char))
|
36
|
+
if wrap == "c":
|
37
|
+
current_line = []
|
38
|
+
for match in lines_re.finditer(text):
|
39
|
+
for char in match.group():
|
40
|
+
try:
|
41
|
+
char_width = widths[char]
|
42
|
+
except KeyError:
|
43
|
+
char_width = char_width_fn(char)
|
62
44
|
|
63
45
|
# adding char to line would result in wrap
|
64
46
|
if line_width + char_width >= max_width:
|
@@ -89,11 +71,14 @@ def wrap_text(
|
|
89
71
|
line_width = 0
|
90
72
|
|
91
73
|
elif wrap == "w":
|
92
|
-
|
74
|
+
try:
|
75
|
+
space_width = widths[" "]
|
76
|
+
except KeyError:
|
77
|
+
space_width = char_width_fn(" ")
|
78
|
+
current_line = []
|
93
79
|
|
94
|
-
for
|
95
|
-
|
96
|
-
for i, word in enumerate(words):
|
80
|
+
for match in lines_re.finditer(text):
|
81
|
+
for i, word in enumerate(match.group().split()):
|
97
82
|
# if we're going to next word and
|
98
83
|
# if a space fits on the end of the current line we add one
|
99
84
|
if i and line_width + space_width < max_width:
|
@@ -104,8 +89,12 @@ def wrap_text(
|
|
104
89
|
word_width = 0
|
105
90
|
word_char_widths = []
|
106
91
|
for char in word:
|
107
|
-
|
108
|
-
|
92
|
+
try:
|
93
|
+
char_width = widths[char]
|
94
|
+
except KeyError:
|
95
|
+
char_width = char_width_fn(char)
|
96
|
+
word_char_widths.append(char_width)
|
97
|
+
word_width += char_width
|
109
98
|
|
110
99
|
# we only wrap by character if the whole word alone wont fit max width
|
111
100
|
# word won't fit at all we resort to char wrapping it
|
@@ -167,6 +156,28 @@ def wrap_text(
|
|
167
156
|
current_line = [] # Reset for next line
|
168
157
|
line_width = 0
|
169
158
|
|
159
|
+
else:
|
160
|
+
for match in lines_re.finditer(text):
|
161
|
+
line_width = 0
|
162
|
+
current_line = []
|
163
|
+
for char in match.group():
|
164
|
+
try:
|
165
|
+
char_width = widths[char]
|
166
|
+
except KeyError:
|
167
|
+
char_width = char_width_fn(char)
|
168
|
+
line_width += char_width
|
169
|
+
if line_width >= max_width:
|
170
|
+
break
|
171
|
+
current_line.append(char)
|
172
|
+
|
173
|
+
if total_lines >= start_line:
|
174
|
+
yield "".join(current_line)
|
175
|
+
|
176
|
+
# Count the line whether it's empty or not
|
177
|
+
total_lines += 1
|
178
|
+
if total_lines >= max_lines:
|
179
|
+
return
|
180
|
+
|
170
181
|
|
171
182
|
def get_csv_str_dialect(s: str, delimiters: str) -> csv.Dialect:
|
172
183
|
if len(s) > 6000:
|
@@ -782,6 +793,11 @@ def move_elements_by_mapping_gen(
|
|
782
793
|
return (seq[old_idxs[i]] if i in old_idxs else next(remaining_values) for i in range(len(seq)))
|
783
794
|
|
784
795
|
|
796
|
+
def move_fast(seq: list[Any], new_idxs: dict[int, int], old_idxs: dict[int, int]) -> list[Any]:
|
797
|
+
remaining_values = (e for i, e in enumerate(seq) if i not in new_idxs)
|
798
|
+
return [seq[old_idxs[i]] if i in old_idxs else next(remaining_values) for i in range(len(seq))]
|
799
|
+
|
800
|
+
|
785
801
|
def move_elements_to(
|
786
802
|
seq: list[Any],
|
787
803
|
move_to: int,
|
@@ -808,10 +824,17 @@ def get_new_indexes(
|
|
808
824
|
returns {old idx: new idx, ...}
|
809
825
|
"""
|
810
826
|
offset = sum(1 for i in to_move if i < move_to)
|
811
|
-
|
812
|
-
if get_inverse:
|
813
|
-
return
|
814
|
-
|
827
|
+
correct_move_to = move_to - offset
|
828
|
+
if not get_inverse:
|
829
|
+
return {elem: correct_move_to + i for i, elem in enumerate(to_move)}
|
830
|
+
else:
|
831
|
+
new_idxs = {}
|
832
|
+
old_idxs = {}
|
833
|
+
for i, elem in enumerate(to_move):
|
834
|
+
value = correct_move_to + i
|
835
|
+
new_idxs[elem] = value
|
836
|
+
old_idxs[value] = elem
|
837
|
+
return new_idxs, old_idxs
|
815
838
|
|
816
839
|
|
817
840
|
def insert_items(
|
@@ -822,7 +845,7 @@ def insert_items(
|
|
822
845
|
"""
|
823
846
|
seq: list[Any]
|
824
847
|
to_insert: keys are ints sorted, representing list indexes to insert items.
|
825
|
-
Values are any, e.g. {
|
848
|
+
Values are any, e.g. {0: 200, 1: 200}
|
826
849
|
"""
|
827
850
|
if to_insert:
|
828
851
|
if seq_len_func and next(reversed(to_insert)) >= len(seq) + len(to_insert):
|
@@ -1684,3 +1707,51 @@ def pop_positions(
|
|
1684
1707
|
save_to[to_pop[i]] = pos
|
1685
1708
|
else:
|
1686
1709
|
yield pos
|
1710
|
+
|
1711
|
+
|
1712
|
+
def get_horizontal_gridline_points(
|
1713
|
+
left: float,
|
1714
|
+
stop: float,
|
1715
|
+
positions: list[float],
|
1716
|
+
start: int,
|
1717
|
+
end: int,
|
1718
|
+
) -> list[int | float]:
|
1719
|
+
return list(
|
1720
|
+
chain.from_iterable(
|
1721
|
+
(
|
1722
|
+
left - 1,
|
1723
|
+
positions[r],
|
1724
|
+
stop,
|
1725
|
+
positions[r],
|
1726
|
+
left - 1,
|
1727
|
+
positions[r],
|
1728
|
+
left - 1,
|
1729
|
+
positions[r + 1] if len(positions) - 1 > r else positions[r],
|
1730
|
+
)
|
1731
|
+
for r in range(start, end)
|
1732
|
+
)
|
1733
|
+
)
|
1734
|
+
|
1735
|
+
|
1736
|
+
def get_vertical_gridline_points(
|
1737
|
+
top: float,
|
1738
|
+
stop: float,
|
1739
|
+
positions: list[float],
|
1740
|
+
start: int,
|
1741
|
+
end: int,
|
1742
|
+
) -> list[float]:
|
1743
|
+
return list(
|
1744
|
+
chain.from_iterable(
|
1745
|
+
(
|
1746
|
+
positions[c],
|
1747
|
+
top - 1,
|
1748
|
+
positions[c],
|
1749
|
+
stop,
|
1750
|
+
positions[c],
|
1751
|
+
top - 1,
|
1752
|
+
positions[c + 1] if len(positions) - 1 > c else positions[c],
|
1753
|
+
top - 1,
|
1754
|
+
)
|
1755
|
+
for c in range(start, end)
|
1756
|
+
)
|
1757
|
+
)
|