src/black/trans.py
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | String transformers that can split and merge strings.
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | import re
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from abc import ABC, abstractmethod
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from collections import defaultdict
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from dataclasses import dataclass
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from typing import (
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Any,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Callable,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ClassVar,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Collection,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Dict,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Final,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Iterable,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Iterator,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | List,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Literal,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Optional,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Sequence,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Set,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Tuple,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | TypeVar,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Union,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | )
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from mypy_extensions import trait
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.comments import contains_pragma_comment
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.lines import Line, append_leaves
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.mode import Feature, Mode
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.nodes import (
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | CLOSING_BRACKETS,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | OPENING_BRACKETS,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | STANDALONE_COMMENT,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | is_empty_lpar,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | is_empty_par,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | is_empty_rpar,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | is_part_of_annotation,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | parent_type,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | replace_child,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | syms,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | )
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.rusty import Err, Ok, Result
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.strings import (
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | assert_is_leaf_string,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | count_chars_in_width,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | get_string_prefix,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | has_triple_quotes,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | normalize_string_quotes,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | str_width,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | )
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from blib2to3.pgen2 import token
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from blib2to3.pytree import Leaf, Node
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | class CannotTransform(Exception):
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | """Base class for errors raised by Transformers."""
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | # types
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | T = TypeVar("T")
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | LN = Union[Leaf, Node]
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Transformer = Callable[[Line, Collection[Feature], Mode], Iterator[Line]]
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Index = int
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | NodeType = int
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ParserState = int
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | StringID = int
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | TResult = Result[T, CannotTransform] # (T)ransform Result
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | TMatchResult = TResult[List[Index]]
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | SPLIT_SAFE_CHARS = frozenset(["\u3001", "\u3002", "\uff0c"]) # East Asian stops
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0007 0004 0003 0000 0003 0001 0000 -- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def TErr(err_msg: str) -> Err[CannotTransform]:
0007 0004 0003 0000 0003 0001 0000 -- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """(T)ransform Err
0007 0004 0003 0000 0003 0001 0000 -- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0007 0004 0003 0000 0003 0001 0000 -- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Convenience function used when working with the TResult type.
0007 0004 0003 0000 0003 0001 0000 -- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0004 0003 0000 0003 0001 0000 -- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | cant_transform = CannotTransform(err_msg)
0007 0004 0003 0000 0003 0001 0000 -- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return Err(cant_transform)
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | def hug_power_op(
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | line: Line, features: Collection[Feature], mode: Mode
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | ) -> Iterator[Line]:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | """A transformer which normalizes spacing around power operators."""
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # Performance optimization to avoid unnecessary Leaf clones and other ops.
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | for leaf in line.leaves:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | if leaf.type == token.DOUBLESTAR:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | break
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | else:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | raise CannotTransform("No doublestar token was found in the line.")
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | def is_simple_lookup(index: int, step: Literal[1, -1]) -> bool:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # Brackets and parentheses indicate calls, subscripts, etc. ...
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # basically stuff that doesn't count as "simple". Only a NAME lookup
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # or dotted lookup (eg. NAME.NAME) is OK.
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | if step == -1:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | disallowed = {token.RPAR, token.RSQB}
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | else:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | disallowed = {token.LPAR, token.LSQB}
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | while 0 <= index < len(line.leaves):
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | current = line.leaves[index]
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | if current.type in disallowed:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | return False
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | if current.type not in {token.NAME, token.DOT} or current.value == "for":
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # If the current token isn't disallowed, we'll assume this is simple as
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # only the disallowed tokens are semantically attached to this lookup
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # expression we're checking. Also, stop early if we hit the 'for' bit
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # of a comprehension.
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | return True
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | index += step
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | return True
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | def is_simple_operand(index: int, kind: Literal["base", "exponent"]) -> bool:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # An operand is considered "simple" if's a NAME, a numeric CONSTANT, a simple
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # lookup (see above), with or without a preceding unary operator.
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | start = line.leaves[index]
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | if start.type in {token.NAME, token.NUMBER}:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | return is_simple_lookup(index, step=(1 if kind == "exponent" else -1))
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | if start.type in {token.PLUS, token.MINUS, token.TILDE}:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | if line.leaves[index + 1].type in {token.NAME, token.NUMBER}:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # step is always one as bases with a preceding unary op will be checked
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # for simplicity starting from the next token (so it'll hit the check
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # above).
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | return is_simple_lookup(index + 1, step=1)
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | return False
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | new_line = line.clone()
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | should_hug = False
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | for idx, leaf in enumerate(line.leaves):
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | new_leaf = leaf.clone()
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | if should_hug:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | new_leaf.prefix = ""
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | should_hug = False
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | should_hug = (
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | (0 < idx < len(line.leaves) - 1)
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | and leaf.type == token.DOUBLESTAR
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | and is_simple_operand(idx - 1, kind="base")
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | and line.leaves[idx - 1].value != "lambda"
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | and is_simple_operand(idx + 1, kind="exponent")
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | )
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | if should_hug:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | new_leaf.prefix = ""
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # We have to be careful to make a new line properly:
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # - bracket related metadata must be maintained (handled by Line.append)
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | # - comments need to copied over, updating the leaf IDs they're attached to
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | new_line.append(new_leaf, preformatted=True)
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | for comment_leaf in line.comments_after(leaf):
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | new_line.append(comment_leaf, preformatted=True)
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 |
0078 0042 0049 0016 0000 0012 0017 -- 12 011 035 026 051 046 077 0425.31 3408.59 0008.01 | yield new_line
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | class StringTransformer(ABC):
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | An implementation of the Transformer protocol that relies on its
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | subclasses overriding the template methods `do_match(...)` and
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | `do_transform(...)`.
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | This Transformer works exclusively on strings (for example, by merging
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | or splitting them).
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | The following sections can be found among the docstrings of each concrete
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | StringTransformer subclass.
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | Requirements:
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | Which requirements must be met of the given Line for this
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | StringTransformer to be applied?
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | Transformations:
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | If the given Line meets all of the above requirements, which string
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | transformations can you expect to be applied to it by this
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | StringTransformer?
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | Collaborations:
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | What contractual agreements does this StringTransformer have with other
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | StringTransfomers? Such collaborations should be eliminated/minimized
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | as much as possible.
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | __name__: Final = "StringTransformer"
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | # Ideally this would be a dataclass, but unfortunately mypyc breaks when used with
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | # `abc.ABC`.
0003 0003 0003 0000 0000 0000 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def __init__(self, line_length: int, normalize_strings: bool) -> None:
0003 0003 0003 0000 0000 0000 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.line_length = line_length
0003 0003 0003 0000 0000 0000 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.normalize_strings = normalize_strings
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | @abstractmethod
0012 0003 0002 0000 0010 0000 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def do_match(self, line: Line) -> TMatchResult:
0012 0003 0002 0000 0010 0000 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0012 0003 0002 0000 0010 0000 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Returns:
0012 0003 0002 0000 0010 0000 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | * Ok(string_indices) such that for each index, `line.leaves[index]`
0012 0003 0002 0000 0010 0000 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | is our target string if a match was able to be made. For
0012 0003 0002 0000 0010 0000 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | transformers that don't result in more lines (e.g. StringMerger,
0012 0003 0002 0000 0010 0000 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | StringParenStripper), multiple matches and transforms are done at
0012 0003 0002 0000 0010 0000 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | once to reduce the complexity.
0012 0003 0002 0000 0010 0000 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | OR
0012 0003 0002 0000 0010 0000 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | * Err(CannotTransform), if no match could be made.
0012 0003 0002 0000 0010 0000 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0012 0003 0002 0000 0010 0000 0000 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | @abstractmethod
0020 0003 0004 0000 0015 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def do_transform(
0020 0003 0004 0000 0015 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self, line: Line, string_indices: List[int]
0020 0003 0004 0000 0015 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | ) -> Iterator[TResult[Line]]:
0020 0003 0004 0000 0015 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Yields:
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | * Ok(new_line) where new_line is the new transformed line.
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | OR
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | * Err(CannotTransform) if the transformation failed for some reason. The
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | `do_match(...)` template method should usually be used to reject
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | the form of the given Line, but in some cases it is difficult to
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | know whether or not a Line meets the StringTransformer's
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | requirements until the transformation is already midway.
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Side Effects:
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | This method should NOT mutate @line directly, but it MAY mutate the
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Line's underlying Node structure. (WARNING: If the underlying Node
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | structure IS altered, then this method should NOT be allowed to
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | yield an CannotTransform after that point.)
0020 0003 0004 0000 0015 0001 0000 03 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0020 0003 0004 0000 0015 0001 0000 03 -- --- --- --- --- --- --- ------- ------- ------- |
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | def __call__(
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | self, line: Line, _features: Collection[Feature], _mode: Mode
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | ) -> Iterator[Line]:
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | """
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | StringTransformer instances have a call signature that mirrors that of
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | the Transformer type.
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | Raises:
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | CannotTransform(...) if the concrete StringTransformer class is unable
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | to transform @line.
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | """
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | # Optimization to avoid calling `self.do_match(...)` when the line does
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | # not contain any string.
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | if not any(leaf.type == token.STRING for leaf in line.leaves):
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | raise CannotTransform("There are no strings in this line.")
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | match_result = self.do_match(line)
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | if isinstance(match_result, Err):
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | cant_transform = match_result.err()
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | raise CannotTransform(
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | f"The string transformer {self.__class__.__name__} does not recognize"
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | " this line as one that it can transform."
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | ) from cant_transform
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | string_indices = match_result.ok()
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | for line_result in self.do_transform(line, string_indices):
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | if isinstance(line_result, Err):
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | cant_transform = line_result.err()
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | raise CannotTransform(
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | "StringTransformer failed while attempting to transform string."
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | ) from cant_transform
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | line = line_result.ok()
0035 0015 0021 0002 0007 0005 0002 03 06 002 003 002 003 005 005 0011.61 0011.61 0001.00 | yield line
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | @dataclass
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | class CustomSplit:
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | """A custom (i.e. manual) string split.
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | A single CustomSplit instance represents a single substring.
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | Examples:
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | Consider the following string:
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | "Hi there friend."
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | " This is a custom"
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | f" string {split}."
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | This string will correspond to the following three CustomSplit instances:
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | CustomSplit(False, 16)
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | CustomSplit(False, 17)
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | CustomSplit(True, 16)
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | has_prefix: bool
---- ---- ---- ---- ---- ---- ---- 01 -- --- --- --- --- --- --- ------- ------- ------- | break_idx: int
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | @trait
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | class CustomSplitMapMixin:
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | This mixin class is used to map merged strings to a sequence of
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | CustomSplits, which will then be used to re-split the strings iff none of
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | the resultant substrings go over the configured max line length.
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | _Key: ClassVar = Tuple[StringID, str]
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | _CUSTOM_SPLIT_MAP: ClassVar[Dict[_Key, Tuple[CustomSplit, ...]]] = defaultdict(
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | tuple
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | )
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
0008 0004 0003 0000 0005 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def _get_key(string: str) -> "CustomSplitMapMixin._Key":
0008 0004 0003 0000 0005 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0008 0004 0003 0000 0005 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Returns:
0008 0004 0003 0000 0005 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | A unique identifier that is used internally to map @string to a
0008 0004 0003 0000 0005 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | group of custom splits.
0008 0004 0003 0000 0005 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0008 0004 0003 0000 0005 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return (id(string), string)
0008 0004 0003 0000 0005 0000 0000 02 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def add_custom_splits(
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self, string: str, custom_splits: Iterable[CustomSplit]
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | ) -> None:
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """Custom Split Map Setter Method
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Side Effects:
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Adds a mapping from @string to the custom splits @custom_splits.
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | key = self._get_key(string)
0010 0004 0005 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self._CUSTOM_SPLIT_MAP[key] = tuple(custom_splits)
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def pop_custom_splits(self, string: str) -> List[CustomSplit]:
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """Custom Split Map Getter Method
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Returns:
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | * A list of the custom splits that are mapped to @string, if any
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | exist.
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | OR
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | * [], otherwise.
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Side Effects:
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Deletes the mapping between @string and its associated custom
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | splits (which are returned to the caller).
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | key = self._get_key(string)
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | custom_splits = self._CUSTOM_SPLIT_MAP[key]
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | del self._CUSTOM_SPLIT_MAP[key]
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0019 0006 0005 0000 0010 0004 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return list(custom_splits)
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0007 0004 0003 0000 0004 0000 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def has_custom_splits(self, string: str) -> bool:
0007 0004 0003 0000 0004 0000 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0007 0004 0003 0000 0004 0000 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Returns:
0007 0004 0003 0000 0004 0000 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | True iff @string is associated with a set of custom splits.
0007 0004 0003 0000 0004 0000 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0007 0004 0003 0000 0004 0000 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | key = self._get_key(string)
0007 0004 0003 0000 0004 0000 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return key in self._CUSTOM_SPLIT_MAP
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | class StringMerger(StringTransformer, CustomSplitMapMixin):
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | """StringTransformer that merges strings together.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | Requirements:
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | (A) The line contains adjacent strings such that ALL of the validation checks
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | listed in StringMerger._validate_msg(...)'s docstring pass.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | OR
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | (B) The line contains a string which uses line continuation backslashes.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | Transformations:
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | Depending on which of the two requirements above where met, either:
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | (A) The string group associated with the target string is merged.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | OR
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | (B) All line-continuation backslashes are removed from the target string.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | Collaborations:
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | StringMerger provides custom split information to StringSplitter.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | def do_match(self, line: Line) -> TMatchResult:
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | LL = line.leaves
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 |
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | is_valid_index = is_valid_index_factory(LL)
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 |
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | string_indices = []
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | idx = 0
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | while is_valid_index(idx):
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | leaf = LL[idx]
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | if (
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | leaf.type == token.STRING
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | and is_valid_index(idx + 1)
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | and LL[idx + 1].type == token.STRING
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | ):
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | # Let's check if the string group contains an inline comment
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | # If we have a comment inline, we don't merge the strings
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | contains_comment = False
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | i = idx
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | while is_valid_index(i):
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | if LL[i].type != token.STRING:
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | break
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | if line.comments_after(LL[i]):
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | contains_comment = True
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | break
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | i += 1
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 |
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | if not is_part_of_annotation(leaf) and not contains_comment:
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | string_indices.append(idx)
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 |
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | # Advance to the next non-STRING leaf.
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | idx += 2
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | while is_valid_index(idx) and LL[idx].type == token.STRING:
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | idx += 1
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 |
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | elif leaf.type == token.STRING and "\\\n" in leaf.value:
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | string_indices.append(idx)
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | # Advance to the next non-STRING leaf.
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | idx += 1
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | while is_valid_index(idx) and LL[idx].type == token.STRING:
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | idx += 1
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 |
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | else:
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | idx += 1
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 |
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | if string_indices:
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | return Ok(string_indices)
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | else:
0048 0033 0037 0004 0000 0007 0004 12 17 006 021 022 043 027 065 0309.07 1898.56 0006.14 | return TErr("This line has no strings that need merging.")
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def do_transform(
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self, line: Line, string_indices: List[int]
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | ) -> Iterator[TResult[Line]]:
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | new_line = line
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | rblc_result = self._remove_backslash_line_continuation_chars(
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | new_line, string_indices
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | )
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if isinstance(rblc_result, Ok):
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | new_line = rblc_result.ok()
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | msg_result = self._merge_string_group(new_line, string_indices)
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if isinstance(msg_result, Ok):
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | new_line = msg_result.ok()
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if isinstance(rblc_result, Err) and isinstance(msg_result, Err):
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | msg_cant_transform = msg_result.err()
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | rblc_cant_transform = rblc_result.err()
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | cant_transform = CannotTransform(
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | "StringMerger failed to merge any strings in this line."
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | )
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | # Chain the errors together using `__cause__`.
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | msg_cant_transform.__cause__ = rblc_cant_transform
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | cant_transform.__cause__ = msg_cant_transform
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | yield Err(cant_transform)
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | else:
0029 0017 0023 0001 0000 0005 0001 12 05 001 002 001 002 003 003 0004.75 0002.38 0000.50 | yield Ok(new_line)
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | def _remove_backslash_line_continuation_chars(
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | line: Line, string_indices: List[int]
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | ) -> TResult[Line]:
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | """
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | Merge strings that were split across multiple lines using
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | line-continuation backslashes.
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 |
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | Returns:
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | Ok(new_line), if @line contains backslash line-continuation
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | characters.
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | OR
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | Err(CannotTransform), otherwise.
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | """
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | LL = line.leaves
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 |
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | indices_to_transform = []
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | for string_idx in string_indices:
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | string_leaf = LL[string_idx]
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | if (
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | string_leaf.type == token.STRING
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | and "\\\n" in string_leaf.value
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | and not has_triple_quotes(string_leaf.value)
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | ):
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | indices_to_transform.append(string_idx)
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 |
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | if not indices_to_transform:
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | return TErr(
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | "Found no string leaves that contain backslash line continuation"
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | " characters."
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | )
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 |
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | new_line = line.clone()
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | new_line.comments = line.comments.copy()
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | append_leaves(new_line, line, LL)
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 |
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | for string_idx in indices_to_transform:
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | new_string_leaf = new_line.leaves[string_idx]
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | new_string_leaf.value = new_string_leaf.value.replace("\\\n", "")
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 |
0041 0018 0026 0000 0009 0006 0000 12 07 004 009 005 009 013 014 0051.81 0103.61 0002.00 | return Ok(new_line)
0041 0018 0026 0000 0009 0006 0000 12 -- --- --- --- --- --- --- ------- ------- ------- |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | def _merge_string_group(
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | self, line: Line, string_indices: List[int]
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | ) -> TResult[Line]:
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | """
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | Merges string groups (i.e. set of adjacent strings).
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | Each index from `string_indices` designates one string group's first
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | leaf in `line.leaves`.
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | Returns:
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | Ok(new_line), if ALL of the validation checks found in
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | _validate_msg(...) pass.
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | OR
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | Err(CannotTransform), otherwise.
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | """
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | LL = line.leaves
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | is_valid_index = is_valid_index_factory(LL)
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | # A dict of {string_idx: tuple[num_of_strings, string_leaf]}.
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | merged_string_idx_dict: Dict[int, Tuple[int, Leaf]] = {}
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | for string_idx in string_indices:
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | vresult = self._validate_msg(line, string_idx)
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | if isinstance(vresult, Err):
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | continue
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | merged_string_idx_dict[string_idx] = self._merge_one_string_group(
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | LL, string_idx, is_valid_index
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | )
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | if not merged_string_idx_dict:
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | return TErr("No string group is merged")
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | # Build the final line ('new_line') that this method will later return.
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | new_line = line.clone()
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | previous_merged_string_idx = -1
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | previous_merged_num_of_strings = -1
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | for i, leaf in enumerate(LL):
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | if i in merged_string_idx_dict:
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | previous_merged_string_idx = i
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | previous_merged_num_of_strings, string_leaf = merged_string_idx_dict[i]
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | new_line.append(string_leaf)
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | if (
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | previous_merged_string_idx
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | <= i
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | < previous_merged_string_idx + previous_merged_num_of_strings
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | ):
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | for comment_leaf in line.comments_after(LL[i]):
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | new_line.append(comment_leaf, preformatted=True)
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | continue
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | append_leaves(new_line, line, [leaf])
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 |
0054 0027 0033 0002 0010 0009 0002 12 08 006 006 007 010 012 017 0060.94 0304.72 0005.00 | return Ok(new_line)
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | def _merge_one_string_group(
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | self, LL: List[Leaf], string_idx: int, is_valid_index: Callable[[int], bool]
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | ) -> Tuple[int, Leaf]:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | """
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | Merges one string group where the first string in the group is
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | `LL[string_idx]`.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | Returns:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | A tuple of `(num_of_strings, leaf)` where `num_of_strings` is the
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | number of strings merged and `leaf` is the newly merged string
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | to be replaced in the new line.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | """
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # If the string group is wrapped inside an Atom node, we must make sure
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # to later replace that Atom with our new (merged) string leaf.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | atom_node = LL[string_idx].parent
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # We will place BREAK_MARK in between every two substrings that we
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # merge. We will then later go through our final result and use the
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # various instances of BREAK_MARK we find to add the right values to
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # the custom split map.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | BREAK_MARK = "@@@@@ BLACK BREAKPOINT MARKER @@@@@"
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | QUOTE = LL[string_idx].value[-1]
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | def make_naked(string: str, string_prefix: str) -> str:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | """Strip @string (i.e. make it a "naked" string)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | Pre-conditions:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | * assert_is_leaf_string(@string)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | Returns:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | A string that is identical to @string except that
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | @string_prefix has been stripped, the surrounding QUOTE
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | characters have been removed, and any remaining QUOTE
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | characters have been escaped.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | """
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | assert_is_leaf_string(string)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | if "f" in string_prefix:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | f_expressions = (
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | string[span[0] + 1 : span[1] - 1] # +-1 to get rid of curly braces
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | for span in iter_fexpr_spans(string)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | )
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | debug_expressions_contain_visible_quotes = any(
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | re.search(r".*[\'\"].*(?<![!:=])={1}(?!=)(?![^\s:])", expression)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | for expression in f_expressions
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | )
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | if not debug_expressions_contain_visible_quotes:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # We don't want to toggle visible quotes in debug f-strings, as
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # that would modify the AST
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | string = _toggle_fexpr_quotes(string, QUOTE)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # After quotes toggling, quotes in expressions won't be escaped
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # because quotes can't be reused in f-strings. So we can simply
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # let the escaping logic below run without knowing f-string
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # expressions.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | RE_EVEN_BACKSLASHES = r"(?:(?<!\\)(?:\\\\)*)"
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | naked_string = string[len(string_prefix) + 1 : -1]
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | naked_string = re.sub(
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | "(" + RE_EVEN_BACKSLASHES + ")" + QUOTE, r"\1\\" + QUOTE, naked_string
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | )
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | return naked_string
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # Holds the CustomSplit objects that will later be added to the custom
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # split map.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | custom_splits = []
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # Temporary storage for the 'has_prefix' part of the CustomSplit objects.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | prefix_tracker = []
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # Sets the 'prefix' variable. This is the prefix that the final merged
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # string will have.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | next_str_idx = string_idx
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | prefix = ""
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | while (
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | not prefix
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | and is_valid_index(next_str_idx)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | and LL[next_str_idx].type == token.STRING
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | ):
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | prefix = get_string_prefix(LL[next_str_idx].value).lower()
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | next_str_idx += 1
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # The next loop merges the string group. The final string will be
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # contained in 'S'.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | #
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # The following convenience variables are used:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | #
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # S: string
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # NS: naked string
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # SS: next string
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # NSS: naked next string
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | S = ""
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | NS = ""
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | num_of_strings = 0
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | next_str_idx = string_idx
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | while is_valid_index(next_str_idx) and LL[next_str_idx].type == token.STRING:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | num_of_strings += 1
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | SS = LL[next_str_idx].value
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | next_prefix = get_string_prefix(SS).lower()
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # If this is an f-string group but this substring is not prefixed
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # with 'f'...
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | if "f" in prefix and "f" not in next_prefix:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # Then we must escape any braces contained in this substring.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | SS = re.sub(r"(\{|\})", r"\1\1", SS)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | NSS = make_naked(SS, next_prefix)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | has_prefix = bool(next_prefix)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | prefix_tracker.append(has_prefix)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | S = prefix + QUOTE + NS + NSS + BREAK_MARK + QUOTE
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | NS = make_naked(S, prefix)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | next_str_idx += 1
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # Take a note on the index of the non-STRING leaf.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | non_string_idx = next_str_idx
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | S_leaf = Leaf(token.STRING, S)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | if self.normalize_strings:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | S_leaf.value = normalize_string_quotes(S_leaf.value)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # Fill the 'custom_splits' list with the appropriate CustomSplit objects.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | temp_string = S_leaf.value[len(prefix) + 1 : -1]
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | for has_prefix in prefix_tracker:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | mark_idx = temp_string.find(BREAK_MARK)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | assert (
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | mark_idx >= 0
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | ), "Logic error while filling the custom string breakpoint cache."
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | temp_string = temp_string[mark_idx + len(BREAK_MARK) :]
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | breakpoint_idx = mark_idx + (len(prefix) if has_prefix else 0) + 1
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | custom_splits.append(CustomSplit(has_prefix, breakpoint_idx))
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | string_leaf = Leaf(token.STRING, S_leaf.value.replace(BREAK_MARK, ""))
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | if atom_node is not None:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # If not all children of the atom node are merged (this can happen
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # when there is a standalone comment in the middle) ...
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | if non_string_idx - string_idx < len(atom_node.children):
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # We need to replace the old STRING leaves with the new string leaf.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | first_child_idx = LL[string_idx].remove()
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | for idx in range(string_idx + 1, non_string_idx):
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | LL[idx].remove()
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | if first_child_idx is not None:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | atom_node.insert_child(first_child_idx, string_leaf)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | else:
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | # Else replace the atom node with the new string leaf.
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | replace_child(atom_node, string_leaf)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 |
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | self.add_custom_splits(string_leaf.value, custom_splits)
0153 0067 0077 0036 0017 0024 0035 12 15 011 050 038 072 061 110 0652.38 5166.86 0007.92 | return num_of_strings, string_leaf
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | def _validate_msg(line: Line, string_idx: int) -> TResult[None]:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | """Validate (M)erge (S)tring (G)roup
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | Transform-time string validation logic for _merge_string_group(...).
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | Returns:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | * Ok(None), if ALL validation checks (listed below) pass.
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | OR
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | * Err(CannotTransform), if any of the following are true:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | - The target string group does not contain ANY stand-alone comments.
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | - The target string is not in a string group (i.e. it has no
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | adjacent strings).
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | - The string group has more than one inline comment.
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | - The string group has an inline comment that appears to be a pragma.
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | - The set of all string prefixes in the string group is of
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | length greater than one and is not equal to {"", "f"}.
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | - The string group consists of raw strings.
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | - The string group is stringified type annotations. We don't want to
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | process stringified type annotations since pyright doesn't support
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | them spanning multiple string values. (NOTE: mypy, pytype, pyre do
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | support them, so we can change if pyright also gains support in the
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | future. See https://github.com/microsoft/pyright/issues/4359.)
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | """
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | # We first check for "inner" stand-alone comments (i.e. stand-alone
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | # comments that have a string leaf before them AND after them).
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | for inc in [1, -1]:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | i = string_idx
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | found_sa_comment = False
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | is_valid_index = is_valid_index_factory(line.leaves)
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | while is_valid_index(i) and line.leaves[i].type in [
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | token.STRING,
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | STANDALONE_COMMENT,
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | ]:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if line.leaves[i].type == STANDALONE_COMMENT:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | found_sa_comment = True
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | elif found_sa_comment:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | return TErr(
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | "StringMerger does NOT merge string groups which contain "
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | "stand-alone comments."
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | )
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | i += inc
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | num_of_inline_string_comments = 0
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | set_of_prefixes = set()
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | num_of_strings = 0
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | for leaf in line.leaves[string_idx:]:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if leaf.type != token.STRING:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | # If the string group is trailed by a comma, we count the
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | # comments trailing the comma to be one of the string group's
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | # comments.
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if leaf.type == token.COMMA and id(leaf) in line.comments:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | num_of_inline_string_comments += 1
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | break
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if has_triple_quotes(leaf.value):
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | return TErr("StringMerger does NOT merge multiline strings.")
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | num_of_strings += 1
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | prefix = get_string_prefix(leaf.value).lower()
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if "r" in prefix:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | return TErr("StringMerger does NOT merge raw strings.")
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | set_of_prefixes.add(prefix)
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if id(leaf) in line.comments:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | num_of_inline_string_comments += 1
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if contains_pragma_comment(line.comments[id(leaf)]):
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | return TErr("Cannot merge strings which have pragma comments.")
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if num_of_strings < 2:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | return TErr(
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | f"Not enough strings to merge (num_of_strings={num_of_strings})."
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | )
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if num_of_inline_string_comments > 1:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | return TErr(
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | f"Too many inline string comments ({num_of_inline_string_comments})."
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | )
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | if len(set_of_prefixes) > 1 and set_of_prefixes != {"", "f"}:
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | return TErr(f"Too many different prefixes ({set_of_prefixes}).")
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 |
0085 0039 0048 0005 0020 0012 0005 12 18 008 025 019 037 033 056 0282.49 1672.32 0005.92 | return Ok(None)
0085 0039 0048 0005 0020 0012 0005 -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | class StringParenStripper(StringTransformer):
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | """StringTransformer that strips surrounding parentheses from strings.
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | Requirements:
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | The line contains a string which is surrounded by parentheses and:
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | - The target string is NOT the only argument to a function call.
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | - The target string is NOT a "pointless" string.
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | - If the target string contains a PERCENT, the brackets are not
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | preceded or followed by an operator with higher precedence than
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | PERCENT.
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | Transformations:
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | The parentheses mentioned in the 'Requirements' section are stripped.
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | Collaborations:
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | StringParenStripper has its own inherent usefulness, but it is also
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | relied on to clean up the parentheses created by StringParenWrapper (in
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | the event that they are no longer needed).
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | def do_match(self, line: Line) -> TMatchResult:
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | LL = line.leaves
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | is_valid_index = is_valid_index_factory(LL)
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | string_indices = []
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | idx = -1
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | while True:
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | idx += 1
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if idx >= len(LL):
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | break
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | leaf = LL[idx]
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # Should be a string...
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if leaf.type != token.STRING:
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | continue
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # If this is a "pointless" string...
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if (
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | leaf.parent
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | and leaf.parent.parent
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | and leaf.parent.parent.type == syms.simple_stmt
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | ):
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | continue
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # Should be preceded by a non-empty LPAR...
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if (
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | not is_valid_index(idx - 1)
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | or LL[idx - 1].type != token.LPAR
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | or is_empty_lpar(LL[idx - 1])
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | ):
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | continue
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # That LPAR should NOT be preceded by a function name or a closing
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # bracket (which could be a function which returns a function or a
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # list/dictionary that contains a function)...
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if is_valid_index(idx - 2) and (
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | LL[idx - 2].type == token.NAME or LL[idx - 2].type in CLOSING_BRACKETS
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | ):
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | continue
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | string_idx = idx
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # Skip the string trailer, if one exists.
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | string_parser = StringParser()
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | next_idx = string_parser.parse(LL, string_idx)
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # if the leaves in the parsed string include a PERCENT, we need to
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # make sure the initial LPAR is NOT preceded by an operator with
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # higher or equal precedence to PERCENT
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if is_valid_index(idx - 2):
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # mypy can't quite follow unless we name this
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | before_lpar = LL[idx - 2]
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if token.PERCENT in {leaf.type for leaf in LL[idx - 1 : next_idx]} and (
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | (
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | before_lpar.type
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | in {
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.STAR,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.AT,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.SLASH,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.DOUBLESLASH,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.PERCENT,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.TILDE,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.DOUBLESTAR,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.AWAIT,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.LSQB,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.LPAR,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | }
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | )
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | or (
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # only unary PLUS/MINUS
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | before_lpar.parent
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | and before_lpar.parent.type == syms.factor
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | and (before_lpar.type in {token.PLUS, token.MINUS})
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | )
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | ):
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | continue
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # Should be followed by a non-empty RPAR...
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if (
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | is_valid_index(next_idx)
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | and LL[next_idx].type == token.RPAR
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | and not is_empty_rpar(LL[next_idx])
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | ):
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # That RPAR should NOT be followed by anything with higher
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | # precedence than PERCENT
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if is_valid_index(next_idx + 1) and LL[next_idx + 1].type in {
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.DOUBLESTAR,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.LSQB,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.LPAR,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | token.DOT,
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | }:
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | continue
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | string_indices.append(string_idx)
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | idx = string_idx
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | while idx < len(LL) - 1 and LL[idx + 1].type == token.STRING:
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | idx += 1
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 |
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | if string_indices:
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | return Ok(string_indices)
0103 0035 0076 0015 0000 0013 0014 14 28 011 044 042 085 055 127 0734.23 7801.22 0010.62 | return TErr("This line has no strings wrapped in parens.")
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- |
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def do_transform(
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self, line: Line, string_indices: List[int]
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | ) -> Iterator[TResult[Line]]:
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | LL = line.leaves
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | string_and_rpar_indices: List[int] = []
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | for string_idx in string_indices:
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | string_parser = StringParser()
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | rpar_idx = string_parser.parse(LL, string_idx)
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | should_transform = True
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | for leaf in (LL[string_idx - 1], LL[rpar_idx]):
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if line.comments_after(leaf):
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | # Should not strip parentheses which have comments attached
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | # to them.
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | should_transform = False
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | break
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if should_transform:
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | string_and_rpar_indices.extend((string_idx, rpar_idx))
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if string_and_rpar_indices:
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | yield Ok(self._transform_to_new_line(line, string_and_rpar_indices))
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | else:
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | yield Err(
0026 0018 0021 0002 0000 0003 0002 14 06 001 002 001 002 003 003 0004.75 0002.38 0000.50 | CannotTransform("All string groups have comments attached to them.")
0026 0018 0021 0002 0000 0003 0002 14 -- 001 002 001 002 003 003 0004.75 0002.38 0000.50 | )
---- ---- ---- ---- ---- ---- ---- 14 -- --- --- --- --- --- --- ------- ------- ------- |
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | def _transform_to_new_line(
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | self, line: Line, string_and_rpar_indices: List[int]
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | ) -> Line:
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | LL = line.leaves
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 |
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | new_line = line.clone()
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | new_line.comments = line.comments.copy()
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 |
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | previous_idx = -1
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | # We need to sort the indices, since string_idx and its matching
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | # rpar_idx may not come in order, e.g. in
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | # `("outer" % ("inner".join(items)))`, the "inner" string's
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | # string_idx is smaller than "outer" string's rpar_idx.
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | for idx in sorted(string_and_rpar_indices):
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | leaf = LL[idx]
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | lpar_or_rpar_idx = idx - 1 if leaf.type == token.STRING else idx
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | append_leaves(new_line, line, LL[previous_idx + 1 : lpar_or_rpar_idx])
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | if leaf.type == token.STRING:
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | string_leaf = Leaf(token.STRING, LL[idx].value)
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | LL[lpar_or_rpar_idx].remove() # Remove lpar.
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | replace_child(LL[idx], string_leaf)
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | new_line.append(string_leaf)
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | # replace comments
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | old_comments = new_line.comments.pop(id(LL[idx]), [])
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | new_line.comments.setdefault(id(string_leaf), []).extend(old_comments)
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | else:
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | LL[lpar_or_rpar_idx].remove() # This is a rpar.
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 |
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | previous_idx = idx
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 |
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | # Append the leaves after the last idx:
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | append_leaves(new_line, line, LL[idx + 1 :])
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 |
0034 0023 0023 0008 0000 0005 0006 14 04 004 005 006 011 009 017 0053.89 0237.11 0004.40 | return new_line
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | class BaseStringSplitter(StringTransformer):
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | Abstract class for StringTransformers which transform a Line's strings by splitting
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | them or placing them on their own lines where necessary to avoid going over
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | the configured line length.
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | Requirements:
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | * The target string value is responsible for the line going over the
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | line length limit. It follows that after all of black's other line
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | split methods have been exhausted, this line (or one of the resulting
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | lines after all line splits are performed) would still be over the
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | line_length limit unless we split this string.
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | AND
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | * The target string is NOT a "pointless" string (i.e. a string that has
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | no parent or siblings).
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | AND
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | * The target string is not followed by an inline comment that appears
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | to be a pragma.
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | AND
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | * The target string is not a multiline (i.e. triple-quote) string.
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | STRING_OPERATORS: Final = [
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | token.EQEQUAL,
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | token.GREATER,
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | token.GREATEREQUAL,
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | token.LESS,
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | token.LESSEQUAL,
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | token.NOTEQUAL,
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | token.PERCENT,
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | token.PLUS,
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | token.STAR,
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | ]
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | @abstractmethod
0010 0003 0002 0000 0006 0002 0000 10 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def do_splitter_match(self, line: Line) -> TMatchResult:
0010 0003 0002 0000 0006 0002 0000 10 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0010 0003 0002 0000 0006 0002 0000 10 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | BaseStringSplitter asks its clients to override this method instead of
0010 0003 0002 0000 0006 0002 0000 10 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | `StringTransformer.do_match(...)`.
0010 0003 0002 0000 0006 0002 0000 10 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0010 0003 0002 0000 0006 0002 0000 10 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Follows the same protocol as `StringTransformer.do_match(...)`.
0010 0003 0002 0000 0006 0002 0000 10 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0010 0003 0002 0000 0006 0002 0000 10 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Refer to `help(StringTransformer.do_match)` for more information.
0010 0003 0002 0000 0006 0002 0000 10 -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0010 0003 0002 0000 0006 0002 0000 10 -- --- --- --- --- --- --- ------- ------- ------- |
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def do_match(self, line: Line) -> TMatchResult:
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | match_result = self.do_splitter_match(line)
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if isinstance(match_result, Err):
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return match_result
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | string_indices = match_result.ok()
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | assert len(string_indices) == 1, (
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | f"{self.__class__.__name__} should only find one match at a time, found"
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | f" {len(string_indices)}"
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | )
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | string_idx = string_indices[0]
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | vresult = self._validate(line, string_idx)
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if isinstance(vresult, Err):
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return vresult
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0016 0011 0014 0000 0000 0002 0000 10 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return match_result
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- |
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | def _validate(self, line: Line, string_idx: int) -> TResult[None]:
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | """
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | Checks that @line meets all of the requirements listed in this classes'
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | docstring. Refer to `help(BaseStringSplitter)` for a detailed
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | description of those requirements.
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 |
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | Returns:
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | * Ok(None), if ALL of the requirements are met.
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | OR
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | * Err(CannotTransform), if ANY of the requirements are NOT met.
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | """
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | LL = line.leaves
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 |
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | string_leaf = LL[string_idx]
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 |
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | max_string_length = self._get_max_string_length(line, string_idx)
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | if len(string_leaf.value) <= max_string_length:
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | return TErr(
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | "The string itself is not what is causing this line to be too long."
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | )
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 |
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | if not string_leaf.parent or [L.type for L in string_leaf.parent.children] == [
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | token.STRING,
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | token.NEWLINE,
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | ]:
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | return TErr(
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | f"This string ({string_leaf.value}) appears to be pointless (i.e. has"
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | " no parent)."
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | )
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 |
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | if id(line.leaves[string_idx]) in line.comments and contains_pragma_comment(
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | line.comments[id(line.leaves[string_idx])]
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | ):
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | return TErr(
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | "Line appears to end with an inline pragma comment. Splitting the line"
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | " could modify the pragma's behavior."
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | )
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 |
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | if has_triple_quotes(string_leaf.value):
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | return TErr("We cannot split multiline strings.")
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 |
0042 0014 0026 0000 0009 0007 0000 10 08 006 011 006 011 017 017 0069.49 0208.46 0003.00 | return Ok(None)
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | def _get_max_string_length(self, line: Line, string_idx: int) -> int:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | """
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | Calculates the max string length used when attempting to determine
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | whether or not the target string is responsible for causing the line to
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | go over the line length limit.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | WARNING: This method is tightly coupled to both StringSplitter and
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | (especially) StringParenWrapper. There is probably a better way to
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | accomplish what is being done here.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | Returns:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | max_string_length: such that `line.leaves[string_idx].value >
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | max_string_length` implies that the target string IS responsible
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | for causing this line to exceed the line length limit.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | """
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | LL = line.leaves
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | is_valid_index = is_valid_index_factory(LL)
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # We use the shorthand "WMA4" in comments to abbreviate "We must
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # account for". When giving examples, we use STRING to mean some/any
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # valid string.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | #
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # Finally, we use the following convenience variables:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | #
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # P: The leaf that is before the target string leaf.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # N: The leaf that is after the target string leaf.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # NN: The leaf that is after N.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 the whitespace at the beginning of the line.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset = line.depth * 4
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if is_valid_index(string_idx - 1):
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | p_idx = string_idx - 1
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if (
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | LL[string_idx - 1].type == token.LPAR
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | and LL[string_idx - 1].value == ""
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | and string_idx >= 2
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | ):
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # If the previous leaf is an empty LPAR placeholder, we should skip it.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | p_idx -= 1
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | P = LL[p_idx]
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if P.type in self.STRING_OPERATORS:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 a space and a string operator (e.g. `+ STRING` or `== STRING`).
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += len(str(P)) + 1
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if P.type == token.COMMA:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 a space, a comma, and a closing bracket [e.g. `), STRING`].
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += 3
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if P.type in [token.COLON, token.EQUAL, token.PLUSEQUAL, token.NAME]:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # This conditional branch is meant to handle dictionary keys,
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # variable assignments, 'return STRING' statement lines, and
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # 'else STRING' ternary expression lines.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 a single space.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += 1
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 the lengths of any leaves that came before that space,
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # but after any closing bracket before that space.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | for leaf in reversed(LL[: p_idx + 1]):
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += len(str(leaf))
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if leaf.type in CLOSING_BRACKETS:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | break
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if is_valid_index(string_idx + 1):
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | N = LL[string_idx + 1]
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if N.type == token.RPAR and N.value == "" and len(LL) > string_idx + 2:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # If the next leaf is an empty RPAR placeholder, we should skip it.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | N = LL[string_idx + 2]
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if N.type == token.COMMA:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 a single comma at the end of the string (e.g `STRING,`).
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += 1
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if is_valid_index(string_idx + 2):
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | NN = LL[string_idx + 2]
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if N.type == token.DOT and NN.type == token.NAME:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # This conditional branch is meant to handle method calls invoked
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # off of a string literal up to and including the LPAR character.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 the '.' character.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += 1
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if (
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | is_valid_index(string_idx + 3)
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | and LL[string_idx + 3].type == token.LPAR
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | ):
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 the left parenthesis character.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += 1
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 the length of the method's name.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += len(NN.value)
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | has_comments = False
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | for comment_leaf in line.comments_after(LL[string_idx]):
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | if not has_comments:
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | has_comments = True
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 two spaces before the '#' character.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += 2
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | # WMA4 the length of the inline comment.
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | offset += len(comment_leaf.value)
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 |
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | max_string_length = count_chars_in_width(str(line), self.line_length - offset)
0108 0041 0047 0028 0012 0021 0028 10 22 009 038 046 093 047 139 0772.09 8503.13 0011.01 | return max_string_length
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 10 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | def _prefer_paren_wrap_match(LL: List[Leaf]) -> Optional[int]:
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | """
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | Returns:
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | string_idx such that @LL[string_idx] is equal to our target (i.e.
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | matched) string, if this line matches the "prefer paren wrap" statement
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | requirements listed in the 'Requirements' section of the StringParenWrapper
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | class's docstring.
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | OR
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | None, otherwise.
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | """
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | # The line must start with a string.
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | if LL[0].type != token.STRING:
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | return None
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 |
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | matching_nodes = [
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | syms.listmaker,
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | syms.dictsetmaker,
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | syms.testlist_gexp,
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | ]
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | # If the string is an immediate child of a list/set/tuple literal...
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | if (
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | parent_type(LL[0]) in matching_nodes
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | or parent_type(LL[0].parent) in matching_nodes
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | ):
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | # And the string is surrounded by commas (or is the first/last child)...
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | prev_sibling = LL[0].prev_sibling
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | next_sibling = LL[0].next_sibling
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | if (
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | not prev_sibling
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | and not next_sibling
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | and parent_type(LL[0]) == syms.atom
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | ):
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | # If it's an atom string, we need to check the parent atom's siblings.
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | parent = LL[0].parent
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | assert parent is not None # For type checkers.
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | prev_sibling = parent.prev_sibling
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | next_sibling = parent.next_sibling
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | if (not prev_sibling or prev_sibling.type == token.COMMA) and (
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | not next_sibling or next_sibling.type == token.COMMA
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | ):
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | return 0
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 |
0044 0017 0029 0005 0009 0002 0004 10 11 007 023 016 029 030 045 0220.81 0974.44 0004.41 | return None
0044 0017 0029 0005 0009 0002 0004 -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | def iter_fexpr_spans(s: str) -> Iterator[Tuple[int, int]]:
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | """
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | Yields spans corresponding to expressions in a given f-string.
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | Spans are half-open ranges (left inclusive, right exclusive).
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | Assumes the input string is a valid f-string, but will not crash if the input
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | string is invalid.
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | """
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | stack: List[int] = [] # our curly paren stack
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | i = 0
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | while i < len(s):
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | if s[i] == "{":
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | # if we're in a string part of the f-string, ignore escaped curly braces
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | if not stack and i + 1 < len(s) and s[i + 1] == "{":
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | i += 2
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | continue
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | stack.append(i)
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | i += 1
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | continue
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 |
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | if s[i] == "}":
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | if not stack:
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | i += 1
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | continue
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | j = stack.pop()
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | # we've made it back out of the expression! yield the span
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | if not stack:
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | yield (j, i + 1)
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | i += 1
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | continue
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 |
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | # if we're in an expression part of the f-string, fast-forward through strings
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | # note that backslashes are not legal in the expression portion of f-strings
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | if stack:
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | delim = None
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | if s[i : i + 3] in ("'''", '"""'):
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | delim = s[i : i + 3]
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | elif s[i] in ("'", '"'):
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | delim = s[i]
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | if delim:
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | i += len(delim)
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | while i < len(s) and s[i : i + len(delim)] != delim:
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | i += 1
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | i += len(delim)
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | continue
0045 0036 0033 0005 0006 0002 0004 -- 15 007 028 028 054 035 082 0420.60 2839.06 0006.75 | i += 1
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0002 0002 0002 0000 0000 0000 0000 -- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def fstring_contains_expr(s: str) -> bool:
0002 0002 0002 0000 0000 0000 0000 -- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return any(iter_fexpr_spans(s))
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def _toggle_fexpr_quotes(fstring: str, old_quote: str) -> str:
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Toggles quotes used in f-string expressions that are `old_quote`.
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | f-string expressions can't contain backslashes, so we need to toggle the
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | quotes if the f-string itself will end up using the same quote. We can
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | simply toggle without escaping because, quotes can't be reused in f-string
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | expressions. They will fail to parse.
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | NOTE: If PEP 701 is accepted, above statement will no longer be true.
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Though if quotes can be reused, we can simply reuse them without updates or
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | escaping, once Black figures out how to parse the new grammar.
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | new_quote = "'" if old_quote == '"' else '"'
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | parts = []
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | previous_index = 0
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | for start, end in iter_fexpr_spans(fstring):
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | parts.append(fstring[previous_index:start])
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | parts.append(fstring[start:end].replace(old_quote, new_quote))
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | previous_index = end
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | parts.append(fstring[previous_index:])
0022 0014 0010 0000 0010 0002 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return "".join(parts)
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | class StringSplitter(BaseStringSplitter, CustomSplitMapMixin):
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | StringTransformer that splits "atom" strings (i.e. strings which exist on
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | lines by themselves).
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | Requirements:
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | * The line consists ONLY of a single string (possibly prefixed by a
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | string operator [e.g. '+' or '==']), MAYBE a string trailer, and MAYBE
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | a trailing comma.
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | AND
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | * All of the requirements listed in BaseStringSplitter's docstring.
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | Transformations:
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | The string mentioned in the 'Requirements' section is split into as
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | many substrings as necessary to adhere to the configured line length.
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | In the final set of substrings, no substring should be smaller than
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | MIN_SUBSTR_SIZE characters.
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | The string will ONLY be split on spaces (i.e. each new substring should
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | start with a space). Note that the string will NOT be split on a space
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | which is escaped with a backslash.
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | If the string is an f-string, it will NOT be split in the middle of an
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | f-expression (e.g. in f"FooBar: {foo() if x else bar()}", {foo() if x
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | else bar()} is an f-expression).
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | If the string that is being split has an associated set of custom split
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | records and those custom splits will NOT result in any line going over
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | the configured line length, those custom splits are used. Otherwise the
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | string is split as late as possible (from left-to-right) while still
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | adhering to the transformation rules listed above.
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | Collaborations:
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | StringSplitter relies on StringMerger to construct the appropriate
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | CustomSplit objects and add them to the custom split map.
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | MIN_SUBSTR_SIZE: Final = 6
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | def do_splitter_match(self, line: Line) -> TMatchResult:
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | LL = line.leaves
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | if self._prefer_paren_wrap_match(LL) is not None:
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | return TErr("Line needs to be wrapped in parens first.")
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | is_valid_index = is_valid_index_factory(LL)
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | idx = 0
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | # The first two leaves MAY be the 'not in' keywords...
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | if (
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | is_valid_index(idx)
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | and is_valid_index(idx + 1)
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | and [LL[idx].type, LL[idx + 1].type] == [token.NAME, token.NAME]
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | and str(LL[idx]) + str(LL[idx + 1]) == "not in"
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | ):
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | idx += 2
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | # Else the first leaf MAY be a string operator symbol or the 'in' keyword...
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | elif is_valid_index(idx) and (
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | LL[idx].type in self.STRING_OPERATORS
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | or LL[idx].type == token.NAME
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | and str(LL[idx]) == "in"
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | ):
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | idx += 1
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | # The next/first leaf MAY be an empty LPAR...
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | if is_valid_index(idx) and is_empty_lpar(LL[idx]):
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | idx += 1
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | # The next/first leaf MUST be a string...
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | if not is_valid_index(idx) or LL[idx].type != token.STRING:
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | return TErr("Line does not start with a string.")
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | string_idx = idx
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | # Skip the string trailer, if one exists.
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | string_parser = StringParser()
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | idx = string_parser.parse(LL, string_idx)
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | # That string MAY be followed by an empty RPAR...
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | if is_valid_index(idx) and is_empty_rpar(LL[idx]):
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | idx += 1
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | # That string / empty RPAR leaf MAY be followed by a comma...
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | if is_valid_index(idx) and LL[idx].type == token.COMMA:
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | idx += 1
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | # But no more leaves are allowed...
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | if is_valid_index(idx):
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | return TErr("This line does not end with a string.")
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 |
0053 0024 0033 0008 0000 0012 0008 08 19 008 037 026 053 045 079 0433.86 2485.88 0005.73 | return Ok([string_idx])
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | def do_transform(
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | self, line: Line, string_indices: List[int]
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | ) -> Iterator[TResult[Line]]:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | LL = line.leaves
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | assert len(string_indices) == 1, (
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | f"{self.__class__.__name__} should only find one match at a time, found"
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | f" {len(string_indices)}"
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | )
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | string_idx = string_indices[0]
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | QUOTE = LL[string_idx].value[-1]
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | is_valid_index = is_valid_index_factory(LL)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | insert_str_child = insert_str_child_factory(LL[string_idx])
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | prefix = get_string_prefix(LL[string_idx].value).lower()
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # We MAY choose to drop the 'f' prefix from substrings that don't
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # contain any f-expressions, but ONLY if the original f-string
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # contains at least one f-expression. Otherwise, we will alter the AST
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # of the program.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | drop_pointless_f_prefix = ("f" in prefix) and fstring_contains_expr(
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | LL[string_idx].value
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | )
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | first_string_line = True
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | string_op_leaves = self._get_string_operator_leaves(LL)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | string_op_leaves_length = (
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | sum(len(str(prefix_leaf)) for prefix_leaf in string_op_leaves) + 1
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if string_op_leaves
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | else 0
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | )
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | def maybe_append_string_operators(new_line: Line) -> None:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | """
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | Side Effects:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | If @line starts with a string operator and this is the first
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | line we are constructing, this function appends the string
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | operator to @new_line and replaces the old string operator leaf
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | in the node structure. Otherwise this function does nothing.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | """
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | maybe_prefix_leaves = string_op_leaves if first_string_line else []
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | for i, prefix_leaf in enumerate(maybe_prefix_leaves):
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | replace_child(LL[i], prefix_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | new_line.append(prefix_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | ends_with_comma = (
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | is_valid_index(string_idx + 1) and LL[string_idx + 1].type == token.COMMA
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | )
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | def max_last_string_column() -> int:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | """
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | Returns:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | The max allowed width of the string value used for the last
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | line we will construct. Note that this value means the width
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | rather than the number of characters (e.g., many East Asian
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | characters expand to two columns).
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | """
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | result = self.line_length
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | result -= line.depth * 4
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | result -= 1 if ends_with_comma else 0
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | result -= string_op_leaves_length
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | return result
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # --- Calculate Max Break Width (for string value)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # We start with the line length limit
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | max_break_width = self.line_length
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # The last index of a string of length N is N-1.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | max_break_width -= 1
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Leading whitespace is not present in the string value (e.g. Leaf.value).
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | max_break_width -= line.depth * 4
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if max_break_width < 0:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | yield TErr(
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | f"Unable to split {LL[string_idx].value} at such high of a line depth:"
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | f" {line.depth}"
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | )
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | return
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Check if StringMerger registered any custom splits.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | custom_splits = self.pop_custom_splits(LL[string_idx].value)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # We use them ONLY if none of them would produce lines that exceed the
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # line limit.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | use_custom_breakpoints = bool(
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | custom_splits
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | and all(csplit.break_idx <= max_break_width for csplit in custom_splits)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | )
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Temporary storage for the remaining chunk of the string line that
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # can't fit onto the line currently being constructed.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | rest_value = LL[string_idx].value
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | def more_splits_should_be_made() -> bool:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | """
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | Returns:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | True iff `rest_value` (the remaining string value from the last
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | split), should be split again.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | """
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if use_custom_breakpoints:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | return len(custom_splits) > 1
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | else:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | return str_width(rest_value) > max_last_string_column()
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | string_line_results: List[Ok[Line]] = []
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | while more_splits_should_be_made():
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if use_custom_breakpoints:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Custom User Split (manual)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | csplit = custom_splits.pop(0)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | break_idx = csplit.break_idx
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | else:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Algorithmic Split (automatic)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | max_bidx = (
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | count_chars_in_width(rest_value, max_break_width)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | - string_op_leaves_length
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | )
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | maybe_break_idx = self._get_break_idx(rest_value, max_bidx)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if maybe_break_idx is None:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # If we are unable to algorithmically determine a good split
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # and this string has custom splits registered to it, we
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # fall back to using them--which means we have to start
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # over from the beginning.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if custom_splits:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | rest_value = LL[string_idx].value
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | string_line_results = []
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | first_string_line = True
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | use_custom_breakpoints = True
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | continue
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Otherwise, we stop splitting here.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | break
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | break_idx = maybe_break_idx
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # --- Construct `next_value`
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | next_value = rest_value[:break_idx] + QUOTE
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # HACK: The following 'if' statement is a hack to fix the custom
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # breakpoint index in the case of either: (a) substrings that were
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # f-strings but will have the 'f' prefix removed OR (b) substrings
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # that were not f-strings but will now become f-strings because of
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # redundant use of the 'f' prefix (i.e. none of the substrings
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # contain f-expressions but one or more of them had the 'f' prefix
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # anyway; in which case, we will prepend 'f' to _all_ substrings).
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | #
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # There is probably a better way to accomplish what is being done
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # here...
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | #
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # If this substring is an f-string, we _could_ remove the 'f'
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # prefix, and the current custom split did NOT originally use a
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # prefix...
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if (
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | use_custom_breakpoints
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | and not csplit.has_prefix
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | and (
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # `next_value == prefix + QUOTE` happens when the custom
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # split is an empty string.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | next_value == prefix + QUOTE
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | or next_value != self._normalize_f_string(next_value, prefix)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | )
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | ):
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Then `csplit.break_idx` will be off by one after removing
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # the 'f' prefix.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | break_idx += 1
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | next_value = rest_value[:break_idx] + QUOTE
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if drop_pointless_f_prefix:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | next_value = self._normalize_f_string(next_value, prefix)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # --- Construct `next_leaf`
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | next_leaf = Leaf(token.STRING, next_value)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | insert_str_child(next_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | self._maybe_normalize_string_quotes(next_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # --- Construct `next_line`
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | next_line = line.clone()
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | maybe_append_string_operators(next_line)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | next_line.append(next_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | string_line_results.append(Ok(next_line))
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | rest_value = prefix + QUOTE + rest_value[break_idx:]
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | first_string_line = False
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | yield from string_line_results
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if drop_pointless_f_prefix:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | rest_value = self._normalize_f_string(rest_value, prefix)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | rest_leaf = Leaf(token.STRING, rest_value)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | insert_str_child(rest_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # NOTE: I could not find a test case that verifies that the following
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # line is actually necessary, but it seems to be. Otherwise we risk
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # not normalizing the last substring, right?
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | self._maybe_normalize_string_quotes(rest_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | last_line = line.clone()
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | maybe_append_string_operators(last_line)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # If there are any leaves to the right of the target string...
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if is_valid_index(string_idx + 1):
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # We use `temp_value` here to determine how long the last line
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # would be if we were to append all the leaves to the right of the
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # target string to the last string line.
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | temp_value = rest_value
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | for leaf in LL[string_idx + 1 :]:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | temp_value += str(leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if leaf.type == token.LPAR:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | break
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Try to fit them all on the same line with the last substring...
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | if (
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | str_width(temp_value) <= max_last_string_column()
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | or LL[string_idx + 1].type == token.COMMA
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | ):
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | last_line.append(rest_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | append_leaves(last_line, line, LL[string_idx + 1 :])
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | yield Ok(last_line)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Otherwise, place the last substring on one line and everything
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # else on a line below that...
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | else:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | last_line.append(rest_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | yield Ok(last_line)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 |
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | non_string_line = line.clone()
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | append_leaves(non_string_line, line, LL[string_idx + 1 :])
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | yield Ok(non_string_line)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | # Else the target string was the last leaf...
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | else:
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | last_line.append(rest_leaf)
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | last_line.comments = line.comments.copy()
0231 0107 0132 0052 0019 0030 0050 08 23 014 055 044 087 069 131 0800.22 8860.58 0011.07 | yield Ok(last_line)
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | def _iter_nameescape_slices(self, string: str) -> Iterator[Tuple[Index, Index]]:
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | """
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | Yields:
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | All ranges of @string which, if @string were to be split there,
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | would result in the splitting of an \\N{...} expression (which is NOT
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | allowed).
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | """
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | # True - the previous backslash was unescaped
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | # False - the previous backslash was escaped *or* there was no backslash
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | previous_was_unescaped_backslash = False
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | it = iter(enumerate(string))
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | for idx, c in it:
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | if c == "\\":
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | previous_was_unescaped_backslash = not previous_was_unescaped_backslash
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | continue
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | if not previous_was_unescaped_backslash or c != "N":
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | previous_was_unescaped_backslash = False
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | continue
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | previous_was_unescaped_backslash = False
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 |
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | begin = idx - 1 # the position of backslash before \N{...}
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | for idx, c in it:
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | if c == "}":
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | end = idx
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | break
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | else:
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | # malformed nameescape expression?
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | # should have been detected by AST parsing earlier...
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | raise RuntimeError(f"{self.__class__.__name__} LOGIC ERROR!")
0030 0020 0019 0005 0006 0001 0004 08 08 005 009 007 012 014 019 0072.34 0241.13 0003.33 | yield begin, end
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def _iter_fexpr_slices(self, string: str) -> Iterator[Tuple[Index, Index]]:
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Yields:
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | All ranges of @string which, if @string were to be split there,
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | would result in the splitting of an f-expression (which is NOT
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | allowed).
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if "f" not in get_string_prefix(string).lower():
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return
0010 0005 0004 0000 0006 0000 0000 08 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | yield from iter_fexpr_spans(string)
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def _get_illegal_split_indices(self, string: str) -> Set[Index]:
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | illegal_indices: Set[Index] = set()
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | iterators = [
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self._iter_fexpr_slices(string),
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self._iter_nameescape_slices(string),
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | ]
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | for it in iterators:
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | for begin, end in it:
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | illegal_indices.update(range(begin, end + 1))
0010 0008 0010 0000 0000 0000 0000 08 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return illegal_indices
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | def _get_break_idx(self, string: str, max_break_idx: int) -> Optional[int]:
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | """
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | This method contains the algorithm that StringSplitter uses to
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | determine which character to split each string at.
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | Args:
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | @string: The substring that we are attempting to split.
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | @max_break_idx: The ideal break index. We will return this value if it
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | meets all the necessary conditions. In the likely event that it
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | doesn't we will try to find the closest index BELOW @max_break_idx
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | that does. If that fails, we will expand our search by also
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | considering all valid indices ABOVE @max_break_idx.
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | Pre-Conditions:
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | * assert_is_leaf_string(@string)
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | * 0 <= @max_break_idx < len(@string)
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | Returns:
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | break_idx, if an index is able to be found that meets all of the
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | conditions listed in the 'Transformations' section of this classes'
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | docstring.
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | OR
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | None, otherwise.
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | """
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | is_valid_index = is_valid_index_factory(string)
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | assert is_valid_index(max_break_idx)
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | assert_is_leaf_string(string)
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | _illegal_split_indices = self._get_illegal_split_indices(string)
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | def breaks_unsplittable_expression(i: Index) -> bool:
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | """
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | Returns:
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | True iff returning @i would result in the splitting of an
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | unsplittable expression (which is NOT allowed).
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | """
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | return i in _illegal_split_indices
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | def passes_all_checks(i: Index) -> bool:
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | """
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | Returns:
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | True iff ALL of the conditions listed in the 'Transformations'
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | section of this classes' docstring would be met by returning @i.
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | """
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | is_space = string[i] == " "
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | is_split_safe = is_valid_index(i - 1) and string[i - 1] in SPLIT_SAFE_CHARS
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | is_not_escaped = True
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | j = i - 1
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | while is_valid_index(j) and string[j] == "\\":
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | is_not_escaped = not is_not_escaped
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | j -= 1
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | is_big_enough = (
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | len(string[i:]) >= self.MIN_SUBSTR_SIZE
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | and len(string[:i]) >= self.MIN_SUBSTR_SIZE
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | )
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | return (
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | (is_space or is_split_safe)
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | and is_not_escaped
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | and is_big_enough
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | and not breaks_unsplittable_expression(i)
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | )
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | # First, we check all indices BELOW @max_break_idx.
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | break_idx = max_break_idx
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | while is_valid_index(break_idx - 1) and not passes_all_checks(break_idx):
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | break_idx -= 1
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | if not passes_all_checks(break_idx):
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | # If that fails, we check all indices ABOVE @max_break_idx.
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | #
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | # If we are able to find a valid index here, the next line is going
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | # to be longer than the specified line length, but it's probably
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | # better than doing nothing at all.
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | break_idx = max_break_idx + 1
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | while is_valid_index(break_idx + 1) and not passes_all_checks(break_idx):
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | break_idx += 1
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | if not is_valid_index(break_idx) or not passes_all_checks(break_idx):
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | return None
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 |
0084 0031 0035 0006 0030 0013 0006 08 08 008 041 030 055 049 085 0477.25 2560.86 0005.37 | return break_idx
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0003 0003 0000 0000 0000 0000 08 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def _maybe_normalize_string_quotes(self, leaf: Leaf) -> None:
0003 0003 0003 0000 0000 0000 0000 08 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | if self.normalize_strings:
0003 0003 0003 0000 0000 0000 0000 08 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | leaf.value = normalize_string_quotes(leaf.value)
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | def _normalize_f_string(self, string: str, prefix: str) -> str:
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | """
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | Pre-Conditions:
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | * assert_is_leaf_string(@string)
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 |
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | Returns:
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | * If @string is an f-string that contains no f-expressions, we
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | return a string identical to @string except that the 'f' prefix
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | has been stripped and all double braces (i.e. '{{' or '}}') have
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | been normalized (i.e. turned into '{' or '}').
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | OR
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | * Otherwise, we return @string.
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | """
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | assert_is_leaf_string(string)
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 |
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | if "f" in prefix and not fstring_contains_expr(string):
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | new_prefix = prefix.replace("f", "")
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 |
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | temp = string[len(prefix) :]
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | temp = re.sub(r"\{\{", "{", temp)
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | temp = re.sub(r"\}\}", "}", temp)
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | new_string = temp
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 |
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | return f"{new_prefix}{new_string}"
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | else:
0026 0013 0011 0000 0011 0004 0000 08 03 003 005 003 005 008 008 0024.00 0036.00 0001.50 | return string
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 | def _get_string_operator_leaves(self, leaves: Iterable[Leaf]) -> List[Leaf]:
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 | LL = list(leaves)
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 |
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 | string_op_leaves = []
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 | i = 0
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 | while LL[i].type in self.STRING_OPERATORS + [token.NAME]:
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 | prefix_leaf = Leaf(LL[i].type, str(LL[i]).strip())
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 | string_op_leaves.append(prefix_leaf)
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 | i += 1
0010 0009 0009 0000 0000 0001 0000 08 02 002 006 003 006 008 009 0027.00 0027.00 0001.00 | return string_op_leaves
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | class StringParenWrapper(BaseStringSplitter, CustomSplitMapMixin):
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | StringTransformer that wraps strings in parens and then splits at the LPAR.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | Requirements:
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | All of the requirements listed in BaseStringSplitter's docstring in
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | addition to the requirements listed below:
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | * The line is a return/yield statement, which returns/yields a string.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | OR
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | * The line is part of a ternary expression (e.g. `x = y if cond else
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | z`) such that the line starts with `else <string>`, where <string> is
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | some string.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | OR
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | * The line is an assert statement, which ends with a string.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | OR
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | * The line is an assignment statement (e.g. `x = <string>` or `x +=
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | <string>`) such that the variable is being assigned the value of some
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | string.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | OR
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | * The line is a dictionary key assignment where some valid key is being
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | assigned the value of some string.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | OR
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | * The line is an lambda expression and the value is a string.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | OR
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | * The line starts with an "atom" string that prefers to be wrapped in
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | parens. It's preferred to be wrapped when it's is an immediate child of
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | a list/set/tuple literal, AND the string is surrounded by commas (or is
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | the first/last child).
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | Transformations:
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | The chosen string is wrapped in parentheses and then split at the LPAR.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | We then have one line which ends with an LPAR and another line that
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | starts with the chosen string. The latter line is then split again at
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | the RPAR. This results in the RPAR (and possibly a trailing comma)
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | being placed on its own line.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | NOTE: If any leaves exist to the right of the chosen string (except
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | for a trailing comma, which would be placed after the RPAR), those
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | leaves are placed inside the parentheses. In effect, the chosen
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | string is not necessarily being "wrapped" by parentheses. We can,
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | however, count on the LPAR being placed directly before the chosen
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | string.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | In other words, StringParenWrapper creates "atom" strings. These
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | can then be split again by StringSplitter, if necessary.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | Collaborations:
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | In the event that a string line split by StringParenWrapper is
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | changed such that it no longer needs to be given its own line,
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | StringParenWrapper relies on StringParenStripper to clean up the
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | parentheses it created.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | For "atom" strings that prefers to be wrapped in parens, it requires
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | StringSplitter to hold the split until the string is wrapped in parens.
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | def do_splitter_match(self, line: Line) -> TMatchResult:
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | LL = line.leaves
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 |
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | if line.leaves[-1].type in OPENING_BRACKETS:
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | return TErr(
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | "Cannot wrap parens around a line that ends in an opening bracket."
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | )
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 |
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | string_idx = (
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | self._return_match(LL)
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | or self._else_match(LL)
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | or self._assert_match(LL)
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | or self._assign_match(LL)
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | or self._dict_or_lambda_match(LL)
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | or self._prefer_paren_wrap_match(LL)
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | )
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 |
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | if string_idx is not None:
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | string_value = line.leaves[string_idx].value
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | # If the string has neither spaces nor East Asian stops...
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | if not any(
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | char == " " or char in SPLIT_SAFE_CHARS for char in string_value
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | ):
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | # And will still violate the line length limit when split...
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | max_string_width = self.line_length - ((line.depth + 1) * 4)
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | if str_width(string_value) > max_string_width:
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | # And has no associated custom splits...
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | if not self.has_custom_splits(string_value):
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | # Then we should NOT put this string on its own line.
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | return TErr(
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | "We do not wrap long strings in parentheses when the"
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | " resultant line would still be over the specified line"
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | " length and can't be split further by StringSplitter."
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | )
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | return Ok([string_idx])
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 |
0037 0014 0029 0004 0000 0004 0004 12 13 010 025 013 027 035 040 0205.17 1107.93 0005.40 | return TErr("This line does not contain any non-atomic strings.")
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | def _return_match(LL: List[Leaf]) -> Optional[int]:
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | """
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | Returns:
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | string_idx such that @LL[string_idx] is equal to our target (i.e.
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | matched) string, if this line matches the return/yield statement
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | requirements listed in the 'Requirements' section of this classes'
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | docstring.
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | OR
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | None, otherwise.
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | """
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | # If this line is a part of a return/yield statement and the first leaf
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | # contains either the "return" or "yield" keywords...
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | if parent_type(LL[0]) in [syms.return_stmt, syms.yield_expr] and LL[
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | 0
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | ].value in ["return", "yield"]:
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | is_valid_index = is_valid_index_factory(LL)
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 |
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | idx = 2 if is_valid_index(1) and is_empty_par(LL[1]) else 1
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | # The next visible leaf MUST contain a string...
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | if is_valid_index(idx) and LL[idx].type == token.STRING:
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | return idx
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 |
0024 0009 0010 0003 0009 0002 0003 12 07 003 012 006 012 015 018 0070.32 0105.49 0001.50 | return None
0024 0009 0010 0003 0009 0002 0003 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | def _else_match(LL: List[Leaf]) -> Optional[int]:
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | """
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | Returns:
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | string_idx such that @LL[string_idx] is equal to our target (i.e.
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | matched) string, if this line matches the ternary expression
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | requirements listed in the 'Requirements' section of this classes'
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | docstring.
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | OR
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | None, otherwise.
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | """
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | # If this line is a part of a ternary expression and the first leaf
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | # contains the "else" keyword...
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | if (
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | parent_type(LL[0]) == syms.test
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | and LL[0].type == token.NAME
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | and LL[0].value == "else"
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | ):
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | is_valid_index = is_valid_index_factory(LL)
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 |
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | idx = 2 if is_valid_index(1) and is_empty_par(LL[1]) else 1
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | # The next visible leaf MUST contain a string...
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | if is_valid_index(idx) and LL[idx].type == token.STRING:
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | return idx
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 |
0026 0009 0012 0003 0009 0002 0003 12 08 002 014 007 015 016 022 0088.00 0094.29 0001.07 | return None
0026 0009 0012 0003 0009 0002 0003 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | def _assert_match(LL: List[Leaf]) -> Optional[int]:
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | """
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | Returns:
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | string_idx such that @LL[string_idx] is equal to our target (i.e.
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | matched) string, if this line matches the assert statement
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | requirements listed in the 'Requirements' section of this classes'
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | docstring.
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | OR
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | None, otherwise.
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | """
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | # If this line is a part of an assert statement and the first leaf
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | # contains the "assert" keyword...
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | if parent_type(LL[0]) == syms.assert_stmt and LL[0].value == "assert":
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | is_valid_index = is_valid_index_factory(LL)
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 |
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | for i, leaf in enumerate(LL):
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | # We MUST find a comma...
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | if leaf.type == token.COMMA:
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | idx = i + 2 if is_empty_par(LL[i + 1]) else i + 1
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 |
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | # That comma MUST be followed by a string...
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | if is_valid_index(idx) and LL[idx].type == token.STRING:
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | string_idx = idx
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 |
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | # Skip the string trailer, if one exists.
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | string_parser = StringParser()
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | idx = string_parser.parse(LL, string_idx)
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 |
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | # But no more leaves are allowed...
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | if not is_valid_index(idx):
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | return string_idx
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 |
0034 0015 0014 0006 0009 0005 0006 12 09 004 015 010 019 019 029 0123.19 0312.08 0002.53 | return None
0034 0015 0014 0006 0009 0005 0006 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | def _assign_match(LL: List[Leaf]) -> Optional[int]:
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | """
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | Returns:
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | string_idx such that @LL[string_idx] is equal to our target (i.e.
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | matched) string, if this line matches the assignment statement
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | requirements listed in the 'Requirements' section of this classes'
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | docstring.
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | OR
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | None, otherwise.
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | """
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | # If this line is a part of an expression statement or is a function
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | # argument AND the first leaf contains a variable name...
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | if (
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | parent_type(LL[0]) in [syms.expr_stmt, syms.argument, syms.power]
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | and LL[0].type == token.NAME
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | ):
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | is_valid_index = is_valid_index_factory(LL)
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 |
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | for i, leaf in enumerate(LL):
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | # We MUST find either an '=' or '+=' symbol...
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | if leaf.type in [token.EQUAL, token.PLUSEQUAL]:
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | idx = i + 2 if is_empty_par(LL[i + 1]) else i + 1
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 |
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | # That symbol MUST be followed by a string...
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | if is_valid_index(idx) and LL[idx].type == token.STRING:
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | string_idx = idx
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 |
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | # Skip the string trailer, if one exists.
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | string_parser = StringParser()
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | idx = string_parser.parse(LL, string_idx)
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 |
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | # The next leaf MAY be a comma iff this line is a part
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | # of a function argument...
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | if (
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | parent_type(LL[0]) == syms.argument
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | and is_valid_index(idx)
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | and LL[idx].type == token.COMMA
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | ):
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | idx += 1
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 |
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | # But no more leaves are allowed...
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | if not is_valid_index(idx):
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | return string_idx
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 |
0046 0017 0023 0008 0009 0006 0008 12 12 005 021 014 028 026 042 0197.42 0658.06 0003.33 | return None
0046 0017 0023 0008 0009 0006 0008 12 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 12 -- --- --- --- --- --- --- ------- ------- ------- | @staticmethod
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | def _dict_or_lambda_match(LL: List[Leaf]) -> Optional[int]:
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | """
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | Returns:
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | string_idx such that @LL[string_idx] is equal to our target (i.e.
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | matched) string, if this line matches the dictionary key assignment
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | statement or lambda expression requirements listed in the
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | 'Requirements' section of this classes' docstring.
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | OR
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | None, otherwise.
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | """
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | # If this line is a part of a dictionary key assignment or lambda expression...
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | parent_types = [parent_type(LL[0]), parent_type(LL[0].parent)]
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | if syms.dictsetmaker in parent_types or syms.lambdef in parent_types:
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | is_valid_index = is_valid_index_factory(LL)
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 |
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | for i, leaf in enumerate(LL):
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | # We MUST find a colon, it can either be dict's or lambda's colon...
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | if leaf.type == token.COLON and i < len(LL) - 1:
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | idx = i + 2 if is_empty_par(LL[i + 1]) else i + 1
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 |
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | # That colon MUST be followed by a string...
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | if is_valid_index(idx) and LL[idx].type == token.STRING:
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | string_idx = idx
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 |
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | # Skip the string trailer, if one exists.
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | string_parser = StringParser()
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | idx = string_parser.parse(LL, string_idx)
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 |
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | # That string MAY be followed by a comma...
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | if is_valid_index(idx) and LL[idx].type == token.COMMA:
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | idx += 1
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 |
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | # But no more leaves are allowed...
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | if not is_valid_index(idx):
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | return string_idx
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 |
0038 0018 0017 0006 0009 0006 0006 12 12 008 022 016 031 030 047 0230.62 1299.88 0005.64 | return None
0038 0018 0017 0006 0009 0006 0006 12 -- --- --- --- --- --- --- ------- ------- ------- |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | def do_transform(
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | self, line: Line, string_indices: List[int]
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | ) -> Iterator[TResult[Line]]:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | LL = line.leaves
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | assert len(string_indices) == 1, (
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | f"{self.__class__.__name__} should only find one match at a time, found"
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | f" {len(string_indices)}"
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | )
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | string_idx = string_indices[0]
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | is_valid_index = is_valid_index_factory(LL)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | insert_str_child = insert_str_child_factory(LL[string_idx])
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | comma_idx = -1
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | ends_with_comma = False
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if LL[comma_idx].type == token.COMMA:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | ends_with_comma = True
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | leaves_to_steal_comments_from = [LL[string_idx]]
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if ends_with_comma:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | leaves_to_steal_comments_from.append(LL[comma_idx])
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # --- First Line
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | first_line = line.clone()
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | left_leaves = LL[:string_idx]
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # We have to remember to account for (possibly invisible) LPAR and RPAR
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # leaves that already wrapped the target string. If these leaves do
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # exist, we will replace them with our own LPAR and RPAR leaves.
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | old_parens_exist = False
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if left_leaves and left_leaves[-1].type == token.LPAR:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | old_parens_exist = True
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | leaves_to_steal_comments_from.append(left_leaves[-1])
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | left_leaves.pop()
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | append_leaves(first_line, line, left_leaves)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | lpar_leaf = Leaf(token.LPAR, "(")
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if old_parens_exist:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | replace_child(LL[string_idx - 1], lpar_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | else:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | insert_str_child(lpar_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | first_line.append(lpar_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # We throw inline comments that were originally to the right of the
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # target string to the top line. They will now be shown to the right of
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # the LPAR.
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | for leaf in leaves_to_steal_comments_from:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | for comment_leaf in line.comments_after(leaf):
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | first_line.append(comment_leaf, preformatted=True)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | yield Ok(first_line)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # --- Middle (String) Line
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # We only need to yield one (possibly too long) string line, since the
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # `StringSplitter` will break it down further if necessary.
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | string_value = LL[string_idx].value
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | string_line = Line(
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | mode=line.mode,
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | depth=line.depth + 1,
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | inside_brackets=True,
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | should_split_rhs=line.should_split_rhs,
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | magic_trailing_comma=line.magic_trailing_comma,
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | )
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | string_leaf = Leaf(token.STRING, string_value)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | insert_str_child(string_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | string_line.append(string_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | old_rpar_leaf = None
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if is_valid_index(string_idx + 1):
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | right_leaves = LL[string_idx + 1 :]
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if ends_with_comma:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | right_leaves.pop()
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if old_parens_exist:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | assert right_leaves and right_leaves[-1].type == token.RPAR, (
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | "Apparently, old parentheses do NOT exist?!"
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | f" (left_leaves={left_leaves}, right_leaves={right_leaves})"
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | )
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | old_rpar_leaf = right_leaves.pop()
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | elif right_leaves and right_leaves[-1].type == token.RPAR:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # Special case for lambda expressions as dict's value, e.g.:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # my_dict = {
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # "key": lambda x: f"formatted: {x},
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # }
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # After wrapping the dict's value with parentheses, the string is
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # followed by a RPAR but its opening bracket is lambda's, not
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # the string's:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # "key": (lambda x: f"formatted: {x}),
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | opening_bracket = right_leaves[-1].opening_bracket
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if opening_bracket is not None and opening_bracket in left_leaves:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | index = left_leaves.index(opening_bracket)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if (
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | 0 < index < len(left_leaves) - 1
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | and left_leaves[index - 1].type == token.COLON
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | and left_leaves[index + 1].value == "lambda"
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | ):
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | right_leaves.pop()
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | append_leaves(string_line, line, right_leaves)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | yield Ok(string_line)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # --- Last Line
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | last_line = line.clone()
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | last_line.bracket_tracker = first_line.bracket_tracker
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | new_rpar_leaf = Leaf(token.RPAR, ")")
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if old_rpar_leaf is not None:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | replace_child(old_rpar_leaf, new_rpar_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | else:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | insert_str_child(new_rpar_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | last_line.append(new_rpar_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # If the target string ended with a comma, we place this comma to the
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | # right of the RPAR on the last line.
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | if ends_with_comma:
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | comma_leaf = Leaf(token.COMMA, ",")
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | replace_child(LL[comma_idx], comma_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | last_line.append(comma_leaf)
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 |
0122 0067 0083 0021 0000 0018 0021 12 20 008 028 030 054 036 084 0434.27 3350.11 0007.71 | yield Ok(last_line)
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | class StringParser:
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | A state machine that aids in parsing a string's "trailer", which can be
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | either non-existent, an old-style formatting sequence (e.g. `% varX` or `%
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (varX, varY)`), or a method-call / attribute access (e.g. `.format(varX,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | varY)`).
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | NOTE: A new StringParser object MUST be instantiated for each string
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | trailer we need to parse.
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | Examples:
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | We shall assume that `line` equals the `Line` object that corresponds
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | to the following line of python code:
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | x = "Some {}.".format("String") + some_other_string
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | Furthermore, we will assume that `string_idx` is some index such that:
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | assert line.leaves[string_idx].value == "Some {}."
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | The following code snippet then holds:
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | string_parser = StringParser()
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | idx = string_parser.parse(line.leaves, string_idx)
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | assert line.leaves[idx].type == token.PLUS
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | ```
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | DEFAULT_TOKEN: Final = 20210605
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # String Parser States
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | START: Final = 1
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | DOT: Final = 2
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | NAME: Final = 3
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | PERCENT: Final = 4
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | SINGLE_FMT_ARG: Final = 5
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | LPAR: Final = 6
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | RPAR: Final = 7
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | DONE: Final = 8
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # Lookup Table for Next State
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | _goto: Final[Dict[Tuple[ParserState, NodeType], ParserState]] = {
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # A string trailer may start with '.' OR '%'.
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (START, token.DOT): DOT,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (START, token.PERCENT): PERCENT,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (START, DEFAULT_TOKEN): DONE,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # A '.' MUST be followed by an attribute or method name.
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (DOT, token.NAME): NAME,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # A method name MUST be followed by an '(', whereas an attribute name
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # is the last symbol in the string trailer.
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (NAME, token.LPAR): LPAR,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (NAME, DEFAULT_TOKEN): DONE,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # A '%' symbol can be followed by an '(' or a single argument (e.g. a
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # string or variable name).
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (PERCENT, token.LPAR): LPAR,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (PERCENT, DEFAULT_TOKEN): SINGLE_FMT_ARG,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # If a '%' symbol is followed by a single argument, that argument is
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # the last leaf in the string trailer.
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (SINGLE_FMT_ARG, DEFAULT_TOKEN): DONE,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # If present, a ')' symbol is the last symbol in a string trailer.
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # (NOTE: LPARS and nested RPARS are not included in this lookup table,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # since they are treated as a special case by the parsing logic in this
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | # classes' implementation.)
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | (RPAR, DEFAULT_TOKEN): DONE,
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- | }
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0003 0003 0000 0000 0000 0000 05 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def __init__(self) -> None:
0003 0003 0003 0000 0000 0000 0000 05 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self._state = self.START
0003 0003 0003 0000 0000 0000 0000 05 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self._unmatched_lpars = 0
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | def parse(self, leaves: List[Leaf], string_idx: int) -> int:
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | """
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | Pre-conditions:
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | * @leaves[@string_idx].type == token.STRING
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 |
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | Returns:
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | The index directly after the last leaf which is a part of the string
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | trailer, if a "trailer" exists.
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | OR
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | @string_idx + 1, if no string "trailer" exists.
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | """
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | assert leaves[string_idx].type == token.STRING
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 |
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | idx = string_idx + 1
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | while idx < len(leaves) and self._next_state(leaves[idx]):
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | idx += 1
0017 0007 0006 0000 0009 0002 0000 05 03 004 008 005 010 012 015 0053.77 0134.44 0002.50 | return idx
---- ---- ---- ---- ---- ---- ---- 05 -- --- --- --- --- --- --- ------- ------- ------- |
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | def _next_state(self, leaf: Leaf) -> bool:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | """
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | Pre-conditions:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | * On the first call to this function, @leaf MUST be the leaf that
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | was directly after the string leaf in question (e.g. if our target
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | string is `line.leaves[i]` then the first call to this method must
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | be `line.leaves[i + 1]`).
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | * On the next call to this function, the leaf parameter passed in
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | MUST be the leaf directly following @leaf.
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 |
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | Returns:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | True iff @leaf is a part of the string's trailer.
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | """
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # We ignore empty LPAR or RPAR leaves.
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | if is_empty_par(leaf):
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | return True
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 |
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | next_token = leaf.type
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | if next_token == token.LPAR:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | self._unmatched_lpars += 1
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 |
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | current_state = self._state
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 |
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # The LPAR parser state is a special case. We will return True until we
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # find the matching RPAR token.
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | if current_state == self.LPAR:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | if next_token == token.RPAR:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | self._unmatched_lpars -= 1
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | if self._unmatched_lpars == 0:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | self._state = self.RPAR
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # Otherwise, we use a lookup table to determine the next state.
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | else:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # If the lookup table matches the current state to the next
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # token, we use the lookup table.
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | if (current_state, next_token) in self._goto:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | self._state = self._goto[current_state, next_token]
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | else:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # Otherwise, we check if a the current state was assigned a
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # default.
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | if (current_state, self.DEFAULT_TOKEN) in self._goto:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | self._state = self._goto[current_state, self.DEFAULT_TOKEN]
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # If no default has been assigned, then this parser has a logic
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | # error.
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | else:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | raise RuntimeError(f"{self.__class__.__name__} LOGIC ERROR!")
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 |
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | if self._state == self.DONE:
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | return False
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 |
0050 0024 0023 0010 0011 0006 0010 05 09 004 012 009 018 016 027 0108.00 0324.00 0003.00 | return True
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | def insert_str_child_factory(string_leaf: Leaf) -> Callable[[LN], None]:
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | """
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Factory for a convenience function that is used to orphan @string_leaf
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | and then insert multiple new leaves into the same part of the node
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | structure that @string_leaf had originally occupied.
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Examples:
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Let `string_leaf = Leaf(token.STRING, '"foo"')` and `N =
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | string_leaf.parent`. Assume the node `N` has the following
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | original structure:
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Node(
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | expr_stmt, [
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Leaf(NAME, 'x'),
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Leaf(EQUAL, '='),
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Leaf(STRING, '"foo"'),
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | ]
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | )
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | We then run the code snippet shown below.
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | ```
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | insert_str_child = insert_str_child_factory(string_leaf)
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | lpar = Leaf(token.LPAR, '(')
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | insert_str_child(lpar)
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | bar = Leaf(token.STRING, '"bar"')
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | insert_str_child(bar)
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | rpar = Leaf(token.RPAR, ')')
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | insert_str_child(rpar)
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | ```
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | After which point, it follows that `string_leaf.parent is None` and
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | the node `N` now has the following structure:
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Node(
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | expr_stmt, [
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Leaf(NAME, 'x'),
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Leaf(EQUAL, '='),
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Leaf(LPAR, '('),
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Leaf(STRING, '"bar"'),
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | Leaf(RPAR, ')'),
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | ]
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | )
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | """
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | string_parent = string_leaf.parent
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | string_child_idx = string_leaf.remove()
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | def insert_str_child(child: LN) -> None:
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | nonlocal string_child_idx
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | assert string_parent is not None
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | assert string_child_idx is not None
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | string_parent.insert_child(string_child_idx, child)
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | string_child_idx += 1
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 |
0059 0011 0010 0000 0037 0012 0000 -- 01 002 004 003 006 006 009 0023.26 0034.90 0001.50 | return insert_str_child
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | def is_valid_index_factory(seq: Sequence[Any]) -> Callable[[int], bool]:
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | """
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | Examples:
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | ```
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | my_list = [1, 2, 3]
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | is_valid_index = is_valid_index_factory(my_list)
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | assert is_valid_index(0)
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | assert is_valid_index(2)
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | assert not is_valid_index(3)
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | assert not is_valid_index(-1)
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | ```
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | """
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | def is_valid_index(idx: int) -> bool:
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | """
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | Returns:
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | True iff @idx is positive AND seq[@idx] does NOT raise an
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | IndexError.
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | """
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | return 0 <= idx < len(seq)
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0025 0006 0004 0000 0016 0005 0000 -- 01 002 003 002 003 005 005 0011.61 0011.61 0001.00 | return is_valid_index