Compare commits
948 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7987951e24 | ||
![]() |
e5e5dad792 | ||
![]() |
24e4cb20ab | ||
![]() |
e7bf7b4619 | ||
![]() |
71e380aedf | ||
![]() |
2630801f95 | ||
![]() |
b0f36f5b42 | ||
![]() |
314f8cf92b | ||
![]() |
d0ff3bd6cb | ||
![]() |
a41dc89f1f | ||
![]() |
950ec38c11 | ||
![]() |
2c135edf37 | ||
![]() |
6144c46c6a | ||
![]() |
dd278cb316 | ||
![]() |
dbb14eac93 | ||
![]() |
5342d2eeda | ||
![]() |
9f38928414 | ||
![]() |
3e9dd25dad | ||
![]() |
bb802cf19a | ||
![]() |
5ae38dd370 | ||
![]() |
45cbe572ee | ||
![]() |
fccd70cff1 | ||
![]() |
00c0d6d91a | ||
![]() |
0580ecbef3 | ||
![]() |
ed64d89faa | ||
![]() |
452d3b68f4 | ||
![]() |
256f3420b1 | ||
![]() |
00cb6d15c5 | ||
![]() |
14e1de805a | ||
![]() |
5f23701708 | ||
![]() |
9c129567e7 | ||
![]() |
c02ca47daa | ||
![]() |
edaf085a18 | ||
![]() |
b844c8a136 | ||
![]() |
d82da0f0e9 | ||
![]() |
8a737e727a | ||
![]() |
d330deea00 | ||
![]() |
3d8129001f | ||
![]() |
459562c71a | ||
![]() |
99dbf3006b | ||
![]() |
c0b92f3888 | ||
![]() |
e58baf15b9 | ||
![]() |
1455ae4731 | ||
![]() |
584d0331c8 | ||
![]() |
6e9654065c | ||
![]() |
8dc912774e | ||
![]() |
40b73f2fb5 | ||
![]() |
e157ba4de5 | ||
![]() |
fdabd424e2 | ||
![]() |
9431e98522 | ||
![]() |
3b00112ac5 | ||
![]() |
0aabac4fe0 | ||
![]() |
ed33205579 | ||
![]() |
6000d37f09 | ||
![]() |
30759ca782 | ||
![]() |
84ac1a947d | ||
![]() |
0db1173bbc | ||
![]() |
3fab5ade71 | ||
![]() |
e54f86bae4 | ||
![]() |
96ca1b6be3 | ||
![]() |
17efac45f9 | ||
![]() |
73f651f02f | ||
![]() |
f6c7c98f34 | ||
![]() |
d670b0439c | ||
![]() |
56896264e4 | ||
![]() |
efd9778873 | ||
![]() |
c472557ba8 | ||
![]() |
53a219056d | ||
![]() |
c98fc0c128 | ||
![]() |
f54f34799b | ||
![]() |
484a669699 | ||
![]() |
fff747d61b | ||
![]() |
9995bffbe4 | ||
![]() |
7452902c77 | ||
![]() |
32ebb93003 | ||
![]() |
1b2427a2b7 | ||
![]() |
a22b1ebbfd | ||
![]() |
b7d0e7212b | ||
![]() |
f1a2f92bba | ||
![]() |
8d9d18c033 | ||
![]() |
bbfdba3a5e | ||
![]() |
8fb2add1f7 | ||
![]() |
2a45cecf29 | ||
![]() |
b4d6d8632d | ||
![]() |
ac018c16ca | ||
![]() |
058da5f81a | ||
![]() |
98a580bbdc | ||
![]() |
f50aba4984 | ||
![]() |
6b27ef53e2 | ||
![]() |
26aeebe9fb | ||
![]() |
9e13708be8 | ||
![]() |
ac28187bf4 | ||
![]() |
823a7b0ff0 | ||
![]() |
699b45aef7 | ||
![]() |
c20423249e | ||
![]() |
5ec91686ff | ||
![]() |
7e3e8f5bd9 | ||
![]() |
b965c2a502 | ||
![]() |
9ccf279a17 | ||
![]() |
14b6e61970 | ||
![]() |
b1c4dd96d7 | ||
![]() |
4b4ae43e8b | ||
![]() |
7fa1faf83a | ||
![]() |
8827accf56 | ||
![]() |
b0da11d370 | ||
![]() |
721dff5493 | ||
![]() |
7e2afc9bfd | ||
![]() |
1ad5263f2f | ||
![]() |
9ff047a957 | ||
![]() |
5e571ccbbe | ||
![]() |
978bc505ac | ||
![]() |
b1f7b9f87d | ||
![]() |
b677a643c5 | ||
![]() |
8447af4d8d | ||
![]() |
9c1fd463e1 | ||
![]() |
b9c63230b4 | ||
![]() |
4af12c499e | ||
![]() |
c827551b23 | ||
![]() |
3be19b306f | ||
![]() |
f71925885c | ||
![]() |
ccfb0db4d5 | ||
![]() |
c801cd60b1 | ||
![]() |
f22b2437d5 | ||
![]() |
75eb55764e | ||
![]() |
f2da85fe7f | ||
![]() |
0ab0b75717 | ||
![]() |
0c033f3eb7 | ||
![]() |
455de7703e | ||
![]() |
dbb956b0d3 | ||
![]() |
3702ba224e | ||
![]() |
e4aaa8a994 | ||
![]() |
ba88fc372e | ||
![]() |
5683242fd4 | ||
![]() |
e7fb048281 | ||
![]() |
3f0f8f1956 | ||
![]() |
2f88085da5 | ||
![]() |
12ce3db077 | ||
![]() |
1354be2525 | ||
![]() |
f4b644b82f | ||
![]() |
551ede2825 | ||
![]() |
944b99aa91 | ||
![]() |
7134754ef4 | ||
![]() |
7669381420 | ||
![]() |
735733b205 | ||
![]() |
9dc9114aef | ||
![]() |
66e2b11571 | ||
![]() |
8fe627072f | ||
![]() |
6b25e7cdab | ||
![]() |
07fe1ca88a | ||
![]() |
3383f531bc | ||
![]() |
c8f1a5542c | ||
![]() |
836acad863 | ||
![]() |
13bd0925eb | ||
![]() |
c9d2635b55 | ||
![]() |
bf1195612c | ||
![]() |
97993f997f | ||
![]() |
f78b15712a | ||
![]() |
8332a75e82 | ||
![]() |
552baf8229 | ||
![]() |
f000936726 | ||
![]() |
7b5a657285 | ||
![]() |
1abcffc818 | ||
![]() |
719e67462c | ||
![]() |
e5510afc06 | ||
![]() |
6af7d11096 | ||
![]() |
f03ee113c9 | ||
![]() |
e4bfedbec2 | ||
![]() |
d0287e1f75 | ||
![]() |
0f18001abf | ||
![]() |
899002399a | ||
![]() |
ea66d40dd7 | ||
![]() |
d1d4fc58d3 | ||
![]() |
6fdf8a4af2 | ||
![]() |
8af439407c | ||
![]() |
35e9776919 | ||
![]() |
23dfc5b2c3 | ||
![]() |
a20100395c | ||
![]() |
dab37a6a11 | ||
![]() |
32230e6f5c | ||
![]() |
7edb50f5a0 | ||
![]() |
3e80de3447 | ||
![]() |
a08b480a2f | ||
![]() |
632f44bd68 | ||
![]() |
9728b8e9b8 | ||
![]() |
2623269dab | ||
![]() |
24c9c01e91 | ||
![]() |
cca3c0fd9f | ||
![]() |
d6e11ca399 | ||
![]() |
8912a33321 | ||
![]() |
2bc5ce8ae1 | ||
![]() |
177e306363 | ||
![]() |
d919746fae | ||
![]() |
0b4364b7e3 | ||
![]() |
e026c93888 | ||
![]() |
79fc1158a9 | ||
![]() |
8bf04549ff | ||
![]() |
1607e9ab20 | ||
![]() |
ed770ba4dd | ||
![]() |
659c29a41c | ||
![]() |
0e6e46b9eb | ||
![]() |
4f47cac192 | ||
![]() |
bccec8adfb | ||
![]() |
7d789469ed | ||
![]() |
17f7f297ef | ||
![]() |
f7d552d9b7 | ||
![]() |
a5196e6f1f | ||
![]() |
59b9d858a3 | ||
![]() |
8fe602b1fa | ||
![]() |
6f3fb78444 | ||
![]() |
995e4ada14 | ||
![]() |
7f60f3dbd7 | ||
![]() |
9a331d606f | ||
![]() |
b7c3a9fedd | ||
![]() |
e11eaf2f44 | ||
![]() |
b1d17ef9a2 | ||
![]() |
4ceed0b958 | ||
![]() |
269190274b | ||
![]() |
8e0a9dee1b | ||
![]() |
b9ad4da2e8 | ||
![]() |
fe3376141c | ||
![]() |
c35924663c | ||
![]() |
db9c592967 | ||
![]() |
bf6cabc804 | ||
![]() |
c80685f361 | ||
![]() |
51786141cc | ||
![]() |
1b831f214a | ||
![]() |
ec91a2be3c | ||
![]() |
8fec1c3085 | ||
![]() |
35ce37ded7 | ||
![]() |
d9ad09a32b | ||
![]() |
ebd543c0ac | ||
![]() |
eb7661f8ab | ||
![]() |
0c9899956d | ||
![]() |
9aea9768cb | ||
![]() |
67b23d7185 | ||
![]() |
ce28be2705 | ||
![]() |
61b529b7d1 | ||
![]() |
e7e122e9ff | ||
![]() |
432d9050c3 | ||
![]() |
50e287cece | ||
![]() |
e4ae213f06 | ||
![]() |
50d5756e8e | ||
![]() |
3416b2c82d | ||
![]() |
66ec056e39 | ||
![]() |
a0e270d0f2 | ||
![]() |
69d49c5a6f | ||
![]() |
fb5e5d2be6 | ||
![]() |
be336bb67f | ||
![]() |
a8062983cd | ||
![]() |
89e28ea66f | ||
![]() |
ec4a1525ee | ||
![]() |
30c6bb3651 | ||
![]() |
f23b845a29 | ||
![]() |
96faa3b469 | ||
![]() |
80a166f2e1 | ||
![]() |
11da02da72 | ||
![]() |
d93a942a79 | ||
![]() |
c4cd200a06 | ||
![]() |
85b1c71a34 | ||
![]() |
5773d5cd2b | ||
![]() |
1b6b0bfcac | ||
![]() |
58f31a70ef | ||
![]() |
2a1c67e0b2 | ||
![]() |
72e7a2e43e | ||
![]() |
1a7d9c2f58 | ||
![]() |
f4c7be5445 | ||
![]() |
2e4fac9d87 | ||
![]() |
66008fda5d | ||
![]() |
50ed6221d9 | ||
![]() |
46be1f8e54 | ||
![]() |
ecbd9e8cf7 | ||
![]() |
e808e61db8 | ||
![]() |
9e3daa1107 | ||
![]() |
448324637d | ||
![]() |
c54c213d6a | ||
![]() |
e2f2bd076f | ||
![]() |
5758da6e3c | ||
![]() |
e50110353a | ||
![]() |
ddfecf06c1 | ||
![]() |
f7cbe4ae1b | ||
![]() |
5515a5ac7a | ||
![]() |
5edd99312a | ||
![]() |
9a90fa2cb7 | ||
![]() |
7686989fc8 | ||
![]() |
53c4278a4c | ||
![]() |
c712d57ca9 | ||
![]() |
caef19689b | ||
![]() |
c369e446f9 | ||
![]() |
7bfa35cca8 | ||
![]() |
de701fe6aa | ||
![]() |
f7174bfc43 | ||
![]() |
878937bcc3 | ||
![]() |
1d4c31aa58 | ||
![]() |
ef1048d5f8 | ||
![]() |
744d23b348 | ||
![]() |
8de4be5168 | ||
![]() |
c0adca321d | ||
![]() |
a7643fac8d | ||
![]() |
d291c2338c | ||
![]() |
7f1c578b89 | ||
![]() |
2db5ab0a7b | ||
![]() |
0a37888e79 | ||
![]() |
882d8795c6 | ||
![]() |
9edba85f71 | ||
![]() |
bb588073ab | ||
![]() |
722735d20e | ||
![]() |
abe57e3d92 | ||
![]() |
1648ac5180 | ||
![]() |
6f84f65285 | ||
![]() |
3bb92146f5 | ||
![]() |
935f303a0a | ||
![]() |
b7717c3f1e | ||
![]() |
7aa37ea0ad | ||
![]() |
5d5bf6e087 | ||
![]() |
a69bda3b9b | ||
![]() |
715f60c11b | ||
![]() |
a8f68f57fe | ||
![]() |
738c2789cc | ||
![]() |
3457ec48af | ||
![]() |
3a2d76c7bc | ||
![]() |
27c05e1e24 | ||
![]() |
6c88e8e46e | ||
![]() |
36078bc83f | ||
![]() |
947bd3825e | ||
![]() |
9e9fdce9a8 | ||
![]() |
1b08cbc634 | ||
![]() |
f99ef6e190 | ||
![]() |
a91eb73064 | ||
![]() |
e7c3368c13 | ||
![]() |
9b82120ddb | ||
![]() |
3dcacdda0d | ||
![]() |
5f6ea5ff20 | ||
![]() |
8c5d96ffd3 | ||
![]() |
e974fc3c52 | ||
![]() |
7316a79318 | ||
![]() |
f5990e8547 | ||
![]() |
edf66baa21 | ||
![]() |
ab92daf408 | ||
![]() |
34ed4cf8fd | ||
![]() |
5a0615a7ed | ||
![]() |
e9356c1ff0 | ||
![]() |
004fb79706 | ||
![]() |
14f60c84c8 | ||
![]() |
b2f03f9132 | ||
![]() |
e73662ca7c | ||
![]() |
213cb65518 | ||
![]() |
e87737140f | ||
![]() |
62dca32dc5 | ||
![]() |
751583a1df | ||
![]() |
f7917453c9 | ||
![]() |
0b62b9c9a4 | ||
![]() |
c83ad6c077 | ||
![]() |
4eebfd1a7a | ||
![]() |
add161b367 | ||
![]() |
4e93f2aa01 | ||
![]() |
716fa08090 | ||
![]() |
b70b2c6196 | ||
![]() |
b40b01ffe3 | ||
![]() |
a20338cf10 | ||
![]() |
74d3009ba4 | ||
![]() |
8daa64a2e1 | ||
![]() |
df50fee7fd | ||
![]() |
58f1bf69d2 | ||
![]() |
47676bf593 | ||
![]() |
d9c249c25a | ||
![]() |
6310a405f6 | ||
![]() |
066aa9210a | ||
![]() |
c6a031e623 | ||
![]() |
793c2b5f9f | ||
![]() |
ade371fd1c | ||
![]() |
7c4fe83bd8 | ||
![]() |
66648c528a | ||
![]() |
c36e468794 | ||
![]() |
77f19944f6 | ||
![]() |
c160e4b7ce | ||
![]() |
59e8936768 | ||
![]() |
1b028cc9d9 | ||
![]() |
8a16b25fb1 | ||
![]() |
1a972e3e11 | ||
![]() |
133af57207 | ||
![]() |
d9d0a02d89 | ||
![]() |
c3235e6da7 | ||
![]() |
13bd4fffae | ||
![]() |
e7e8d6287b | ||
![]() |
0b301f8095 | ||
![]() |
2f68ac850b | ||
![]() |
068f6fb8fa | ||
![]() |
c1e30d97fe | ||
![]() |
8d80aecd50 | ||
![]() |
92e0f5b965 | ||
![]() |
0e26ada66d | ||
![]() |
6123b4ac26 | ||
![]() |
37895f8e50 | ||
![]() |
8d2110320b | ||
![]() |
f4490acfd7 | ||
![]() |
027afda403 | ||
![]() |
a062d5c985 | ||
![]() |
193ee766ca | ||
![]() |
38723bb778 | ||
![]() |
138769aa27 | ||
![]() |
ad3724b7ff | ||
![]() |
b8e2ec728c | ||
![]() |
257d392217 | ||
![]() |
2593af2c5d | ||
![]() |
f3b50e4669 | ||
![]() |
0b4d7d55f7 | ||
![]() |
114e8357e6 | ||
![]() |
4130c65578 | ||
![]() |
b4dca26c7d | ||
![]() |
cf4cc29819 | ||
![]() |
8e618f3869 | ||
![]() |
839ef35dc1 | ||
![]() |
f01aaa63a0 | ||
![]() |
63481bb926 | ||
![]() |
31b3b6701d | ||
![]() |
e1036119f2 | ||
![]() |
93989e995d | ||
![]() |
7be2735318 | ||
![]() |
c732a1f13a | ||
![]() |
453828d17d | ||
![]() |
d1248ca9be | ||
![]() |
e7783e9ab2 | ||
![]() |
01b8d3d409 | ||
![]() |
35722dff62 | ||
![]() |
688f78d380 | ||
![]() |
c76e0b03ec | ||
![]() |
898915d556 | ||
![]() |
3aad6e385b | ||
![]() |
a538ab7663 | ||
![]() |
a4032dce64 | ||
![]() |
c42178690e | ||
![]() |
3decbd6db9 | ||
![]() |
f95b43d6fa | ||
![]() |
c99417ffe8 | ||
![]() |
cd02c2809b | ||
![]() |
eedfc38322 | ||
![]() |
2fd9d8b339 | ||
![]() |
db3668a381 | ||
![]() |
dc188f2060 | ||
![]() |
c97b9c55b4 | ||
![]() |
64887aab03 | ||
![]() |
eb32729ab5 | ||
![]() |
a07871b9cd | ||
![]() |
e712e48e06 | ||
![]() |
de65741b8d | ||
![]() |
4b76a54815 | ||
![]() |
3da7339955 | ||
![]() |
02f81c6995 | ||
![]() |
f265ff5bcd | ||
![]() |
a552f7096a | ||
![]() |
96ee2fef3d | ||
![]() |
bf7a16254e | ||
![]() |
9b2b048692 | ||
![]() |
bf5abdb0b6 | ||
![]() |
b542f589a5 | ||
![]() |
f3b1a3b9d2 | ||
![]() |
ef6e079901 | ||
![]() |
5c064a986c | ||
![]() |
3a9d6f0a5f | ||
![]() |
53c23e62df | ||
![]() |
dba3c2695c | ||
![]() |
d7a28dd786 | ||
![]() |
a3e8247a41 | ||
![]() |
c9efbf9d97 | ||
![]() |
34a93a8d49 | ||
![]() |
268dcb677c | ||
![]() |
fc6cea0f0e | ||
![]() |
71a2daaacf | ||
![]() |
6ffc5f7b01 | ||
![]() |
d16a1dbd05 | ||
![]() |
4a063a9f8d | ||
![]() |
25d886f52c | ||
![]() |
d9b8a6407e | ||
![]() |
9c8464ca7d | ||
![]() |
e74a05286b | ||
![]() |
e506c46f7b | ||
![]() |
ff53fc1b97 | ||
![]() |
ea5293b036 | ||
![]() |
dd0e912a6e | ||
![]() |
b0d1fba7ac | ||
![]() |
69ca0a4c7a | ||
![]() |
c4bd2e31ce | ||
![]() |
226cbf0226 | ||
![]() |
f4ebc68320 | ||
![]() |
6407ebb870 | ||
![]() |
196b1f349e | ||
![]() |
d950f15987 | ||
![]() |
a36878eb2f | ||
![]() |
eabff673b3 | ||
![]() |
1557f7d3a3 | ||
![]() |
c5df7b7d3c | ||
![]() |
91e1e1328a | ||
![]() |
18fb88486d | ||
![]() |
7e6d3fac19 | ||
![]() |
24469c9bd1 | ||
![]() |
60a2e8e2c2 | ||
![]() |
d4ff985853 | ||
![]() |
f758010340 | ||
![]() |
4bee9cca55 | ||
![]() |
5d0d5936db | ||
![]() |
37542e6485 | ||
![]() |
4e3303fa08 | ||
![]() |
0abe85eebb | ||
![]() |
72a3408965 | ||
![]() |
9b91638190 | ||
![]() |
3feff21eca | ||
![]() |
3246df89d6 | ||
![]() |
29dd257253 | ||
![]() |
59f03d1b9d | ||
![]() |
73c2d5514c | ||
![]() |
a44dc3d59e | ||
![]() |
1e8217fd62 | ||
![]() |
9ce75726fc | ||
![]() |
cd9fef8bab | ||
![]() |
23b92b48a5 | ||
![]() |
159984a735 | ||
![]() |
c0089ef19d | ||
![]() |
78163939f1 | ||
![]() |
aafc21aa77 | ||
![]() |
658c8d8d96 | ||
![]() |
a2821815af | ||
![]() |
7d062ecd5f | ||
![]() |
abd2b2556a | ||
![]() |
9bbe11dd7b | ||
![]() |
80de2372e4 | ||
![]() |
5f0dc862f5 | ||
![]() |
16b98abca9 | ||
![]() |
96e62c57e3 | ||
![]() |
1f7f6de4ab | ||
![]() |
2ddea293a8 | ||
![]() |
5b1443aefd | ||
![]() |
9ace064d85 | ||
![]() |
19c5fe429e | ||
![]() |
d4a85643a4 | ||
![]() |
27932494bc | ||
![]() |
d97b7898b3 | ||
![]() |
c23a5c15aa | ||
![]() |
8091b2503d | ||
![]() |
ffaaf48382 | ||
![]() |
0e9d29ab73 | ||
![]() |
2704dc796b | ||
![]() |
f67791427d | ||
![]() |
3179a442af | ||
![]() |
4bb6e4f64a | ||
![]() |
d338de7f68 | ||
![]() |
b73b77a9b0 | ||
![]() |
09d4acdcb7 | ||
![]() |
527248b389 | ||
![]() |
4abc0399b5 | ||
![]() |
fbc5136aa0 | ||
![]() |
26de5f91c3 | ||
![]() |
f22273a72b | ||
![]() |
575220f460 | ||
![]() |
f16333e78b | ||
![]() |
d923945513 | ||
![]() |
1c786ee627 | ||
![]() |
b60b85b234 | ||
![]() |
27d20144a7 | ||
![]() |
4da0851809 | ||
![]() |
0359b85b58 | ||
![]() |
27d7ea43eb | ||
![]() |
1a20c4d487 | ||
![]() |
980997f215 | ||
![]() |
b1077aa14e | ||
![]() |
956bf3962e | ||
![]() |
141291a1d8 | ||
![]() |
ddb99241b5 | ||
![]() |
096806ee26 | ||
![]() |
6b42c2b8c9 | ||
![]() |
1f2ad77505 | ||
![]() |
42fdd1b91f | ||
![]() |
af3de08154 | ||
![]() |
2189bcaac0 | ||
![]() |
468ceafca5 | ||
![]() |
4b4680a0a9 | ||
![]() |
55db05519e | ||
![]() |
bfc013ab93 | ||
![]() |
4c99900236 | ||
![]() |
75d5c0e3fb | ||
![]() |
6ae8457a86 | ||
![]() |
d852af7167 | ||
![]() |
04bce6ad2e | ||
![]() |
e2adcd7de1 | ||
![]() |
72a25591b0 | ||
![]() |
383b228a16 | ||
![]() |
062e644aae | ||
![]() |
92c93a2780 | ||
![]() |
095fe0d649 | ||
![]() |
2018e667a6 | ||
![]() |
0019261abc | ||
![]() |
7757078ecd | ||
![]() |
767604e03f | ||
![]() |
2c90480e1a | ||
![]() |
ba618a307a | ||
![]() |
c0cc19b5b3 | ||
![]() |
afed2c0190 | ||
![]() |
e269f44b25 | ||
![]() |
c47b91f513 | ||
![]() |
a5fde8ab9b | ||
![]() |
21218b666a | ||
![]() |
59acf8af38 | ||
![]() |
6e0ad52e7a | ||
![]() |
4ebf14d17e | ||
![]() |
e7b967132f | ||
![]() |
07b68e2425 | ||
![]() |
680cbe3a4f | ||
![]() |
6064a43545 | ||
![]() |
507234c47d | ||
![]() |
f066e3fcae | ||
![]() |
b776bf92ad | ||
![]() |
ca0dbb8fa6 | ||
![]() |
eaa048925e | ||
![]() |
d85cf00ee8 | ||
![]() |
4f1772e2ae | ||
![]() |
ef8deb6d4a | ||
![]() |
411ed778d5 | ||
![]() |
44d5da00b5 | ||
![]() |
e0a780a505 | ||
![]() |
e9e756da7a | ||
![]() |
b4dc40bf7a | ||
![]() |
249c6536c4 | ||
![]() |
6ea4eddf93 | ||
![]() |
1b6de7b0a3 | ||
![]() |
33f0d9e79a | ||
![]() |
df5a87d93b | ||
![]() |
b0eed7c6bd | ||
![]() |
ad5c315dda | ||
![]() |
9aa33f467b | ||
![]() |
8900e3ac8a | ||
![]() |
4f0532d6f0 | ||
![]() |
18c17bea75 | ||
![]() |
05b63c4bcc | ||
![]() |
7af77d1cf1 | ||
![]() |
b859a377c0 | ||
![]() |
6debce63bc | ||
![]() |
f6c139c521 | ||
![]() |
eb5d175c9c | ||
![]() |
d848209d38 | ||
![]() |
fa6caa6ca8 | ||
![]() |
6463fb874f | ||
![]() |
e3c9b0430e | ||
![]() |
6c1bd08f16 | ||
![]() |
799adb5323 | ||
![]() |
162ecd1d2c | ||
![]() |
8c8675c62a | ||
![]() |
4bb7bf2bdc | ||
![]() |
6d32ab02c5 | ||
![]() |
f51e53726b | ||
![]() |
436e12f290 | ||
![]() |
1e557184b0 | ||
![]() |
9fe788d870 | ||
![]() |
fdb01f8622 | ||
![]() |
2893c42176 | ||
![]() |
7f033136ac | ||
![]() |
4af87d8a43 | ||
![]() |
ba21a85699 | ||
![]() |
5d5b7316db | ||
![]() |
fc2a16433e | ||
![]() |
20d8ccb542 | ||
![]() |
62c2b167bc | ||
![]() |
9ce100ba61 | ||
![]() |
c940f75d5b | ||
![]() |
9d5edd3020 | ||
![]() |
fb8dfdeec5 | ||
![]() |
c6800e0c65 | ||
![]() |
8ed3e3d07e | ||
![]() |
7f7673d941 | ||
![]() |
712f8b37fb | ||
![]() |
96bd428524 | ||
![]() |
911b59fb4f | ||
![]() |
40053b522e | ||
![]() |
abdc31cd4f | ||
![]() |
497a72560d | ||
![]() |
431bd09e15 | ||
![]() |
75f99bded3 | ||
![]() |
98fcccee55 | ||
![]() |
f6188ce6dc | ||
![]() |
9b307405fb | ||
![]() |
421383d560 | ||
![]() |
fa5fd262ff | ||
![]() |
24c708eb37 | ||
![]() |
4d0a4b15a9 | ||
![]() |
1af29fbfa5 | ||
![]() |
5436810921 | ||
![]() |
3451502daa | ||
![]() |
def048356b | ||
![]() |
a66016cb94 | ||
![]() |
3dea6e3635 | ||
![]() |
82e150a13a | ||
![]() |
2d62a09e83 | ||
![]() |
ae2c0758c9 | ||
![]() |
e9681a40dc | ||
![]() |
ac7402cbf6 | ||
![]() |
f239d227c0 | ||
![]() |
bd1e980349 | ||
![]() |
14d84ba2e9 | ||
![]() |
14e5ce5412 | ||
![]() |
3800ebd81d | ||
![]() |
062b54931d | ||
![]() |
5379d4f3f4 | ||
![]() |
f87df0e3c8 | ||
![]() |
fa7f01592b | ||
![]() |
086ae68076 | ||
![]() |
a57ab326b2 | ||
![]() |
9ce3c806e4 | ||
![]() |
71e71e5f52 | ||
![]() |
24ffc54a53 | ||
![]() |
fd6e92aa46 | ||
![]() |
dab1be38e6 | ||
![]() |
6f4976a7ac | ||
![]() |
eb213151ce | ||
![]() |
7af3abd383 | ||
![]() |
67eaf24665 | ||
![]() |
147526451a | ||
![]() |
9b161072c1 | ||
![]() |
6cfb51871b | ||
![]() |
2918ea3b07 | ||
![]() |
7e2b2d4784 | ||
![]() |
c26c7728e8 | ||
![]() |
8089aaad6b | ||
![]() |
50a856970d | ||
![]() |
07a2e6f678 | ||
![]() |
862c6f2c0c | ||
![]() |
b4a6bb08fa | ||
![]() |
9b317178d6 | ||
![]() |
01001d5cff | ||
![]() |
31fe97e7ce | ||
![]() |
111880efc7 | ||
![]() |
fb9fe6b565 | ||
![]() |
f3f3acc444 | ||
![]() |
afc0fb05cb | ||
![]() |
cae7ae3a4d | ||
![]() |
f61299a62a | ||
![]() |
bbe1bdf1ed | ||
![]() |
d038a24ca2 | ||
![]() |
dea2f94ebd | ||
![]() |
c5f8e8bd59 | ||
![]() |
0d768e58f4 | ||
![]() |
8acb8548c3 | ||
![]() |
a4992b4d50 | ||
![]() |
a24e1f7959 | ||
![]() |
95e77cb559 | ||
![]() |
df0aeeeee0 | ||
![]() |
4ce049dbfa | ||
![]() |
343795029f | ||
![]() |
e1506769a4 | ||
![]() |
5f01b872e0 | ||
![]() |
fda2561f79 | ||
![]() |
777cae55b6 | ||
![]() |
b92822afee | ||
![]() |
b517dfb396 | ||
![]() |
889a8d5dd2 | ||
![]() |
32dd9ecb2e | ||
![]() |
6417c99bfd | ||
![]() |
73cb6e7734 | ||
![]() |
3905173cb3 | ||
![]() |
d2c938eb02 | ||
![]() |
6e3677f3f0 | ||
![]() |
022f89625f | ||
![]() |
b3b341b44f | ||
![]() |
811de5f36b | ||
![]() |
fb1d1b2fc8 | ||
![]() |
10677baa40 | ||
![]() |
d24bc4364c | ||
![]() |
95c03b9638 | ||
![]() |
e0c572833a | ||
![]() |
4ea75cd495 | ||
![]() |
e66e0f8ff0 | ||
![]() |
6e97c5f47c | ||
![]() |
9bd4134f31 | ||
![]() |
8c22d232b5 | ||
![]() |
98db4abc21 | ||
![]() |
1d2ed2bb42 | ||
![]() |
33e3bb1e4e | ||
![]() |
5fe6d48fcd | ||
![]() |
565f9c92b7 | ||
![]() |
5543d1b55a | ||
![]() |
7a29568115 | ||
![]() |
799f76f537 | ||
![]() |
f298032ddb | ||
![]() |
8954e58ccf | ||
![]() |
4efb795129 | ||
![]() |
0f26a0369e | ||
![]() |
3e731527e4 | ||
![]() |
521d1b8129 | ||
![]() |
e401b6bb1e | ||
![]() |
e64949ee69 | ||
![]() |
ea4c772746 | ||
![]() |
05e1fbf27d | ||
![]() |
668bace2ab | ||
![]() |
8a84bebcfc | ||
![]() |
4f5268af4f | ||
![]() |
b8df7e4b10 | ||
![]() |
092959ff1f | ||
![]() |
ced2d65679 | ||
![]() |
f0a99f6402 | ||
![]() |
3fafd806b3 | ||
![]() |
c758126a27 | ||
![]() |
7c94ed61a5 | ||
![]() |
389e9c23a9 | ||
![]() |
c5b458ef4b | ||
![]() |
6ef3e466db | ||
![]() |
b97ec62368 | ||
![]() |
61fe8418cc | ||
![]() |
dc90d4951f | ||
![]() |
f10ce0c942 | ||
![]() |
e9f520c16a | ||
![]() |
3501cefb09 | ||
![]() |
93701d249e | ||
![]() |
72fbacd996 | ||
![]() |
3083f4470b | ||
![]() |
ab86513710 | ||
![]() |
1c6b3a3a6f | ||
![]() |
e7ddf524b0 | ||
![]() |
085efac037 | ||
![]() |
f1d4e742c9 | ||
![]() |
28ab82aab0 | ||
![]() |
d9eee31ec8 | ||
![]() |
9424e795bf | ||
![]() |
dc8cdda8fd | ||
![]() |
f52cb0fe37 | ||
![]() |
136930fccb | ||
![]() |
bd9d52b52d | ||
![]() |
20d7ae0676 | ||
![]() |
b0c2bcc953 | ||
![]() |
8485191448 | ||
![]() |
f1813e31b6 | ||
![]() |
0f7cf9187f | ||
![]() |
5e2bb528e0 | ||
![]() |
b336b390d0 | ||
![]() |
ebd3e391da | ||
![]() |
e151686c6f | ||
![]() |
8cdac18a04 | ||
![]() |
a066a2bc8b | ||
![]() |
a18ee4018f | ||
![]() |
72a84d4099 | ||
![]() |
e0253080b0 | ||
![]() |
17e42cb94b | ||
![]() |
db2715441a | ||
![]() |
dfa45cec9e | ||
![]() |
40759445c9 | ||
![]() |
05954c0950 | ||
![]() |
9a73bb86db | ||
![]() |
19f6aa8208 | ||
![]() |
ecf8c74481 | ||
![]() |
d0b04d9f21 | ||
![]() |
7dacdbe6dc | ||
![]() |
0d1b957d40 | ||
![]() |
117891878e | ||
![]() |
1d7260050d | ||
![]() |
1d7163957a | ||
![]() |
d7b091e762 | ||
![]() |
78317a4cfb | ||
![]() |
3cb010ec8e | ||
![]() |
147d075a4c | ||
![]() |
eb9d0396cd | ||
![]() |
1e0ec543ff | ||
![]() |
5e191c29d4 | ||
![]() |
53cabe7265 | ||
![]() |
0753d99519 | ||
![]() |
f297c4644e | ||
![]() |
f80f49767c | ||
![]() |
64c8be01f0 | ||
![]() |
bd961304b6 | ||
![]() |
b21c0c3d28 | ||
![]() |
7bf233a944 | ||
![]() |
9afffacaa0 | ||
![]() |
fac498bf31 | ||
![]() |
92eeacc2e3 | ||
![]() |
6b38b52187 | ||
![]() |
cbf5401eff | ||
![]() |
5434407af7 | ||
![]() |
467efe1556 | ||
![]() |
aedb4ff7f0 | ||
![]() |
26970742b7 | ||
![]() |
62ed5389fc | ||
![]() |
da8a5bb189 | ||
![]() |
c75abed63e | ||
![]() |
847d468b82 | ||
![]() |
2f3fa1f6d0 | ||
![]() |
3b2a7d196b | ||
![]() |
872bb9474e | ||
![]() |
3500e1cda5 | ||
![]() |
0fd353f163 | ||
![]() |
09915f4bd2 | ||
![]() |
31a9d8a184 | ||
![]() |
39b55f787c | ||
![]() |
1af5331089 | ||
![]() |
a5381ba764 | ||
![]() |
7b15393658 | ||
![]() |
37861b4ce2 | ||
![]() |
0540591e25 | ||
![]() |
22747a6937 | ||
![]() |
911470a610 | ||
![]() |
41e6700640 | ||
![]() |
8b0c7bcfda | ||
![]() |
72de89f54e | ||
![]() |
77d11bb4b4 | ||
![]() |
79575f3376 | ||
![]() |
a8b4665e7d | ||
![]() |
16275d24e3 | ||
![]() |
a5bb6e0a32 | ||
![]() |
7a093f0303 | ||
![]() |
fcfead919b | ||
![]() |
8b06805334 | ||
![]() |
366a0806eb | ||
![]() |
8a59528c2d | ||
![]() |
d249f2d838 | ||
![]() |
5bb4da02c2 | ||
![]() |
0969ca4a46 | ||
![]() |
b97a4ac449 | ||
![]() |
8c04847aa2 | ||
![]() |
104aec555f | ||
![]() |
ef7c45f281 | ||
![]() |
b92ec34843 | ||
![]() |
e465acf6f8 | ||
![]() |
355a6b34b3 | ||
![]() |
b1d0601016 | ||
![]() |
e76adbecb8 | ||
![]() |
8ea641eed5 | ||
![]() |
4760b6e71e | ||
![]() |
982e7fd9de | ||
![]() |
6665677495 | ||
![]() |
6559bdbd9d | ||
![]() |
65abd1006b | ||
![]() |
4dd100bff2 | ||
![]() |
e3000ace2f | ||
![]() |
4622e4cb82 | ||
![]() |
756177a617 | ||
![]() |
91773b8909 | ||
![]() |
2946d3b03d | ||
![]() |
c64fb8cbb1 | ||
![]() |
548d699161 | ||
![]() |
dd6c674e3a | ||
![]() |
ae56983a5f | ||
![]() |
14072be245 | ||
![]() |
017aafea99 | ||
![]() |
be16cfa035 | ||
![]() |
3980b4b176 | ||
![]() |
8d8b3d1805 | ||
![]() |
742ddd1561 | ||
![]() |
bd7f49df3e | ||
![]() |
52f402dcfb | ||
![]() |
e2fd914dc1 | ||
![]() |
52384bf0a3 | ||
![]() |
4a007a881f | ||
![]() |
aa31a117b1 | ||
![]() |
05b54b8432 |
@ -1,9 +0,0 @@
|
|||||||
[report]
|
|
||||||
omit =
|
|
||||||
src/blib2to3/*
|
|
||||||
tests/data/*
|
|
||||||
*/site-packages/*
|
|
||||||
.tox/*
|
|
||||||
|
|
||||||
[run]
|
|
||||||
relative_files = True
|
|
5
.flake8
5
.flake8
@ -1,7 +1,8 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
ignore = E203, E266, E501, W503
|
# B905 should be enabled when we drop support for 3.9
|
||||||
|
ignore = E203, E266, E501, E701, E704, W503, B905, B907
|
||||||
# line length is intentionally set to 80 here because black uses Bugbear
|
# line length is intentionally set to 80 here because black uses Bugbear
|
||||||
# See https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#line-length for more details
|
# See https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html#bugbear for more details
|
||||||
max-line-length = 80
|
max-line-length = 80
|
||||||
max-complexity = 18
|
max-complexity = 18
|
||||||
select = B,C,E,F,W,T4,B9
|
select = B,C,E,F,W,T4,B9
|
||||||
|
3
.git_archival.txt
Normal file
3
.git_archival.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node: $Format:%H$
|
||||||
|
node-date: $Format:%cI$
|
||||||
|
describe-name: $Format:%(describe:tags=true,match=[0-9]*)$
|
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.git_archival.txt export-subst
|
||||||
|
*.py diff=python
|
65
.github/ISSUE_TEMPLATE/bug_report.md
vendored
65
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,47 +1,66 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help us improve
|
about: Create a report to help us improve Black's quality
|
||||||
title: ""
|
title: ""
|
||||||
labels: bug
|
labels: "T: bug"
|
||||||
assignees: ""
|
assignees: ""
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please make sure that the bug is not already fixed either in newer versions or the
|
||||||
|
current development version. To confirm this, you have three options:
|
||||||
|
|
||||||
|
1. Update Black's version if a newer release exists: `pip install -U black`
|
||||||
|
2. Use the online formatter at <https://black.vercel.app/?version=main>, which will use
|
||||||
|
the latest main branch. Note that the online formatter currently runs on
|
||||||
|
an older version of Python and may not support newer syntax, such as the
|
||||||
|
extended f-string syntax added in Python 3.12.
|
||||||
|
3. Or run _Black_ on your machine:
|
||||||
|
- create a new virtualenv (make sure it's the same Python version);
|
||||||
|
- clone this repository;
|
||||||
|
- run `pip install -e .[d]`;
|
||||||
|
- run `pip install -r test_requirements.txt`
|
||||||
|
- make sure it's sane by running `python -m pytest`; and
|
||||||
|
- run `black` like you did last time.
|
||||||
|
-->
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
|
|
||||||
<!-- A clear and concise description of what the bug is. -->
|
<!-- A clear and concise description of what the bug is. -->
|
||||||
|
|
||||||
**To Reproduce**
|
**To Reproduce**
|
||||||
|
|
||||||
<!-- Steps to reproduce the behavior:
|
<!--
|
||||||
|
Minimal steps to reproduce the behavior with source code and Black's configuration.
|
||||||
|
-->
|
||||||
|
|
||||||
For example:
|
For example, take this code:
|
||||||
1. Take this file '...'
|
|
||||||
1. Run _Black_ on it with these arguments '...'
|
```python
|
||||||
1. See error -->
|
this = "code"
|
||||||
|
```
|
||||||
|
|
||||||
|
And run it with these arguments:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ black file.py --target-version py39
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulting error is:
|
||||||
|
|
||||||
|
> cannot format file.py: INTERNAL ERROR: ...
|
||||||
|
|
||||||
**Expected behavior**
|
**Expected behavior**
|
||||||
|
|
||||||
<!-- A clear and concise description of what you expected to happen. -->
|
<!-- A clear and concise description of what you expected to happen. -->
|
||||||
|
|
||||||
**Environment (please complete the following information):**
|
**Environment**
|
||||||
|
|
||||||
- Version: <!-- e.g. [main] -->
|
<!-- Please complete the following information: -->
|
||||||
|
|
||||||
|
- Black's version: <!-- e.g. [main] -->
|
||||||
- OS and Python version: <!-- e.g. [Linux/Python 3.7.4rc1] -->
|
- OS and Python version: <!-- e.g. [Linux/Python 3.7.4rc1] -->
|
||||||
|
|
||||||
**Does this bug also happen on main?**
|
|
||||||
|
|
||||||
<!-- To answer this, you have two options:
|
|
||||||
|
|
||||||
1. Use the online formatter at <https://black.vercel.app/?version=main>, which will use
|
|
||||||
the latest main branch.
|
|
||||||
1. Or run _Black_ on your machine:
|
|
||||||
- create a new virtualenv (make sure it's the same Python version);
|
|
||||||
- clone this repository;
|
|
||||||
- run `pip install -e .[d,python2]`;
|
|
||||||
- run `pip install -r test_requirements.txt`
|
|
||||||
- make sure it's sane by running `python -m pytest`; and
|
|
||||||
- run `black` like you did last time. -->
|
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
|
||||||
<!-- Add any other context about the problem here. -->
|
<!-- Add any other context about the problem here. -->
|
||||||
|
12
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
12
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# See also: https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
|
||||||
|
|
||||||
|
# This is the default and blank issues are useful so let's keep 'em.
|
||||||
|
blank_issues_enabled: true
|
||||||
|
|
||||||
|
contact_links:
|
||||||
|
- name: Chat on Python Discord
|
||||||
|
url: https://discord.gg/RtVdv86PrH
|
||||||
|
about: |
|
||||||
|
User support, questions, and other lightweight requests can be
|
||||||
|
handled via the #black-formatter text channel we have on Python
|
||||||
|
Discord.
|
27
.github/ISSUE_TEMPLATE/docs-issue.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/docs-issue.md
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: Documentation
|
||||||
|
about: Report a problem with or suggest something for the documentation
|
||||||
|
title: ""
|
||||||
|
labels: "T: documentation"
|
||||||
|
assignees: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is this related to a problem? Please describe.**
|
||||||
|
|
||||||
|
<!-- A clear and concise description of what the problem is.
|
||||||
|
e.g. I'm always frustrated when [...] / I wished that [...] -->
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
|
||||||
|
<!-- A clear and concise description of what you want to
|
||||||
|
happen or see changed. -->
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
|
||||||
|
<!-- A clear and concise description of any
|
||||||
|
alternative solutions or features you've considered. -->
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
|
||||||
|
<!-- Add any other context or screenshots about the issue
|
||||||
|
here. -->
|
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -2,7 +2,7 @@
|
|||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest an idea for this project
|
about: Suggest an idea for this project
|
||||||
title: ""
|
title: ""
|
||||||
labels: enhancement
|
labels: "T: enhancement"
|
||||||
assignees: ""
|
assignees: ""
|
||||||
---
|
---
|
||||||
|
|
||||||
|
6
.github/ISSUE_TEMPLATE/style_issue.md
vendored
6
.github/ISSUE_TEMPLATE/style_issue.md
vendored
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
name: Style issue
|
name: Code style issue
|
||||||
about: Help us improve the Black style
|
about: Help us improve the Black code style
|
||||||
title: ""
|
title: ""
|
||||||
labels: design
|
labels: "T: style"
|
||||||
assignees: ""
|
assignees: ""
|
||||||
---
|
---
|
||||||
|
|
||||||
|
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<!-- Hello! Thanks for submitting a PR. To help make things go a bit more
|
||||||
|
smoothly we would appreciate that you go through this template. -->
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
<!-- Good things to put here include: reasoning for the change (please link
|
||||||
|
any relevant issues!), any noteworthy (or hacky) choices to be aware of,
|
||||||
|
or what the problem resolved here looked like ... we won't mind a ranty
|
||||||
|
story :) -->
|
||||||
|
|
||||||
|
### Checklist - did you ...
|
||||||
|
|
||||||
|
<!-- If any of the following items aren't relevant for your contribution
|
||||||
|
please still tick them so we know you've gone through the checklist.
|
||||||
|
|
||||||
|
All user-facing changes should get an entry. Otherwise, signal to us
|
||||||
|
this should get the magical label to silence the CHANGELOG entry check.
|
||||||
|
Tests are required for bugfixes and new features. Documentation changes
|
||||||
|
are necessary for formatting and most enhancement changes. -->
|
||||||
|
|
||||||
|
- [ ] Add an entry in `CHANGES.md` if necessary?
|
||||||
|
- [ ] Add / update tests if necessary?
|
||||||
|
- [ ] Add new / update outdated documentation?
|
||||||
|
|
||||||
|
<!-- Just as a reminder, everyone in all psf/black spaces including PRs
|
||||||
|
must follow the PSF Code of Conduct (link below).
|
||||||
|
|
||||||
|
Finally, once again thanks for your time and effort. If you have any
|
||||||
|
feedback in regards to your experience contributing here, please
|
||||||
|
let us know!
|
||||||
|
|
||||||
|
Helpful links:
|
||||||
|
|
||||||
|
PSF COC: https://www.python.org/psf/conduct/
|
||||||
|
Contributing docs: https://black.readthedocs.io/en/latest/contributing/index.html
|
||||||
|
Chat on Python Discord: https://discord.gg/RtVdv86PrH -->
|
16
.github/dependabot.yml
vendored
Normal file
16
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
# Workflow files in .github/workflows will be checked
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels: ["skip news", "C: dependencies"]
|
||||||
|
|
||||||
|
- package-ecosystem: "pip"
|
||||||
|
directory: "docs/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels: ["skip news", "C: dependencies", "T: documentation"]
|
7
.github/workflows/changelog.yml
vendored
7
.github/workflows/changelog.yml
vendored
@ -4,6 +4,9 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, labeled, unlabeled, reopened]
|
types: [opened, synchronize, labeled, unlabeled, reopened]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Changelog Entry Check
|
name: Changelog Entry Check
|
||||||
@ -11,11 +14,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Grep CHANGES.md for PR number
|
- name: Grep CHANGES.md for PR number
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'skip news') != true
|
if: contains(github.event.pull_request.labels.*.name, 'skip news') != true
|
||||||
run: |
|
run: |
|
||||||
grep -Pz "\((\n\s*)?#${{ github.event.pull_request.number }}(\n\s*)?\)" CHANGES.md || \
|
grep -Pz "\((\n\s*)?#${{ github.event.pull_request.number }}(\n\s*)?\)" CHANGES.md || \
|
||||||
(echo "Please add '(#${{ github.event.pull_request.number }})' change line to CHANGES.md" && \
|
(echo "Please add '(#${{ github.event.pull_request.number }})' change line to CHANGES.md (or if appropriate, ask a maintainer to add the 'skip news' label)" && \
|
||||||
exit 1)
|
exit 1)
|
||||||
|
155
.github/workflows/diff_shades.yml
vendored
Normal file
155
.github/workflows/diff_shades.yml
vendored
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
name: diff-shades
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths: ["src/**", "pyproject.toml", ".github/workflows/*"]
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
paths: ["src/**", "pyproject.toml", ".github/workflows/*"]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
configure:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
matrix: ${{ steps.set-config.outputs.matrix }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.11"
|
||||||
|
|
||||||
|
- name: Install diff-shades and support dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install 'click>=8.1.7' packaging urllib3
|
||||||
|
python -m pip install https://github.com/ichard26/diff-shades/archive/stable.zip
|
||||||
|
|
||||||
|
- name: Calculate run configuration & metadata
|
||||||
|
id: set-config
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
run: >
|
||||||
|
python scripts/diff_shades_gha_helper.py config ${{ github.event_name }}
|
||||||
|
${{ matrix.mode }}
|
||||||
|
|
||||||
|
analysis:
|
||||||
|
name: analysis / ${{ matrix.mode }}
|
||||||
|
needs: configure
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
HATCH_BUILD_HOOKS_ENABLE: "1"
|
||||||
|
# Clang is less picky with the C code it's given than gcc (and may
|
||||||
|
# generate faster binaries too).
|
||||||
|
CC: clang-18
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include: ${{ fromJson(needs.configure.outputs.matrix) }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout this repository (full clone)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# The baseline revision could be rather old so a full clone is ideal.
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.11"
|
||||||
|
|
||||||
|
- name: Install diff-shades and support dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install https://github.com/ichard26/diff-shades/archive/stable.zip
|
||||||
|
python -m pip install 'click>=8.1.7' packaging urllib3
|
||||||
|
# After checking out old revisions, this might not exist so we'll use a copy.
|
||||||
|
cat scripts/diff_shades_gha_helper.py > helper.py
|
||||||
|
git config user.name "diff-shades-gha"
|
||||||
|
git config user.email "diff-shades-gha@example.com"
|
||||||
|
|
||||||
|
- name: Attempt to use cached baseline analysis
|
||||||
|
id: baseline-cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{ matrix.baseline-analysis }}
|
||||||
|
key: ${{ matrix.baseline-cache-key }}
|
||||||
|
|
||||||
|
- name: Build and install baseline revision
|
||||||
|
if: steps.baseline-cache.outputs.cache-hit != 'true'
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
run: >
|
||||||
|
${{ matrix.baseline-setup-cmd }}
|
||||||
|
&& python -m pip install .
|
||||||
|
|
||||||
|
- name: Analyze baseline revision
|
||||||
|
if: steps.baseline-cache.outputs.cache-hit != 'true'
|
||||||
|
run: >
|
||||||
|
diff-shades analyze -v --work-dir projects-cache/
|
||||||
|
${{ matrix.baseline-analysis }} ${{ matrix.force-flag }}
|
||||||
|
|
||||||
|
- name: Build and install target revision
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
run: >
|
||||||
|
${{ matrix.target-setup-cmd }}
|
||||||
|
&& python -m pip install .
|
||||||
|
|
||||||
|
- name: Analyze target revision
|
||||||
|
run: >
|
||||||
|
diff-shades analyze -v --work-dir projects-cache/
|
||||||
|
${{ matrix.target-analysis }} --repeat-projects-from
|
||||||
|
${{ matrix.baseline-analysis }} ${{ matrix.force-flag }}
|
||||||
|
|
||||||
|
- name: Generate HTML diff report
|
||||||
|
run: >
|
||||||
|
diff-shades --dump-html diff.html compare --diff
|
||||||
|
${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }}
|
||||||
|
|
||||||
|
- name: Upload diff report
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.mode }}-diff.html
|
||||||
|
path: diff.html
|
||||||
|
|
||||||
|
- name: Upload baseline analysis
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.baseline-analysis }}
|
||||||
|
path: ${{ matrix.baseline-analysis }}
|
||||||
|
|
||||||
|
- name: Upload target analysis
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.target-analysis }}
|
||||||
|
path: ${{ matrix.target-analysis }}
|
||||||
|
|
||||||
|
- name: Generate summary file (PR only)
|
||||||
|
if: github.event_name == 'pull_request' && matrix.mode == 'preview-changes'
|
||||||
|
run: >
|
||||||
|
python helper.py comment-body ${{ matrix.baseline-analysis }}
|
||||||
|
${{ matrix.target-analysis }} ${{ matrix.baseline-sha }}
|
||||||
|
${{ matrix.target-sha }} ${{ github.event.pull_request.number }}
|
||||||
|
|
||||||
|
- name: Upload summary file (PR only)
|
||||||
|
if: github.event_name == 'pull_request' && matrix.mode == 'preview-changes'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: .pr-comment.json
|
||||||
|
path: .pr-comment.json
|
||||||
|
|
||||||
|
- name: Verify zero changes (PR only)
|
||||||
|
if: matrix.mode == 'assert-no-changes'
|
||||||
|
run: >
|
||||||
|
diff-shades compare --check ${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }}
|
||||||
|
|| (echo "Please verify you didn't change the stable code style unintentionally!" && exit 1)
|
||||||
|
|
||||||
|
- name: Check for failed files for target revision
|
||||||
|
# Even if the previous step failed, we should still check for failed files.
|
||||||
|
if: always()
|
||||||
|
run: >
|
||||||
|
diff-shades show-failed --check --show-log ${{ matrix.target-analysis }}
|
49
.github/workflows/diff_shades_comment.yml
vendored
Normal file
49
.github/workflows/diff_shades_comment.yml
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
name: diff-shades-comment
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: [diff-shades]
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
comment:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "*"
|
||||||
|
|
||||||
|
- name: Install support dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install pip --upgrade
|
||||||
|
python -m pip install click packaging urllib3
|
||||||
|
|
||||||
|
- name: Get details from initial workflow run
|
||||||
|
id: metadata
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
run: >
|
||||||
|
python scripts/diff_shades_gha_helper.py comment-details
|
||||||
|
${{github.event.workflow_run.id }}
|
||||||
|
|
||||||
|
- name: Try to find pre-existing PR comment
|
||||||
|
if: steps.metadata.outputs.needs-comment == 'true'
|
||||||
|
id: find-comment
|
||||||
|
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e
|
||||||
|
with:
|
||||||
|
issue-number: ${{ steps.metadata.outputs.pr-number }}
|
||||||
|
comment-author: "github-actions[bot]"
|
||||||
|
body-includes: "diff-shades"
|
||||||
|
|
||||||
|
- name: Create or update PR comment
|
||||||
|
if: steps.metadata.outputs.needs-comment == 'true'
|
||||||
|
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043
|
||||||
|
with:
|
||||||
|
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||||
|
issue-number: ${{ steps.metadata.outputs.pr-number }}
|
||||||
|
body: ${{ steps.metadata.outputs.comment-body }}
|
||||||
|
edit-mode: replace
|
19
.github/workflows/doc.yml
vendored
19
.github/workflows/doc.yml
vendored
@ -1,7 +1,10 @@
|
|||||||
name: Documentation Build
|
name: Documentation
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
||||||
@ -18,16 +21,20 @@ jobs:
|
|||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up latest Python
|
- name: Set up latest Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.13"
|
||||||
|
allow-prereleases: true
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip setuptools wheel
|
python -m pip install uv
|
||||||
python -m pip install -e ".[d]"
|
python -m uv venv
|
||||||
python -m pip install -r "docs/requirements.txt"
|
python -m uv pip install -e ".[d]"
|
||||||
|
python -m uv pip install -r "docs/requirements.txt"
|
||||||
|
|
||||||
- name: Build documentation
|
- name: Build documentation
|
||||||
run: sphinx-build -a -b html -W --keep-going docs/ docs/_build
|
run: sphinx-build -a -b html -W --keep-going docs/ docs/_build
|
||||||
|
37
.github/workflows/docker.yml
vendored
37
.github/workflows/docker.yml
vendored
@ -5,7 +5,10 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- "main"
|
- "main"
|
||||||
release:
|
release:
|
||||||
types: created
|
types: [published]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
@ -13,16 +16,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
@ -33,12 +36,34 @@ jobs:
|
|||||||
latest_non_release)" >> $GITHUB_ENV
|
latest_non_release)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: pyfound/black:latest,pyfound/black:${{ env.GIT_TAG }}
|
tags: pyfound/black:latest,pyfound/black:${{ env.GIT_TAG }}
|
||||||
|
|
||||||
|
- name: Build and push latest_release tag
|
||||||
|
if:
|
||||||
|
${{ github.event_name == 'release' && github.event.action == 'published' &&
|
||||||
|
!github.event.release.prerelease }}
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: pyfound/black:latest_release
|
||||||
|
|
||||||
|
- name: Build and push latest_prerelease tag
|
||||||
|
if:
|
||||||
|
${{ github.event_name == 'release' && github.event.action == 'published' &&
|
||||||
|
github.event.release.prerelease }}
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: pyfound/black:latest_prerelease
|
||||||
|
|
||||||
- name: Image digest
|
- name: Image digest
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
|
14
.github/workflows/fuzz.yml
vendored
14
.github/workflows/fuzz.yml
vendored
@ -2,6 +2,13 @@ name: Fuzz
|
|||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
||||||
@ -15,15 +22,16 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.6, 3.7, 3.8, 3.9]
|
python-version: ["3.9", "3.10", "3.11", "3.12.4", "3.13"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
allow-prereleases: true
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
34
.github/workflows/lint.yml
vendored
34
.github/workflows/lint.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Lint
|
name: Lint + format ourselves
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
@ -14,15 +14,35 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Assert PR target is main
|
||||||
uses: actions/setup-python@v2
|
if: github.event_name == 'pull_request' && github.repository == 'psf/black'
|
||||||
|
run: |
|
||||||
|
if [ "$GITHUB_BASE_REF" != "main" ]; then
|
||||||
|
echo "::error::PR targeting '$GITHUB_BASE_REF', please refile targeting 'main'." && exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Set up latest Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.13"
|
||||||
|
allow-prereleases: true
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install -e '.[d]'
|
python -m pip install -e '.'
|
||||||
|
python -m pip install tox
|
||||||
|
|
||||||
- name: Lint
|
- name: Run pre-commit hooks
|
||||||
uses: pre-commit/action@v2.0.2
|
uses: pre-commit/action@v3.0.1
|
||||||
|
|
||||||
|
- name: Format ourselves
|
||||||
|
run: |
|
||||||
|
tox -e run_self
|
||||||
|
|
||||||
|
- name: Regenerate schema
|
||||||
|
run: |
|
||||||
|
tox -e generate_schema
|
||||||
|
git diff --exit-code
|
||||||
|
47
.github/workflows/primer.yml
vendored
47
.github/workflows/primer.yml
vendored
@ -1,47 +0,0 @@
|
|||||||
name: Primer
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths-ignore:
|
|
||||||
- "docs/**"
|
|
||||||
- "*.md"
|
|
||||||
|
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- "docs/**"
|
|
||||||
- "*.md"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
|
||||||
# by the push to the branch. Without this if check, checks are duplicated since
|
|
||||||
# internal PRs match both the push and pull_request events.
|
|
||||||
if:
|
|
||||||
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
|
|
||||||
github.repository
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
python-version: [3.6, 3.7, 3.8, 3.9]
|
|
||||||
os: [ubuntu-latest, windows-latest]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
|
||||||
uses: actions/setup-python@v2
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python-version }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
python -m pip install -e ".[d]"
|
|
||||||
|
|
||||||
- name: Primer run
|
|
||||||
env:
|
|
||||||
pythonioencoding: utf-8
|
|
||||||
run: |
|
|
||||||
black-primer
|
|
129
.github/workflows/pypi_upload.yml
vendored
129
.github/workflows/pypi_upload.yml
vendored
@ -1,31 +1,130 @@
|
|||||||
name: pypi_upload
|
name: Build and publish
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: created
|
types: [published]
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
main:
|
||||||
name: PyPI Upload
|
name: sdist + pure wheel
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up latest Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.13"
|
||||||
|
allow-prereleases: true
|
||||||
|
|
||||||
- name: Install latest pip, setuptools, twine + wheel
|
- name: Install latest pip, build, twine
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip setuptools twine wheel
|
python -m pip install --upgrade --disable-pip-version-check pip
|
||||||
|
python -m pip install --upgrade build twine
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheel and source distributions
|
||||||
run: |
|
run: python -m build
|
||||||
python setup.py bdist_wheel
|
|
||||||
python setup.py sdist
|
|
||||||
|
|
||||||
- name: Upload to PyPI via Twine
|
- if: github.event_name == 'release'
|
||||||
|
name: Upload to PyPI via Twine
|
||||||
env:
|
env:
|
||||||
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
||||||
|
run: twine upload --verbose -u '__token__' dist/*
|
||||||
|
|
||||||
|
generate_wheels_matrix:
|
||||||
|
name: generate wheels matrix
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
include: ${{ steps.set-matrix.outputs.include }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# Keep cibuildwheel version in sync with below
|
||||||
|
- name: Install cibuildwheel and pypyp
|
||||||
run: |
|
run: |
|
||||||
twine upload --verbose -u '__token__' dist/*
|
pipx install cibuildwheel==2.22.0
|
||||||
|
pipx install pypyp==1.3.0
|
||||||
|
- name: generate matrix
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
run: |
|
||||||
|
{
|
||||||
|
cibuildwheel --print-build-identifiers --platform linux \
|
||||||
|
| pyp 'json.dumps({"only": x, "os": "ubuntu-latest"})' \
|
||||||
|
&& cibuildwheel --print-build-identifiers --platform macos \
|
||||||
|
| pyp 'json.dumps({"only": x, "os": "macos-latest"})' \
|
||||||
|
&& cibuildwheel --print-build-identifiers --platform windows \
|
||||||
|
| pyp 'json.dumps({"only": x, "os": "windows-latest"})'
|
||||||
|
} | pyp 'json.dumps(list(map(json.loads, lines)))' > /tmp/matrix
|
||||||
|
env:
|
||||||
|
CIBW_ARCHS_LINUX: x86_64
|
||||||
|
CIBW_ARCHS_MACOS: x86_64 arm64
|
||||||
|
CIBW_ARCHS_WINDOWS: AMD64
|
||||||
|
- name: generate matrix (PR)
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
run: |
|
||||||
|
{
|
||||||
|
cibuildwheel --print-build-identifiers --platform linux \
|
||||||
|
| pyp 'json.dumps({"only": x, "os": "ubuntu-latest"})'
|
||||||
|
} | pyp 'json.dumps(list(map(json.loads, lines)))' > /tmp/matrix
|
||||||
|
env:
|
||||||
|
CIBW_BUILD: "cp39-* cp313-*"
|
||||||
|
CIBW_ARCHS_LINUX: x86_64
|
||||||
|
- id: set-matrix
|
||||||
|
run: echo "include=$(cat /tmp/matrix)" | tee -a $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
mypyc:
|
||||||
|
name: mypyc wheels ${{ matrix.only }}
|
||||||
|
needs: generate_wheels_matrix
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include: ${{ fromJson(needs.generate_wheels_matrix.outputs.include) }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# Keep cibuildwheel version in sync with above
|
||||||
|
- uses: pypa/cibuildwheel@v2.23.3
|
||||||
|
with:
|
||||||
|
only: ${{ matrix.only }}
|
||||||
|
|
||||||
|
- name: Upload wheels as workflow artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.only }}-mypyc-wheels
|
||||||
|
path: ./wheelhouse/*.whl
|
||||||
|
|
||||||
|
- if: github.event_name == 'release'
|
||||||
|
name: Upload wheels to PyPI via Twine
|
||||||
|
env:
|
||||||
|
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
||||||
|
run: pipx run twine upload --verbose -u '__token__' wheelhouse/*.whl
|
||||||
|
|
||||||
|
update-stable-branch:
|
||||||
|
name: Update stable branch
|
||||||
|
needs: [main, mypyc]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout stable branch
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: stable
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- if: github.event_name == 'release'
|
||||||
|
name: Update stable branch to release tag & push
|
||||||
|
run: |
|
||||||
|
git reset --hard ${{ github.event.release.tag_name }}
|
||||||
|
git push
|
||||||
|
56
.github/workflows/release_tests.yml
vendored
Normal file
56
.github/workflows/release_tests.yml
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
name: Release tool CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- .github/workflows/release_tests.yml
|
||||||
|
- release.py
|
||||||
|
- release_tests.py
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- .github/workflows/release_tests.yml
|
||||||
|
- release.py
|
||||||
|
- release_tests.py
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
||||||
|
# by the push to the branch. Without this if check, checks are duplicated since
|
||||||
|
# internal PRs match both the push and pull_request events.
|
||||||
|
if:
|
||||||
|
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
|
||||||
|
github.repository
|
||||||
|
|
||||||
|
name: Running python ${{ matrix.python-version }} on ${{matrix.os}}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.13"]
|
||||||
|
os: [macOS-latest, ubuntu-latest, windows-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# Give us all history, branches and tags
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
allow-prereleases: true
|
||||||
|
|
||||||
|
- name: Print Python Version
|
||||||
|
run: python --version --version && which python
|
||||||
|
|
||||||
|
- name: Print Git Version
|
||||||
|
run: git --version && which git
|
||||||
|
|
||||||
|
- name: Update pip, setuptools + wheels
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip setuptools wheel
|
||||||
|
|
||||||
|
- name: Run unit tests via coverage + print report
|
||||||
|
run: |
|
||||||
|
python -m pip install coverage
|
||||||
|
coverage run scripts/release_tests.py
|
||||||
|
coverage report --show-missing
|
78
.github/workflows/test.yml
vendored
78
.github/workflows/test.yml
vendored
@ -11,8 +11,15 @@ on:
|
|||||||
- "docs/**"
|
- "docs/**"
|
||||||
- "*.md"
|
- "*.md"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
main:
|
||||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
||||||
# by the push to the branch. Without this if check, checks are duplicated since
|
# by the push to the branch. Without this if check, checks are duplicated since
|
||||||
# internal PRs match both the push and pull_request events.
|
# internal PRs match both the push and pull_request events.
|
||||||
@ -24,35 +31,39 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.6, 3.7, 3.8, 3.9]
|
python-version: ["3.9", "3.10", "3.11", "3.12.4", "3.13", "pypy-3.9"]
|
||||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
allow-prereleases: true
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install tox
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install --upgrade tox
|
python -m pip install --upgrade tox
|
||||||
|
|
||||||
- name: Unit tests
|
- name: Unit tests
|
||||||
run: |
|
if: "!startsWith(matrix.python-version, 'pypy')"
|
||||||
tox -e ci-py -- -v --color=yes
|
run:
|
||||||
|
tox -e ci-py$(echo ${{ matrix.python-version }} | tr -d '.') -- -v --color=yes
|
||||||
|
|
||||||
- name: Publish coverage to Coveralls
|
- name: Unit tests (pypy)
|
||||||
# If pushed / is a pull request against main repo AND
|
if: "startsWith(matrix.python-version, 'pypy')"
|
||||||
|
run: tox -e ci-pypy3 -- -v --color=yes
|
||||||
|
|
||||||
|
- name: Upload coverage to Coveralls
|
||||||
|
# Upload coverage if we are on the main repository and
|
||||||
# we're running on Linux (this action only supports Linux)
|
# we're running on Linux (this action only supports Linux)
|
||||||
if:
|
if:
|
||||||
((github.event_name == 'push' && github.repository == 'psf/black') ||
|
github.repository == 'psf/black' && matrix.os == 'ubuntu-latest' &&
|
||||||
github.event.pull_request.base.repo.full_name == 'psf/black') && matrix.os ==
|
!startsWith(matrix.python-version, 'pypy')
|
||||||
'ubuntu-latest'
|
uses: AndreMiras/coveralls-python-action@ac868b9540fad490f7ca82b8ca00480fd751ed19
|
||||||
|
|
||||||
uses: AndreMiras/coveralls-python-action@v20201129
|
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
parallel: true
|
parallel: true
|
||||||
@ -60,17 +71,40 @@ jobs:
|
|||||||
debug: true
|
debug: true
|
||||||
|
|
||||||
coveralls-finish:
|
coveralls-finish:
|
||||||
needs: build
|
needs: main
|
||||||
# If pushed / is a pull request against main repo
|
if: github.repository == 'psf/black'
|
||||||
if:
|
|
||||||
(github.event_name == 'push' && github.repository == 'psf/black') ||
|
|
||||||
github.event.pull_request.base.repo.full_name == 'psf/black'
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Coveralls finished
|
- name: Send finished signal to Coveralls
|
||||||
uses: AndreMiras/coveralls-python-action@v20201129
|
uses: AndreMiras/coveralls-python-action@ac868b9540fad490f7ca82b8ca00480fd751ed19
|
||||||
with:
|
with:
|
||||||
parallel-finished: true
|
parallel-finished: true
|
||||||
debug: true
|
debug: true
|
||||||
|
|
||||||
|
uvloop:
|
||||||
|
if:
|
||||||
|
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
|
||||||
|
github.repository
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macOS-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up latest Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12.4"
|
||||||
|
|
||||||
|
- name: Install black with uvloop
|
||||||
|
run: |
|
||||||
|
python -m pip install pip --upgrade --disable-pip-version-check
|
||||||
|
python -m pip install -e ".[uvloop]"
|
||||||
|
|
||||||
|
- name: Format ourselves
|
||||||
|
run: python -m black --check src/ tests/
|
||||||
|
31
.github/workflows/upload_binary.yml
vendored
31
.github/workflows/upload_binary.yml
vendored
@ -1,22 +1,25 @@
|
|||||||
name: Upload self-contained binaries
|
name: Publish executables
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write # actions/upload-release-asset needs this.
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-2019, ubuntu-20.04, macos-latest]
|
os: [windows-2019, ubuntu-22.04, macos-latest]
|
||||||
include:
|
include:
|
||||||
- os: windows-2019
|
- os: windows-2019
|
||||||
pathsep: ";"
|
pathsep: ";"
|
||||||
asset_name: black_windows.exe
|
asset_name: black_windows.exe
|
||||||
executable_mime: "application/vnd.microsoft.portable-executable"
|
executable_mime: "application/vnd.microsoft.portable-executable"
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-22.04
|
||||||
pathsep: ":"
|
pathsep: ":"
|
||||||
asset_name: black_linux
|
asset_name: black_linux
|
||||||
executable_mime: "application/x-executable"
|
executable_mime: "application/x-executable"
|
||||||
@ -26,22 +29,28 @@ jobs:
|
|||||||
executable_mime: "application/x-mach-binary"
|
executable_mime: "application/x-mach-binary"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up latest Python
|
- name: Set up latest Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "*"
|
python-version: "3.12.4"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install Black and PyInstaller
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip wheel setuptools
|
python -m pip install --upgrade pip wheel
|
||||||
python -m pip install .
|
python -m pip install .[colorama]
|
||||||
python -m pip install pyinstaller
|
python -m pip install pyinstaller
|
||||||
|
|
||||||
- name: Build binary
|
- name: Build executable with PyInstaller
|
||||||
|
run: >
|
||||||
|
python -m PyInstaller -F --name ${{ matrix.asset_name }} --add-data
|
||||||
|
'src/blib2to3${{ matrix.pathsep }}blib2to3' src/black/__main__.py
|
||||||
|
|
||||||
|
- name: Quickly test executable
|
||||||
run: |
|
run: |
|
||||||
python -m PyInstaller -F --name ${{ matrix.asset_name }} --add-data 'src/blib2to3${{ matrix.pathsep }}blib2to3' src/black/__main__.py
|
./dist/${{ matrix.asset_name }} --version
|
||||||
|
./dist/${{ matrix.asset_name }} src --verbose
|
||||||
|
|
||||||
- name: Upload binary as release asset
|
- name: Upload binary as release asset
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
|
45
.github/workflows/uvloop_test.yml
vendored
45
.github/workflows/uvloop_test.yml
vendored
@ -1,45 +0,0 @@
|
|||||||
name: test uvloop
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths-ignore:
|
|
||||||
- "docs/**"
|
|
||||||
- "*.md"
|
|
||||||
|
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- "docs/**"
|
|
||||||
- "*.md"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
|
||||||
# by the push to the branch. Without this if check, checks are duplicated since
|
|
||||||
# internal PRs match both the push and pull_request events.
|
|
||||||
if:
|
|
||||||
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
|
|
||||||
github.repository
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macOS-latest]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
|
||||||
uses: actions/setup-python@v2
|
|
||||||
|
|
||||||
- name: Install latest pip
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
|
|
||||||
- name: Test uvloop Extra Install
|
|
||||||
run: |
|
|
||||||
python -m pip install -e ".[uvloop]"
|
|
||||||
|
|
||||||
- name: Primer uvloop run
|
|
||||||
run: |
|
|
||||||
black-primer
|
|
12
.gitignore
vendored
12
.gitignore
vendored
@ -4,17 +4,25 @@
|
|||||||
_build
|
_build
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.vscode
|
.vscode
|
||||||
|
.python-version
|
||||||
docs/_static/pypi.svg
|
docs/_static/pypi.svg
|
||||||
.tox
|
.tox
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|
||||||
|
# Packaging artifacts
|
||||||
black.egg-info
|
black.egg-info
|
||||||
|
black.dist-info
|
||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
pip-wheel-metadata/
|
pip-wheel-metadata/
|
||||||
|
.eggs
|
||||||
|
|
||||||
src/_black_version.py
|
src/_black_version.py
|
||||||
.idea
|
.idea
|
||||||
.eggs
|
|
||||||
.dmypy.json
|
.dmypy.json
|
||||||
*.swp
|
*.swp
|
||||||
.hypothesis/
|
.hypothesis/
|
||||||
venv/
|
venv/
|
||||||
|
.ipynb_checkpoints/
|
||||||
|
node_modules/
|
||||||
|
@ -1,30 +1,83 @@
|
|||||||
# Note: don't use this config for your own repositories. Instead, see
|
# Note: don't use this config for your own repositories. Instead, see
|
||||||
# "Version control integration" in README.md.
|
# "Version control integration" in docs/integrations/source_version_control.md
|
||||||
exclude: ^(src/blib2to3/|profiling/|tests/data/)
|
exclude: ^(profiling/|tests/data/)
|
||||||
repos:
|
repos:
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: check-pre-commit-rev-in-example
|
||||||
name: black
|
name: Check pre-commit rev in example
|
||||||
language: system
|
language: python
|
||||||
entry: black
|
entry: python -m scripts.check_pre_commit_rev_in_example
|
||||||
minimum_pre_commit_version: 2.9.2
|
files: '(CHANGES\.md|source_version_control\.md)$'
|
||||||
require_serial: true
|
additional_dependencies:
|
||||||
types_or: [python, pyi]
|
&version_check_dependencies [
|
||||||
|
commonmark==0.9.1,
|
||||||
|
pyyaml==6.0.1,
|
||||||
|
beautifulsoup4==4.9.3,
|
||||||
|
]
|
||||||
|
|
||||||
- repo: https://gitlab.com/pycqa/flake8
|
- id: check-version-in-the-basics-example
|
||||||
rev: 3.9.0
|
name: Check black version in the basics example
|
||||||
|
language: python
|
||||||
|
entry: python -m scripts.check_version_in_basics_example
|
||||||
|
files: '(CHANGES\.md|the_basics\.md)$'
|
||||||
|
additional_dependencies: *version_check_dependencies
|
||||||
|
|
||||||
|
- repo: https://github.com/pycqa/isort
|
||||||
|
rev: 6.0.1
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
|
||||||
|
- repo: https://github.com/pycqa/flake8
|
||||||
|
rev: 7.2.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies: [flake8-bugbear]
|
additional_dependencies:
|
||||||
|
- flake8-bugbear==24.2.6
|
||||||
|
- flake8-comprehensions
|
||||||
|
- flake8-simplify
|
||||||
|
exclude: ^src/blib2to3/
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v0.812
|
rev: v1.15.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
exclude: ^docs/conf.py
|
exclude: ^(docs/conf.py|scripts/generate_schema.py)$
|
||||||
|
args: []
|
||||||
|
additional_dependencies: &mypy_deps
|
||||||
|
- types-PyYAML
|
||||||
|
- types-atheris
|
||||||
|
- tomli >= 0.2.6, < 2.0.0
|
||||||
|
- click >= 8.2.0
|
||||||
|
# Click is intentionally out-of-sync with pyproject.toml
|
||||||
|
# v8.2 has breaking changes. We work around them at runtime, but we need the newer stubs.
|
||||||
|
- packaging >= 22.0
|
||||||
|
- platformdirs >= 2.1.0
|
||||||
|
- pytokens >= 0.1.10
|
||||||
|
- pytest
|
||||||
|
- hypothesis
|
||||||
|
- aiohttp >= 3.7.4
|
||||||
|
- types-commonmark
|
||||||
|
- urllib3
|
||||||
|
- hypothesmith
|
||||||
|
- id: mypy
|
||||||
|
name: mypy (Python 3.10)
|
||||||
|
files: scripts/generate_schema.py
|
||||||
|
args: ["--python-version=3.10"]
|
||||||
|
additional_dependencies: *mypy_deps
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
- repo: https://github.com/rbubley/mirrors-prettier
|
||||||
rev: v2.2.1
|
rev: v3.5.3
|
||||||
hooks:
|
hooks:
|
||||||
- id: prettier
|
- id: prettier
|
||||||
|
types_or: [markdown, yaml, json]
|
||||||
|
exclude: \.github/workflows/diff_shades\.yml
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v5.0.0
|
||||||
|
hooks:
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
|
|
||||||
|
ci:
|
||||||
|
autoupdate_schedule: quarterly
|
||||||
|
@ -1,9 +1,20 @@
|
|||||||
|
# Note that we recommend using https://github.com/psf/black-pre-commit-mirror instead
|
||||||
|
# This will work about 2x as fast as using the hooks in this repository
|
||||||
- id: black
|
- id: black
|
||||||
name: black
|
name: black
|
||||||
description: "Black: The uncompromising Python code formatter"
|
description: "Black: The uncompromising Python code formatter"
|
||||||
entry: black
|
entry: black
|
||||||
language: python
|
language: python
|
||||||
language_version: python3
|
|
||||||
minimum_pre_commit_version: 2.9.2
|
minimum_pre_commit_version: 2.9.2
|
||||||
require_serial: true
|
require_serial: true
|
||||||
types_or: [python, pyi]
|
types_or: [python, pyi]
|
||||||
|
- id: black-jupyter
|
||||||
|
name: black-jupyter
|
||||||
|
description:
|
||||||
|
"Black: The uncompromising Python code formatter (with Jupyter Notebook support)"
|
||||||
|
entry: black
|
||||||
|
language: python
|
||||||
|
minimum_pre_commit_version: 2.9.2
|
||||||
|
require_serial: true
|
||||||
|
types_or: [python, pyi, jupyter]
|
||||||
|
additional_dependencies: [".[jupyter]"]
|
||||||
|
@ -3,8 +3,12 @@ version: 2
|
|||||||
formats:
|
formats:
|
||||||
- htmlzip
|
- htmlzip
|
||||||
|
|
||||||
|
build:
|
||||||
|
os: ubuntu-22.04
|
||||||
|
tools:
|
||||||
|
python: "3.11"
|
||||||
|
|
||||||
python:
|
python:
|
||||||
version: 3.8
|
|
||||||
install:
|
install:
|
||||||
- requirements: docs/requirements.txt
|
- requirements: docs/requirements.txt
|
||||||
|
|
||||||
@ -12,3 +16,6 @@ python:
|
|||||||
path: .
|
path: .
|
||||||
extra_requirements:
|
extra_requirements:
|
||||||
- d
|
- d
|
||||||
|
|
||||||
|
sphinx:
|
||||||
|
configuration: docs/conf.py
|
||||||
|
26
AUTHORS.md
26
AUTHORS.md
@ -2,27 +2,36 @@
|
|||||||
|
|
||||||
Glued together by [Łukasz Langa](mailto:lukasz@langa.pl).
|
Glued together by [Łukasz Langa](mailto:lukasz@langa.pl).
|
||||||
|
|
||||||
Maintained with [Carol Willing](mailto:carolcode@willingconsulting.com),
|
Maintained with:
|
||||||
[Carl Meyer](mailto:carl@oddbird.net),
|
|
||||||
[Jelle Zijlstra](mailto:jelle.zijlstra@gmail.com),
|
- [Carol Willing](mailto:carolcode@willingconsulting.com)
|
||||||
[Mika Naylor](mailto:mail@autophagy.io),
|
- [Carl Meyer](mailto:carl@oddbird.net)
|
||||||
[Zsolt Dollenstein](mailto:zsol.zsol@gmail.com),
|
- [Jelle Zijlstra](mailto:jelle.zijlstra@gmail.com)
|
||||||
[Cooper Lees](mailto:me@cooperlees.com), and Richard Si.
|
- [Mika Naylor](mailto:mail@autophagy.io)
|
||||||
|
- [Zsolt Dollenstein](mailto:zsol.zsol@gmail.com)
|
||||||
|
- [Cooper Lees](mailto:me@cooperlees.com)
|
||||||
|
- [Richard Si](mailto:sichard26@gmail.com)
|
||||||
|
- [Felix Hildén](mailto:felix.hilden@gmail.com)
|
||||||
|
- [Batuhan Taskaya](mailto:batuhan@python.org)
|
||||||
|
- [Shantanu Jain](mailto:hauntsaninja@gmail.com)
|
||||||
|
|
||||||
Multiple contributions by:
|
Multiple contributions by:
|
||||||
|
|
||||||
- [Abdur-Rahmaan Janhangeer](mailto:arj.python@gmail.com)
|
- [Abdur-Rahmaan Janhangeer](mailto:arj.python@gmail.com)
|
||||||
- [Adam Johnson](mailto:me@adamj.eu)
|
- [Adam Johnson](mailto:me@adamj.eu)
|
||||||
- [Adam Williamson](mailto:adamw@happyassassin.net)
|
- [Adam Williamson](mailto:adamw@happyassassin.net)
|
||||||
- [Alexander Huynh](mailto:github@grande.coffee)
|
- [Alexander Huynh](mailto:ahrex-gh-psf-black@e.sc)
|
||||||
|
- [Alexandr Artemyev](mailto:mogost@gmail.com)
|
||||||
- [Alex Vandiver](mailto:github@chmrr.net)
|
- [Alex Vandiver](mailto:github@chmrr.net)
|
||||||
- [Allan Simon](mailto:allan.simon@supinfo.com)
|
- [Allan Simon](mailto:allan.simon@supinfo.com)
|
||||||
- Anders-Petter Ljungquist
|
- Anders-Petter Ljungquist
|
||||||
|
- [Amethyst Reese](mailto:amy@n7.gg)
|
||||||
- [Andrew Thorp](mailto:andrew.thorp.dev@gmail.com)
|
- [Andrew Thorp](mailto:andrew.thorp.dev@gmail.com)
|
||||||
- [Andrew Zhou](mailto:andrewfzhou@gmail.com)
|
- [Andrew Zhou](mailto:andrewfzhou@gmail.com)
|
||||||
- [Andrey](mailto:dyuuus@yandex.ru)
|
- [Andrey](mailto:dyuuus@yandex.ru)
|
||||||
- [Andy Freeland](mailto:andy@andyfreeland.net)
|
- [Andy Freeland](mailto:andy@andyfreeland.net)
|
||||||
- [Anthony Sottile](mailto:asottile@umich.edu)
|
- [Anthony Sottile](mailto:asottile@umich.edu)
|
||||||
|
- [Antonio Ossa Guerra](mailto:aaossa+black@uc.cl)
|
||||||
- [Arjaan Buijk](mailto:arjaan.buijk@gmail.com)
|
- [Arjaan Buijk](mailto:arjaan.buijk@gmail.com)
|
||||||
- [Arnav Borbornah](mailto:arnavborborah11@gmail.com)
|
- [Arnav Borbornah](mailto:arnavborborah11@gmail.com)
|
||||||
- [Artem Malyshev](mailto:proofit404@gmail.com)
|
- [Artem Malyshev](mailto:proofit404@gmail.com)
|
||||||
@ -73,6 +82,7 @@ Multiple contributions by:
|
|||||||
- [Hugo Barrera](mailto::hugo@barrera.io)
|
- [Hugo Barrera](mailto::hugo@barrera.io)
|
||||||
- Hugo van Kemenade
|
- Hugo van Kemenade
|
||||||
- [Hynek Schlawack](mailto:hs@ox.cx)
|
- [Hynek Schlawack](mailto:hs@ox.cx)
|
||||||
|
- [Ionite](mailto:dev@ionite.io)
|
||||||
- [Ivan Katanić](mailto:ivan.katanic@gmail.com)
|
- [Ivan Katanić](mailto:ivan.katanic@gmail.com)
|
||||||
- [Jakub Kadlubiec](mailto:jakub.kadlubiec@skyscanner.net)
|
- [Jakub Kadlubiec](mailto:jakub.kadlubiec@skyscanner.net)
|
||||||
- [Jakub Warczarek](mailto:jakub.warczarek@gmail.com)
|
- [Jakub Warczarek](mailto:jakub.warczarek@gmail.com)
|
||||||
@ -143,6 +153,7 @@ Multiple contributions by:
|
|||||||
- [Rishikesh Jha](mailto:rishijha424@gmail.com)
|
- [Rishikesh Jha](mailto:rishijha424@gmail.com)
|
||||||
- [Rupert Bedford](mailto:rupert@rupertb.com)
|
- [Rupert Bedford](mailto:rupert@rupertb.com)
|
||||||
- Russell Davis
|
- Russell Davis
|
||||||
|
- [Sagi Shadur](mailto:saroad2@gmail.com)
|
||||||
- [Rémi Verschelde](mailto:rverschelde@gmail.com)
|
- [Rémi Verschelde](mailto:rverschelde@gmail.com)
|
||||||
- [Sami Salonen](mailto:sakki@iki.fi)
|
- [Sami Salonen](mailto:sakki@iki.fi)
|
||||||
- [Samuel Cormier-Iijima](mailto:samuel@cormier-iijima.com)
|
- [Samuel Cormier-Iijima](mailto:samuel@cormier-iijima.com)
|
||||||
@ -170,6 +181,7 @@ Multiple contributions by:
|
|||||||
- [Tony Narlock](mailto:tony@git-pull.com)
|
- [Tony Narlock](mailto:tony@git-pull.com)
|
||||||
- [Tsuyoshi Hombashi](mailto:tsuyoshi.hombashi@gmail.com)
|
- [Tsuyoshi Hombashi](mailto:tsuyoshi.hombashi@gmail.com)
|
||||||
- [Tushar Chandra](mailto:tusharchandra2018@u.northwestern.edu)
|
- [Tushar Chandra](mailto:tusharchandra2018@u.northwestern.edu)
|
||||||
|
- [Tushar Sadhwani](mailto:tushar.sadhwani000@gmail.com)
|
||||||
- [Tzu-ping Chung](mailto:uranusjr@gmail.com)
|
- [Tzu-ping Chung](mailto:uranusjr@gmail.com)
|
||||||
- [Utsav Shah](mailto:ukshah2@illinois.edu)
|
- [Utsav Shah](mailto:ukshah2@illinois.edu)
|
||||||
- utsav-dbx
|
- utsav-dbx
|
||||||
|
1324
CHANGES.md
1324
CHANGES.md
File diff suppressed because it is too large
Load Diff
22
CITATION.cff
Normal file
22
CITATION.cff
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
cff-version: 1.2.0
|
||||||
|
title: "Black: The uncompromising Python code formatter"
|
||||||
|
message: >-
|
||||||
|
If you use this software, please cite it using the metadata from this file.
|
||||||
|
type: software
|
||||||
|
authors:
|
||||||
|
- family-names: Langa
|
||||||
|
given-names: Łukasz
|
||||||
|
- name: "contributors to Black"
|
||||||
|
repository-code: "https://github.com/psf/black"
|
||||||
|
url: "https://black.readthedocs.io/en/stable/"
|
||||||
|
abstract: >-
|
||||||
|
Black is the uncompromising Python code formatter. By using it, you agree to cede
|
||||||
|
control over minutiae of hand-formatting. In return, Black gives you speed,
|
||||||
|
determinism, and freedom from pycodestyle nagging about formatting. You will save time
|
||||||
|
and mental energy for more important matters.
|
||||||
|
|
||||||
|
Blackened code looks the same regardless of the project you're reading. Formatting
|
||||||
|
becomes transparent after a while and you can focus on the content instead.
|
||||||
|
|
||||||
|
Black makes code review faster by producing the smallest diffs possible.
|
||||||
|
license: MIT
|
@ -1,10 +1,13 @@
|
|||||||
# Contributing to _Black_
|
# Contributing to _Black_
|
||||||
|
|
||||||
Welcome! Happy to see you willing to make the project better. Have you read the entire
|
Welcome future contributor! We're happy to see you willing to make the project better.
|
||||||
[user documentation](https://black.readthedocs.io/en/latest/) yet?
|
|
||||||
|
|
||||||
Our [contributing documentation](https://black.readthedocs.org/en/latest/contributing/)
|
If you aren't familiar with _Black_, or are looking for documentation on something
|
||||||
contains details on all you need to know about contributing to _Black_, the basics to
|
specific, the [user documentation](https://black.readthedocs.io/en/latest/) is the best
|
||||||
the internals of _Black_.
|
place to look.
|
||||||
|
|
||||||
We look forward to your contributions!
|
For getting started on contributing, please read the
|
||||||
|
[contributing documentation](https://black.readthedocs.org/en/latest/contributing/) for
|
||||||
|
all you need to know.
|
||||||
|
|
||||||
|
Thank you, and we look forward to your contributions!
|
||||||
|
28
Dockerfile
28
Dockerfile
@ -1,14 +1,22 @@
|
|||||||
FROM python:3-slim
|
FROM python:3.12-slim AS builder
|
||||||
|
|
||||||
RUN mkdir /src
|
RUN mkdir /src
|
||||||
COPY . /src/
|
COPY . /src/
|
||||||
RUN pip install --no-cache-dir --upgrade pip setuptools wheel \
|
ENV VIRTUAL_ENV=/opt/venv
|
||||||
&& apt update && apt install -y git \
|
ENV HATCH_BUILD_HOOKS_ENABLE=1
|
||||||
&& cd /src \
|
# Install build tools to compile black + dependencies
|
||||||
&& pip install --no-cache-dir .[colorama,d] \
|
RUN apt update && apt install -y build-essential git python3-dev
|
||||||
&& rm -rf /src \
|
RUN python -m venv $VIRTUAL_ENV
|
||||||
&& apt remove -y git \
|
RUN python -m pip install --no-cache-dir hatch hatch-fancy-pypi-readme hatch-vcs
|
||||||
&& apt autoremove -y \
|
RUN . /opt/venv/bin/activate && pip install --no-cache-dir --upgrade pip setuptools \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& cd /src && hatch build -t wheel \
|
||||||
|
&& pip install --no-cache-dir dist/*-cp* \
|
||||||
|
&& pip install black[colorama,d,uvloop]
|
||||||
|
|
||||||
CMD ["black"]
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
# copy only Python packages to limit the image size
|
||||||
|
COPY --from=builder /opt/venv /opt/venv
|
||||||
|
ENV PATH="/opt/venv/bin:$PATH"
|
||||||
|
|
||||||
|
CMD ["/opt/venv/bin/black"]
|
||||||
|
36
Pipfile
36
Pipfile
@ -1,36 +0,0 @@
|
|||||||
[[source]]
|
|
||||||
name = "pypi"
|
|
||||||
url = "https://pypi.python.org/simple"
|
|
||||||
verify_ssl = true
|
|
||||||
|
|
||||||
[dev-packages]
|
|
||||||
Sphinx = ">=3.1.2"
|
|
||||||
coverage = "*"
|
|
||||||
docutils = "==0.15" # not a direct dependency, see https://github.com/pypa/pipenv/issues/3865
|
|
||||||
flake8 = "*"
|
|
||||||
flake8-bugbear = "*"
|
|
||||||
mypy = ">=0.812"
|
|
||||||
pre-commit = "*"
|
|
||||||
readme_renderer = "*"
|
|
||||||
MyST-Parser = ">=0.13.7"
|
|
||||||
sphinxcontrib-programoutput = ">=0.17"
|
|
||||||
sphinx-copybutton = ">=0.3.0"
|
|
||||||
setuptools = ">=39.2.0"
|
|
||||||
setuptools-scm = "*"
|
|
||||||
twine = ">=1.11.0"
|
|
||||||
wheel = ">=0.31.1"
|
|
||||||
black = {editable = true, extras = ["d"], path = "."}
|
|
||||||
|
|
||||||
[packages]
|
|
||||||
aiohttp = ">=3.6.0"
|
|
||||||
aiohttp-cors = ">=0.4.0"
|
|
||||||
appdirs = "*"
|
|
||||||
click = ">=7.1.2"
|
|
||||||
mypy_extensions = ">=0.4.3"
|
|
||||||
pathspec = ">=0.8.1"
|
|
||||||
regex = ">=2020.1.8"
|
|
||||||
toml = ">=0.10.1"
|
|
||||||
typed-ast = "==1.4.2"
|
|
||||||
typing_extensions = {"python_version <" = "3.8","version >=" = "3.7.4"}
|
|
||||||
black = {editable = true,extras = ["d"],path = "."}
|
|
||||||
dataclasses = {"python_version <" = "3.7","version >" = "0.6"}
|
|
1262
Pipfile.lock
generated
1262
Pipfile.lock
generated
File diff suppressed because it is too large
Load Diff
53
README.md
53
README.md
@ -1,15 +1,14 @@
|
|||||||

|
[](https://black.readthedocs.io/en/stable/)
|
||||||
|
|
||||||
<h2 align="center">The Uncompromising Code Formatter</h2>
|
<h2 align="center">The Uncompromising Code Formatter</h2>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/psf/black/actions"><img alt="Actions Status" src="https://github.com/psf/black/workflows/Test/badge.svg"></a>
|
<a href="https://github.com/psf/black/actions"><img alt="Actions Status" src="https://github.com/psf/black/workflows/Test/badge.svg"></a>
|
||||||
<a href="https://github.com/psf/black/actions"><img alt="Actions Status" src="https://github.com/psf/black/workflows/Primer/badge.svg"></a>
|
|
||||||
<a href="https://black.readthedocs.io/en/stable/?badge=stable"><img alt="Documentation Status" src="https://readthedocs.org/projects/black/badge/?version=stable"></a>
|
<a href="https://black.readthedocs.io/en/stable/?badge=stable"><img alt="Documentation Status" src="https://readthedocs.org/projects/black/badge/?version=stable"></a>
|
||||||
<a href="https://coveralls.io/github/psf/black?branch=main"><img alt="Coverage Status" src="https://coveralls.io/repos/github/psf/black/badge.svg?branch=main"></a>
|
<a href="https://coveralls.io/github/psf/black?branch=main"><img alt="Coverage Status" src="https://coveralls.io/repos/github/psf/black/badge.svg?branch=main"></a>
|
||||||
<a href="https://github.com/psf/black/blob/main/LICENSE"><img alt="License: MIT" src="https://black.readthedocs.io/en/stable/_static/license.svg"></a>
|
<a href="https://github.com/psf/black/blob/main/LICENSE"><img alt="License: MIT" src="https://black.readthedocs.io/en/stable/_static/license.svg"></a>
|
||||||
<a href="https://pypi.org/project/black/"><img alt="PyPI" src="https://img.shields.io/pypi/v/black"></a>
|
<a href="https://pypi.org/project/black/"><img alt="PyPI" src="https://img.shields.io/pypi/v/black"></a>
|
||||||
<a href="https://pepy.tech/project/black"><img alt="Downloads" src="https://pepy.tech/badge/black"></a>
|
<a href="https://pepy.tech/project/black"><img alt="Downloads" src="https://static.pepy.tech/badge/black"></a>
|
||||||
<a href="https://anaconda.org/conda-forge/black/"><img alt="conda-forge" src="https://img.shields.io/conda/dn/conda-forge/black.svg?label=conda-forge"></a>
|
<a href="https://anaconda.org/conda-forge/black/"><img alt="conda-forge" src="https://img.shields.io/conda/dn/conda-forge/black.svg?label=conda-forge"></a>
|
||||||
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
|
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
|
||||||
</p>
|
</p>
|
||||||
@ -39,13 +38,12 @@ Try it out now using the [Black Playground](https://black.vercel.app). Watch the
|
|||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
_Black_ can be installed by running `pip install black`. It requires Python 3.6.2+ to
|
_Black_ can be installed by running `pip install black`. It requires Python 3.9+ to run.
|
||||||
run. If you want to format Python 2 code as well, install with
|
If you want to format Jupyter Notebooks, install with `pip install "black[jupyter]"`.
|
||||||
`pip install black[python2]`.
|
|
||||||
|
|
||||||
If you can't wait for the latest _hotness_ and want to install from GitHub, use:
|
If you can't wait for the latest _hotness_ and want to install from GitHub, use:
|
||||||
|
|
||||||
`pip install git+git://github.com/psf/black`
|
`pip install git+https://github.com/psf/black`
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
@ -65,16 +63,13 @@ Further information can be found in our docs:
|
|||||||
|
|
||||||
- [Usage and Configuration](https://black.readthedocs.io/en/stable/usage_and_configuration/index.html)
|
- [Usage and Configuration](https://black.readthedocs.io/en/stable/usage_and_configuration/index.html)
|
||||||
|
|
||||||
### NOTE: This is a beta product
|
|
||||||
|
|
||||||
_Black_ is already [successfully used](https://github.com/psf/black#used-by) by many
|
_Black_ is already [successfully used](https://github.com/psf/black#used-by) by many
|
||||||
projects, small and big. Black has a comprehensive test suite, with efficient parallel
|
projects, small and big. _Black_ has a comprehensive test suite, with efficient parallel
|
||||||
tests, and our own auto formatting and parallel Continuous Integration runner. However,
|
tests, and our own auto formatting and parallel Continuous Integration runner. Now that
|
||||||
_Black_ is still beta. Things will probably be wonky for a while. This is made explicit
|
we have become stable, you should not expect large formatting changes in the future.
|
||||||
by the "Beta" trove classifier, as well as by the "b" in the version number. What this
|
Stylistic changes will mostly be responses to bug reports and support for new Python
|
||||||
means for you is that **until the formatter becomes stable, you should expect some
|
syntax. For more information please refer to
|
||||||
formatting to change in the future**. That being said, no drastic stylistic changes are
|
[The Black Code Style](https://black.readthedocs.io/en/stable/the_black_code_style/index.html).
|
||||||
planned, mostly responses to bug reports.
|
|
||||||
|
|
||||||
Also, as a safety measure which slows down processing, _Black_ will check that the
|
Also, as a safety measure which slows down processing, _Black_ will check that the
|
||||||
reformatted code still produces a valid AST that is effectively equivalent to the
|
reformatted code still produces a valid AST that is effectively equivalent to the
|
||||||
@ -86,14 +81,20 @@ section for details). If you're feeling confident, use `--fast`.
|
|||||||
|
|
||||||
_Black_ is a PEP 8 compliant opinionated formatter. _Black_ reformats entire files in
|
_Black_ is a PEP 8 compliant opinionated formatter. _Black_ reformats entire files in
|
||||||
place. Style configuration options are deliberately limited and rarely added. It doesn't
|
place. Style configuration options are deliberately limited and rarely added. It doesn't
|
||||||
take previous formatting into account (see [Pragmatism](#pragmatism) for exceptions).
|
take previous formatting into account (see
|
||||||
|
[Pragmatism](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#pragmatism)
|
||||||
|
for exceptions).
|
||||||
|
|
||||||
Our documentation covers the current _Black_ code style, but planned changes to it are
|
Our documentation covers the current _Black_ code style, but planned changes to it are
|
||||||
also documented. They're both worth taking a look:
|
also documented. They're both worth taking a look at:
|
||||||
|
|
||||||
- [The _Black_ Code Style: Current style](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html)
|
- [The _Black_ Code Style: Current style](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html)
|
||||||
- [The _Black_ Code Style: Future style](https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html)
|
- [The _Black_ Code Style: Future style](https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html)
|
||||||
|
|
||||||
|
Changes to the _Black_ code style are bound by the Stability Policy:
|
||||||
|
|
||||||
|
- [The _Black_ Code Style: Stability Policy](https://black.readthedocs.io/en/stable/the_black_code_style/index.html#stability-policy)
|
||||||
|
|
||||||
Please refer to this document before submitting an issue. What seems like a bug might be
|
Please refer to this document before submitting an issue. What seems like a bug might be
|
||||||
intended behaviour.
|
intended behaviour.
|
||||||
|
|
||||||
@ -131,11 +132,13 @@ code in compliance with many other _Black_ formatted projects.
|
|||||||
## Used by
|
## Used by
|
||||||
|
|
||||||
The following notable open-source projects trust _Black_ with enforcing a consistent
|
The following notable open-source projects trust _Black_ with enforcing a consistent
|
||||||
code style: pytest, tox, Pyramid, Django Channels, Hypothesis, attrs, SQLAlchemy,
|
code style: pytest, tox, Pyramid, Django, Django Channels, Hypothesis, attrs,
|
||||||
Poetry, PyPA applications (Warehouse, Bandersnatch, Pipenv, virtualenv), pandas, Pillow,
|
SQLAlchemy, Poetry, PyPA applications (Warehouse, Bandersnatch, Pipenv, virtualenv),
|
||||||
every Datadog Agent Integration, Home Assistant, Zulip.
|
pandas, Pillow, Twisted, LocalStack, every Datadog Agent Integration, Home Assistant,
|
||||||
|
Zulip, Kedro, OpenOA, FLORIS, ORBIT, WOMBAT, and many more.
|
||||||
|
|
||||||
The following organizations use _Black_: Facebook, Dropbox, Mozilla, Quora.
|
The following organizations use _Black_: Dropbox, KeepTruckin, Lyft, Mozilla, Quora,
|
||||||
|
Duolingo, QuantumBlack, Tesla, Archer Aviation.
|
||||||
|
|
||||||
Are we missing anyone? Let us know.
|
Are we missing anyone? Let us know.
|
||||||
|
|
||||||
@ -162,8 +165,8 @@ Twisted and CPython:
|
|||||||
|
|
||||||
> At least the name is good.
|
> At least the name is good.
|
||||||
|
|
||||||
**Kenneth Reitz**, creator of [`requests`](http://python-requests.org/) and
|
**Kenneth Reitz**, creator of [`requests`](https://requests.readthedocs.io/en/latest/)
|
||||||
[`pipenv`](https://readthedocs.org/projects/pipenv/):
|
and [`pipenv`](https://readthedocs.org/projects/pipenv/):
|
||||||
|
|
||||||
> This vastly improves the formatting of our code. Thanks a ton!
|
> This vastly improves the formatting of our code. Thanks a ton!
|
||||||
|
|
||||||
@ -200,7 +203,7 @@ You can also take a look at the rest of the contributing docs or talk with the
|
|||||||
developers:
|
developers:
|
||||||
|
|
||||||
- [Contributing documentation](https://black.readthedocs.io/en/latest/contributing/index.html)
|
- [Contributing documentation](https://black.readthedocs.io/en/latest/contributing/index.html)
|
||||||
- [IRC channel on Freenode](https://webchat.freenode.net/?channels=%23blackformatter)
|
- [Chat on Discord](https://discord.gg/RtVdv86PrH)
|
||||||
|
|
||||||
## Change log
|
## Change log
|
||||||
|
|
||||||
|
11
SECURITY.md
Normal file
11
SECURITY.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Only the latest non-prerelease version is supported.
|
||||||
|
|
||||||
|
## Security contact information
|
||||||
|
|
||||||
|
To report a security vulnerability, please use the
|
||||||
|
[Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the
|
||||||
|
fix and disclosure.
|
56
action.yml
56
action.yml
@ -5,13 +5,18 @@ inputs:
|
|||||||
options:
|
options:
|
||||||
description:
|
description:
|
||||||
"Options passed to Black. Use `black --help` to see available options. Default:
|
"Options passed to Black. Use `black --help` to see available options. Default:
|
||||||
'--check'"
|
'--check --diff'"
|
||||||
required: false
|
required: false
|
||||||
default: "--check --diff"
|
default: "--check --diff"
|
||||||
src:
|
src:
|
||||||
description: "Source to run Black. Default: '.'"
|
description: "Source to run Black. Default: '.'"
|
||||||
required: false
|
required: false
|
||||||
default: "."
|
default: "."
|
||||||
|
jupyter:
|
||||||
|
description:
|
||||||
|
"Set this option to true to include Jupyter Notebook files. Default: false"
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
black_args:
|
black_args:
|
||||||
description: "[DEPRECATED] Black input arguments."
|
description: "[DEPRECATED] Black input arguments."
|
||||||
required: false
|
required: false
|
||||||
@ -22,38 +27,53 @@ inputs:
|
|||||||
description: 'Python Version specifier (PEP440) - e.g. "21.5b1"'
|
description: 'Python Version specifier (PEP440) - e.g. "21.5b1"'
|
||||||
required: false
|
required: false
|
||||||
default: ""
|
default: ""
|
||||||
|
use_pyproject:
|
||||||
|
description: Read Black version specifier from pyproject.toml if `true`.
|
||||||
|
required: false
|
||||||
|
default: "false"
|
||||||
|
summary:
|
||||||
|
description: "Whether to add the output to the workflow summary"
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
branding:
|
branding:
|
||||||
color: "black"
|
color: "black"
|
||||||
icon: "check-circle"
|
icon: "check-circle"
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- run: |
|
- name: black
|
||||||
# Exists since using github.action_path + path to main script doesn't work because bash
|
run: |
|
||||||
# interprets the backslashes in github.action_path (which are used when the runner OS
|
# Even when black fails, do not close the shell
|
||||||
# is Windows) destroying the path to the target file.
|
set +e
|
||||||
#
|
|
||||||
# Also semicolons are necessary because I can't get the newlines to work
|
|
||||||
entrypoint="import sys;
|
|
||||||
import subprocess;
|
|
||||||
from pathlib import Path;
|
|
||||||
|
|
||||||
MAIN_SCRIPT = Path(r'${{ github.action_path }}') / 'action' / 'main.py';
|
|
||||||
|
|
||||||
proc = subprocess.run([sys.executable, str(MAIN_SCRIPT)]);
|
|
||||||
sys.exit(proc.returncode)
|
|
||||||
"
|
|
||||||
|
|
||||||
if [ "$RUNNER_OS" == "Windows" ]; then
|
if [ "$RUNNER_OS" == "Windows" ]; then
|
||||||
echo $entrypoint | python
|
runner="python"
|
||||||
else
|
else
|
||||||
echo $entrypoint | python3
|
runner="python3"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
out=$(${runner} $GITHUB_ACTION_PATH/action/main.py)
|
||||||
|
exit_code=$?
|
||||||
|
|
||||||
|
# Display the raw output in the step
|
||||||
|
echo "${out}"
|
||||||
|
|
||||||
|
if [ "${{ inputs.summary }}" == "true" ]; then
|
||||||
|
# Display the Markdown output in the job summary
|
||||||
|
echo "\`\`\`python" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "${out}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit with the exit-code returned by Black
|
||||||
|
exit ${exit_code}
|
||||||
env:
|
env:
|
||||||
# TODO: Remove once https://github.com/actions/runner/issues/665 is fixed.
|
# TODO: Remove once https://github.com/actions/runner/issues/665 is fixed.
|
||||||
INPUT_OPTIONS: ${{ inputs.options }}
|
INPUT_OPTIONS: ${{ inputs.options }}
|
||||||
INPUT_SRC: ${{ inputs.src }}
|
INPUT_SRC: ${{ inputs.src }}
|
||||||
|
INPUT_JUPYTER: ${{ inputs.jupyter }}
|
||||||
INPUT_BLACK_ARGS: ${{ inputs.black_args }}
|
INPUT_BLACK_ARGS: ${{ inputs.black_args }}
|
||||||
INPUT_VERSION: ${{ inputs.version }}
|
INPUT_VERSION: ${{ inputs.version }}
|
||||||
|
INPUT_USE_PYPROJECT: ${{ inputs.use_pyproject }}
|
||||||
pythonioencoding: utf-8
|
pythonioencoding: utf-8
|
||||||
shell: bash
|
shell: bash
|
||||||
|
159
action/main.py
159
action/main.py
@ -1,39 +1,182 @@
|
|||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import run, PIPE, STDOUT
|
from subprocess import PIPE, STDOUT, run
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
ACTION_PATH = Path(os.environ["GITHUB_ACTION_PATH"])
|
ACTION_PATH = Path(os.environ["GITHUB_ACTION_PATH"])
|
||||||
ENV_PATH = ACTION_PATH / ".black-env"
|
ENV_PATH = ACTION_PATH / ".black-env"
|
||||||
ENV_BIN = ENV_PATH / ("Scripts" if sys.platform == "win32" else "bin")
|
ENV_BIN = ENV_PATH / ("Scripts" if sys.platform == "win32" else "bin")
|
||||||
OPTIONS = os.getenv("INPUT_OPTIONS", default="")
|
OPTIONS = os.getenv("INPUT_OPTIONS", default="")
|
||||||
SRC = os.getenv("INPUT_SRC", default="")
|
SRC = os.getenv("INPUT_SRC", default="")
|
||||||
|
JUPYTER = os.getenv("INPUT_JUPYTER") == "true"
|
||||||
BLACK_ARGS = os.getenv("INPUT_BLACK_ARGS", default="")
|
BLACK_ARGS = os.getenv("INPUT_BLACK_ARGS", default="")
|
||||||
VERSION = os.getenv("INPUT_VERSION", default="")
|
VERSION = os.getenv("INPUT_VERSION", default="")
|
||||||
|
USE_PYPROJECT = os.getenv("INPUT_USE_PYPROJECT") == "true"
|
||||||
|
|
||||||
|
BLACK_VERSION_RE = re.compile(r"^black([^A-Z0-9._-]+.*)$", re.IGNORECASE)
|
||||||
|
EXTRAS_RE = re.compile(r"\[.*\]")
|
||||||
|
EXPORT_SUBST_FAIL_RE = re.compile(r"\$Format:.*\$")
|
||||||
|
|
||||||
|
|
||||||
|
def determine_version_specifier() -> str:
|
||||||
|
"""Determine the version of Black to install.
|
||||||
|
|
||||||
|
The version can be specified either via the `with.version` input or via the
|
||||||
|
pyproject.toml file if `with.use_pyproject` is set to `true`.
|
||||||
|
"""
|
||||||
|
if USE_PYPROJECT and VERSION:
|
||||||
|
print(
|
||||||
|
"::error::'with.version' and 'with.use_pyproject' inputs are "
|
||||||
|
"mutually exclusive.",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
if USE_PYPROJECT:
|
||||||
|
return read_version_specifier_from_pyproject()
|
||||||
|
elif VERSION and VERSION[0] in "0123456789":
|
||||||
|
return f"=={VERSION}"
|
||||||
|
else:
|
||||||
|
return VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def read_version_specifier_from_pyproject() -> str:
|
||||||
|
if sys.version_info < (3, 11):
|
||||||
|
print(
|
||||||
|
"::error::'with.use_pyproject' input requires Python 3.11 or later.",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
import tomllib # type: ignore[import-not-found,unreachable]
|
||||||
|
|
||||||
|
try:
|
||||||
|
with Path("pyproject.toml").open("rb") as fp:
|
||||||
|
pyproject = tomllib.load(fp)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(
|
||||||
|
"::error::'with.use_pyproject' input requires a pyproject.toml file.",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
version = pyproject.get("tool", {}).get("black", {}).get("required-version")
|
||||||
|
if version is not None:
|
||||||
|
return f"=={version}"
|
||||||
|
|
||||||
|
arrays = [
|
||||||
|
*pyproject.get("dependency-groups", {}).values(),
|
||||||
|
pyproject.get("project", {}).get("dependencies"),
|
||||||
|
*pyproject.get("project", {}).get("optional-dependencies", {}).values(),
|
||||||
|
]
|
||||||
|
for array in arrays:
|
||||||
|
version = find_black_version_in_array(array)
|
||||||
|
if version is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
if version is None:
|
||||||
|
print(
|
||||||
|
"::error::'black' dependency missing from pyproject.toml.",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return version
|
||||||
|
|
||||||
|
|
||||||
|
def find_black_version_in_array(array: object) -> Union[str, None]:
|
||||||
|
if not isinstance(array, list):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
for item in array:
|
||||||
|
# Rudimentary PEP 508 parsing.
|
||||||
|
item = item.split(";")[0]
|
||||||
|
item = EXTRAS_RE.sub("", item).strip()
|
||||||
|
if item == "black":
|
||||||
|
print(
|
||||||
|
"::error::Version specifier missing for 'black' dependency in "
|
||||||
|
"pyproject.toml.",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
elif m := BLACK_VERSION_RE.match(item):
|
||||||
|
return m.group(1).strip()
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
run([sys.executable, "-m", "venv", str(ENV_PATH)], check=True)
|
run([sys.executable, "-m", "venv", str(ENV_PATH)], check=True)
|
||||||
|
|
||||||
req = "black[colorama,python2]"
|
version_specifier = determine_version_specifier()
|
||||||
if VERSION:
|
if JUPYTER:
|
||||||
req += f"=={VERSION}"
|
extra_deps = "[colorama,jupyter]"
|
||||||
|
else:
|
||||||
|
extra_deps = "[colorama]"
|
||||||
|
if version_specifier:
|
||||||
|
req = f"black{extra_deps}{version_specifier}"
|
||||||
|
else:
|
||||||
|
describe_name = ""
|
||||||
|
with open(ACTION_PATH / ".git_archival.txt", encoding="utf-8") as fp:
|
||||||
|
for line in fp:
|
||||||
|
if line.startswith("describe-name: "):
|
||||||
|
describe_name = line[len("describe-name: ") :].rstrip()
|
||||||
|
break
|
||||||
|
if not describe_name:
|
||||||
|
print("::error::Failed to detect action version.", file=sys.stderr, flush=True)
|
||||||
|
sys.exit(1)
|
||||||
|
# expected format is one of:
|
||||||
|
# - 23.1.0
|
||||||
|
# - 23.1.0-51-g448bba7
|
||||||
|
# - $Format:%(describe:tags=true,match=*[0-9]*)$ (if export-subst fails)
|
||||||
|
if (
|
||||||
|
describe_name.count("-") < 2
|
||||||
|
and EXPORT_SUBST_FAIL_RE.match(describe_name) is None
|
||||||
|
):
|
||||||
|
# the action's commit matches a tag exactly, install exact version from PyPI
|
||||||
|
req = f"black{extra_deps}=={describe_name}"
|
||||||
|
else:
|
||||||
|
# the action's commit does not match any tag, install from the local git repo
|
||||||
|
req = f".{extra_deps}"
|
||||||
|
print(f"Installing {req}...", flush=True)
|
||||||
pip_proc = run(
|
pip_proc = run(
|
||||||
[str(ENV_BIN / "python"), "-m", "pip", "install", req],
|
[str(ENV_BIN / "python"), "-m", "pip", "install", req],
|
||||||
stdout=PIPE,
|
stdout=PIPE,
|
||||||
stderr=STDOUT,
|
stderr=STDOUT,
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
|
cwd=ACTION_PATH,
|
||||||
)
|
)
|
||||||
if pip_proc.returncode:
|
if pip_proc.returncode:
|
||||||
print(pip_proc.stdout)
|
print(pip_proc.stdout)
|
||||||
print("::error::Failed to install Black.", flush=True)
|
print("::error::Failed to install Black.", file=sys.stderr, flush=True)
|
||||||
sys.exit(pip_proc.returncode)
|
sys.exit(pip_proc.returncode)
|
||||||
|
|
||||||
|
|
||||||
base_cmd = [str(ENV_BIN / "black")]
|
base_cmd = [str(ENV_BIN / "black")]
|
||||||
if BLACK_ARGS:
|
if BLACK_ARGS:
|
||||||
# TODO: remove after a while since this is deprecated in favour of SRC + OPTIONS.
|
# TODO: remove after a while since this is deprecated in favour of SRC + OPTIONS.
|
||||||
proc = run([*base_cmd, *shlex.split(BLACK_ARGS)])
|
proc = run(
|
||||||
|
[*base_cmd, *shlex.split(BLACK_ARGS)],
|
||||||
|
stdout=PIPE,
|
||||||
|
stderr=STDOUT,
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
proc = run([*base_cmd, *shlex.split(OPTIONS), *shlex.split(SRC)])
|
proc = run(
|
||||||
|
[*base_cmd, *shlex.split(OPTIONS), *shlex.split(SRC)],
|
||||||
|
stdout=PIPE,
|
||||||
|
stderr=STDOUT,
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
shutil.rmtree(ENV_PATH, ignore_errors=True)
|
||||||
|
print(proc.stdout)
|
||||||
sys.exit(proc.returncode)
|
sys.exit(proc.returncode)
|
||||||
|
@ -3,8 +3,13 @@ import collections
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import vim
|
import vim
|
||||||
from distutils.util import strtobool
|
|
||||||
|
|
||||||
|
def strtobool(text):
|
||||||
|
if text.lower() in ['y', 'yes', 't', 'true', 'on', '1']:
|
||||||
|
return True
|
||||||
|
if text.lower() in ['n', 'no', 'f', 'false', 'off', '0']:
|
||||||
|
return False
|
||||||
|
raise ValueError(f"{text} is not convertible to boolean")
|
||||||
|
|
||||||
class Flag(collections.namedtuple("FlagBase", "name, cast")):
|
class Flag(collections.namedtuple("FlagBase", "name, cast")):
|
||||||
@property
|
@property
|
||||||
@ -22,12 +27,14 @@ class Flag(collections.namedtuple("FlagBase", "name, cast")):
|
|||||||
FLAGS = [
|
FLAGS = [
|
||||||
Flag(name="line_length", cast=int),
|
Flag(name="line_length", cast=int),
|
||||||
Flag(name="fast", cast=strtobool),
|
Flag(name="fast", cast=strtobool),
|
||||||
Flag(name="string_normalization", cast=strtobool),
|
Flag(name="skip_string_normalization", cast=strtobool),
|
||||||
Flag(name="quiet", cast=strtobool),
|
Flag(name="quiet", cast=strtobool),
|
||||||
|
Flag(name="skip_magic_trailing_comma", cast=strtobool),
|
||||||
|
Flag(name="preview", cast=strtobool),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _get_python_binary(exec_prefix):
|
def _get_python_binary(exec_prefix, pyver):
|
||||||
try:
|
try:
|
||||||
default = vim.eval("g:pymode_python").strip()
|
default = vim.eval("g:pymode_python").strip()
|
||||||
except vim.error:
|
except vim.error:
|
||||||
@ -36,7 +43,15 @@ def _get_python_binary(exec_prefix):
|
|||||||
return default
|
return default
|
||||||
if sys.platform[:3] == "win":
|
if sys.platform[:3] == "win":
|
||||||
return exec_prefix / 'python.exe'
|
return exec_prefix / 'python.exe'
|
||||||
return exec_prefix / 'bin' / 'python3'
|
bin_path = exec_prefix / "bin"
|
||||||
|
exec_path = (bin_path / f"python{pyver[0]}.{pyver[1]}").resolve()
|
||||||
|
if exec_path.exists():
|
||||||
|
return exec_path
|
||||||
|
# It is possible that some environments may only have python3
|
||||||
|
exec_path = (bin_path / f"python3").resolve()
|
||||||
|
if exec_path.exists():
|
||||||
|
return exec_path
|
||||||
|
raise ValueError("python executable not found")
|
||||||
|
|
||||||
def _get_pip(venv_path):
|
def _get_pip(venv_path):
|
||||||
if sys.platform[:3] == "win":
|
if sys.platform[:3] == "win":
|
||||||
@ -49,9 +64,19 @@ def _get_virtualenv_site_packages(venv_path, pyver):
|
|||||||
return venv_path / 'lib' / f'python{pyver[0]}.{pyver[1]}' / 'site-packages'
|
return venv_path / 'lib' / f'python{pyver[0]}.{pyver[1]}' / 'site-packages'
|
||||||
|
|
||||||
def _initialize_black_env(upgrade=False):
|
def _initialize_black_env(upgrade=False):
|
||||||
|
if vim.eval("g:black_use_virtualenv ? 'true' : 'false'") == "false":
|
||||||
|
if upgrade:
|
||||||
|
print("Upgrade disabled due to g:black_use_virtualenv being disabled.")
|
||||||
|
print("Either use your system package manager (or pip) to upgrade black separately,")
|
||||||
|
print("or modify your vimrc to have 'let g:black_use_virtualenv = 1'.")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
# Nothing needed to be done.
|
||||||
|
return True
|
||||||
|
|
||||||
pyver = sys.version_info[:3]
|
pyver = sys.version_info[:3]
|
||||||
if pyver < (3, 6, 2):
|
if pyver < (3, 9):
|
||||||
print("Sorry, Black requires Python 3.6.2+ to run.")
|
print("Sorry, Black requires Python 3.9+ to run.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -65,7 +90,7 @@ def _initialize_black_env(upgrade=False):
|
|||||||
_executable = sys.executable
|
_executable = sys.executable
|
||||||
_base_executable = getattr(sys, "_base_executable", _executable)
|
_base_executable = getattr(sys, "_base_executable", _executable)
|
||||||
try:
|
try:
|
||||||
executable = str(_get_python_binary(Path(sys.exec_prefix)))
|
executable = str(_get_python_binary(Path(sys.exec_prefix), pyver))
|
||||||
sys.executable = executable
|
sys.executable = executable
|
||||||
sys._base_executable = executable
|
sys._base_executable = executable
|
||||||
print(f'Creating a virtualenv in {virtualenv_path}...')
|
print(f'Creating a virtualenv in {virtualenv_path}...')
|
||||||
@ -98,13 +123,49 @@ if _initialize_black_env():
|
|||||||
import black
|
import black
|
||||||
import time
|
import time
|
||||||
|
|
||||||
def Black():
|
def get_target_version(tv):
|
||||||
|
if isinstance(tv, black.TargetVersion):
|
||||||
|
return tv
|
||||||
|
ret = None
|
||||||
|
try:
|
||||||
|
ret = black.TargetVersion[tv.upper()]
|
||||||
|
except KeyError:
|
||||||
|
print(f"WARNING: Target version {tv!r} not recognized by Black, using default target")
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def Black(**kwargs):
|
||||||
|
"""
|
||||||
|
kwargs allows you to override ``target_versions`` argument of
|
||||||
|
``black.FileMode``.
|
||||||
|
|
||||||
|
``target_version`` needs to be cleaned because ``black.FileMode``
|
||||||
|
expects the ``target_versions`` argument to be a set of TargetVersion enums.
|
||||||
|
|
||||||
|
Allow kwargs["target_version"] to be a string to allow
|
||||||
|
to type it more quickly.
|
||||||
|
|
||||||
|
Using also target_version instead of target_versions to remain
|
||||||
|
consistent to Black's documentation of the structure of pyproject.toml.
|
||||||
|
"""
|
||||||
start = time.time()
|
start = time.time()
|
||||||
configs = get_configs()
|
configs = get_configs()
|
||||||
|
|
||||||
|
black_kwargs = {}
|
||||||
|
if "target_version" in kwargs:
|
||||||
|
target_version = kwargs["target_version"]
|
||||||
|
|
||||||
|
if not isinstance(target_version, (list, set)):
|
||||||
|
target_version = [target_version]
|
||||||
|
target_version = set(filter(lambda x: x, map(lambda tv: get_target_version(tv), target_version)))
|
||||||
|
black_kwargs["target_versions"] = target_version
|
||||||
|
|
||||||
mode = black.FileMode(
|
mode = black.FileMode(
|
||||||
line_length=configs["line_length"],
|
line_length=configs["line_length"],
|
||||||
string_normalization=configs["string_normalization"],
|
string_normalization=not configs["skip_string_normalization"],
|
||||||
is_pyi=vim.current.buffer.name.endswith('.pyi'),
|
is_pyi=vim.current.buffer.name.endswith('.pyi'),
|
||||||
|
magic_trailing_comma=not configs["skip_magic_trailing_comma"],
|
||||||
|
preview=configs["preview"],
|
||||||
|
**black_kwargs,
|
||||||
)
|
)
|
||||||
quiet = configs["quiet"]
|
quiet = configs["quiet"]
|
||||||
|
|
||||||
@ -117,9 +178,9 @@ def Black():
|
|||||||
)
|
)
|
||||||
except black.NothingChanged:
|
except black.NothingChanged:
|
||||||
if not quiet:
|
if not quiet:
|
||||||
print(f'Already well formatted, good job. (took {time.time() - start:.4f}s)')
|
print(f'Black: already well formatted, good job. (took {time.time() - start:.4f}s)')
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print(exc)
|
print(f'Black: {exc}')
|
||||||
else:
|
else:
|
||||||
current_buffer = vim.current.window.buffer
|
current_buffer = vim.current.window.buffer
|
||||||
cursors = []
|
cursors = []
|
||||||
@ -136,17 +197,18 @@ def Black():
|
|||||||
except vim.error:
|
except vim.error:
|
||||||
window.cursor = (len(window.buffer), 0)
|
window.cursor = (len(window.buffer), 0)
|
||||||
if not quiet:
|
if not quiet:
|
||||||
print(f'Reformatted in {time.time() - start:.4f}s.')
|
print(f'Black: reformatted in {time.time() - start:.4f}s.')
|
||||||
|
|
||||||
def get_configs():
|
def get_configs():
|
||||||
path_pyproject_toml = black.find_pyproject_toml(vim.eval("fnamemodify(getcwd(), ':t')"))
|
filename = vim.eval("@%")
|
||||||
|
path_pyproject_toml = black.find_pyproject_toml((filename,))
|
||||||
if path_pyproject_toml:
|
if path_pyproject_toml:
|
||||||
toml_config = black.parse_pyproject_toml(path_pyproject_toml)
|
toml_config = black.parse_pyproject_toml(path_pyproject_toml)
|
||||||
else:
|
else:
|
||||||
toml_config = {}
|
toml_config = {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
flag.var_name: flag.cast(toml_config.get(flag.name, vim.eval(flag.vim_rc_name)))
|
flag.var_name: toml_config.get(flag.name, flag.cast(vim.eval(flag.vim_rc_name)))
|
||||||
for flag in FLAGS
|
for flag in FLAGS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,8 +221,17 @@ def BlackVersion():
|
|||||||
|
|
||||||
EndPython3
|
EndPython3
|
||||||
|
|
||||||
function black#Black()
|
function black#Black(...)
|
||||||
:py3 Black()
|
let kwargs = {}
|
||||||
|
for arg in a:000
|
||||||
|
let arg_list = split(arg, '=')
|
||||||
|
let kwargs[arg_list[0]] = arg_list[1]
|
||||||
|
endfor
|
||||||
|
python3 << EOF
|
||||||
|
import vim
|
||||||
|
kwargs = vim.eval("kwargs")
|
||||||
|
EOF
|
||||||
|
:py3 Black(**kwargs)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function black#BlackUpgrade()
|
function black#BlackUpgrade()
|
||||||
|
@ -17,4 +17,4 @@ help:
|
|||||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
%: Makefile
|
%: Makefile
|
||||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
|
44
docs/_static/custom.css
vendored
44
docs/_static/custom.css
vendored
@ -1,44 +0,0 @@
|
|||||||
/* Make the sidebar scrollable. Fixes https://github.com/psf/black/issues/990 */
|
|
||||||
div.sphinxsidebar {
|
|
||||||
max-height: calc(100% - 18px);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
|
||||||
div.sphinxsidebar::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide scrollbar for IE 6, 7 and 8 */
|
|
||||||
@media \0screen\, screen\9 {
|
|
||||||
div.sphinxsidebar {
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide scrollbar for IE 9 and 10 */
|
|
||||||
/* backslash-9 removes ie11+ & old Safari 4 */
|
|
||||||
@media screen and (min-width: 0\0) {
|
|
||||||
div.sphinxsidebar {
|
|
||||||
-ms-overflow-style: none\9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide scrollbar for IE 11 and up */
|
|
||||||
_:-ms-fullscreen,
|
|
||||||
:root div.sphinxsidebar {
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide scrollbar for Edge */
|
|
||||||
@supports (-ms-ime-align: auto) {
|
|
||||||
div.sphinxsidebar {
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nicer style for local document toc */
|
|
||||||
.contents.topic {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
}
|
|
2
docs/_static/license.svg
vendored
2
docs/_static/license.svg
vendored
@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="78" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="78" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h47v20H0z"/><path fill="#7900CA" d="M47 0h31v20H47z"/><path fill="url(#b)" d="M0 0h78v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><text x="245" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">license</text><text x="245" y="140" transform="scale(.1)" textLength="370">license</text><text x="615" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">MIT</text><text x="615" y="140" transform="scale(.1)" textLength="210">MIT</text></g> </svg>
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="78" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="78" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h47v20H0z"/><path fill="#7900CA" d="M47 0h31v20H47z"/><path fill="url(#b)" d="M0 0h78v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><text x="245" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">license</text><text x="245" y="140" transform="scale(.1)" textLength="370">license</text><text x="615" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">MIT</text><text x="615" y="140" transform="scale(.1)" textLength="210">MIT</text></g> </svg>
|
||||||
|
Before Width: | Height: | Size: 949 B After Width: | Height: | Size: 950 B |
@ -1,3 +1,3 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203
|
extend-ignore = E203,E701
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203
|
extend-ignore = E203,E701
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203
|
extend-ignore = E203,E701
|
||||||
|
3
docs/compatible_configs/pycodestyle/.flake8
Normal file
3
docs/compatible_configs/pycodestyle/.flake8
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[pycodestyle]
|
||||||
|
max-line-length = 88
|
||||||
|
ignore = E203,E701
|
3
docs/compatible_configs/pycodestyle/setup.cfg
Normal file
3
docs/compatible_configs/pycodestyle/setup.cfg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[pycodestyle]
|
||||||
|
max-line-length = 88
|
||||||
|
ignore = E203,E701
|
3
docs/compatible_configs/pycodestyle/tox.ini
Normal file
3
docs/compatible_configs/pycodestyle/tox.ini
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[pycodestyle]
|
||||||
|
max-line-length = 88
|
||||||
|
ignore = E203,E701
|
@ -1,5 +1,2 @@
|
|||||||
[MESSAGES CONTROL]
|
|
||||||
disable = C0330, C0326
|
|
||||||
|
|
||||||
[format]
|
[format]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
[tool.pylint.messages_control]
|
|
||||||
disable = "C0330, C0326"
|
|
||||||
|
|
||||||
[tool.pylint.format]
|
[tool.pylint.format]
|
||||||
max-line-length = "88"
|
max-line-length = "88"
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
[pylint]
|
[pylint]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
|
|
||||||
[pylint.messages_control]
|
|
||||||
disable = C0330, C0326
|
|
||||||
|
108
docs/conf.py
108
docs/conf.py
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
#
|
||||||
# Configuration file for the Sphinx documentation builder.
|
# Configuration file for the Sphinx documentation builder.
|
||||||
#
|
#
|
||||||
@ -14,10 +13,12 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import string
|
import string
|
||||||
|
from importlib.metadata import version
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from pkg_resources import get_distribution
|
from sphinx.application import Sphinx
|
||||||
|
|
||||||
CURRENT_DIR = Path(__file__).parent
|
CURRENT_DIR = Path(__file__).parent
|
||||||
|
|
||||||
@ -25,12 +26,33 @@
|
|||||||
def make_pypi_svg(version: str) -> None:
|
def make_pypi_svg(version: str) -> None:
|
||||||
template: Path = CURRENT_DIR / "_static" / "pypi_template.svg"
|
template: Path = CURRENT_DIR / "_static" / "pypi_template.svg"
|
||||||
target: Path = CURRENT_DIR / "_static" / "pypi.svg"
|
target: Path = CURRENT_DIR / "_static" / "pypi.svg"
|
||||||
with open(str(template), "r", encoding="utf8") as f:
|
with open(str(template), encoding="utf8") as f:
|
||||||
svg: str = string.Template(f.read()).substitute(version=version)
|
svg: str = string.Template(f.read()).substitute(version=version)
|
||||||
with open(str(target), "w", encoding="utf8") as f:
|
with open(str(target), "w", encoding="utf8") as f:
|
||||||
f.write(svg)
|
f.write(svg)
|
||||||
|
|
||||||
|
|
||||||
|
def replace_pr_numbers_with_links(content: str) -> str:
|
||||||
|
"""Replaces all PR numbers with the corresponding GitHub link."""
|
||||||
|
return re.sub(r"#(\d+)", r"[#\1](https://github.com/psf/black/pull/\1)", content)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_include_read(
|
||||||
|
app: Sphinx,
|
||||||
|
relative_path: Path,
|
||||||
|
parent_docname: str,
|
||||||
|
content: list[str],
|
||||||
|
) -> None:
|
||||||
|
"""Handler for the include-read sphinx event."""
|
||||||
|
if parent_docname == "change_log":
|
||||||
|
content[0] = replace_pr_numbers_with_links(content[0])
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app: Sphinx) -> None:
|
||||||
|
"""Sets up a minimal sphinx extension."""
|
||||||
|
app.connect("include-read", handle_include_read)
|
||||||
|
|
||||||
|
|
||||||
# Necessary so Click doesn't hit an encode error when called by
|
# Necessary so Click doesn't hit an encode error when called by
|
||||||
# sphinxcontrib-programoutput on Windows.
|
# sphinxcontrib-programoutput on Windows.
|
||||||
os.putenv("pythonioencoding", "utf-8")
|
os.putenv("pythonioencoding", "utf-8")
|
||||||
@ -43,7 +65,7 @@ def make_pypi_svg(version: str) -> None:
|
|||||||
|
|
||||||
# Autopopulate version
|
# Autopopulate version
|
||||||
# The version, including alpha/beta/rc tags, but not commit hash and datestamps
|
# The version, including alpha/beta/rc tags, but not commit hash and datestamps
|
||||||
release = get_distribution("black").version.split("+")[0]
|
release = version("black").split("+")[0]
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = release
|
version = release
|
||||||
for sp in "abcfr":
|
for sp in "abcfr":
|
||||||
@ -55,7 +77,7 @@ def make_pypi_svg(version: str) -> None:
|
|||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
needs_sphinx = "3.0"
|
needs_sphinx = "4.4"
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
@ -87,7 +109,7 @@ def make_pypi_svg(version: str) -> None:
|
|||||||
#
|
#
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
# Usually you set "language" from the command line for these cases.
|
# Usually you set "language" from the command line for these cases.
|
||||||
language = None
|
language = "en"
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
@ -105,39 +127,22 @@ def make_pypi_svg(version: str) -> None:
|
|||||||
# Prettier support formatting some MyST syntax but not all, so let's disable the
|
# Prettier support formatting some MyST syntax but not all, so let's disable the
|
||||||
# unsupported yet still enabled by default ones.
|
# unsupported yet still enabled by default ones.
|
||||||
myst_disable_syntax = [
|
myst_disable_syntax = [
|
||||||
|
"colon_fence",
|
||||||
"myst_block_break",
|
"myst_block_break",
|
||||||
"myst_line_comment",
|
"myst_line_comment",
|
||||||
"math_block",
|
"math_block",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Optional MyST Syntaxes
|
||||||
|
myst_enable_extensions = []
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
#
|
#
|
||||||
html_theme = "alabaster"
|
html_theme = "furo"
|
||||||
|
html_logo = "_static/logo2-readme.png"
|
||||||
html_sidebars = {
|
|
||||||
"**": [
|
|
||||||
"about.html",
|
|
||||||
"navigation.html",
|
|
||||||
"relations.html",
|
|
||||||
"searchbox.html",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
html_theme_options = {
|
|
||||||
"show_related": False,
|
|
||||||
"description": "“Any color you like.”",
|
|
||||||
"github_button": True,
|
|
||||||
"github_user": "psf",
|
|
||||||
"github_repo": "black",
|
|
||||||
"github_type": "star",
|
|
||||||
"show_powered_by": True,
|
|
||||||
"fixed_sidebar": True,
|
|
||||||
"logo": "logo2.png",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
@ -166,15 +171,13 @@ def make_pypi_svg(version: str) -> None:
|
|||||||
# Grouping the document tree into LaTeX files. List of tuples
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
# (source start file, target name, title,
|
# (source start file, target name, title,
|
||||||
# author, documentclass [howto, manual, or own class]).
|
# author, documentclass [howto, manual, or own class]).
|
||||||
latex_documents = [
|
latex_documents = [(
|
||||||
(
|
master_doc,
|
||||||
master_doc,
|
"black.tex",
|
||||||
"black.tex",
|
"Documentation for Black",
|
||||||
"Documentation for Black",
|
"Łukasz Langa and contributors to Black",
|
||||||
"Łukasz Langa and contributors to Black",
|
"manual",
|
||||||
"manual",
|
)]
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output ------------------------------------------
|
# -- Options for manual page output ------------------------------------------
|
||||||
@ -189,17 +192,15 @@ def make_pypi_svg(version: str) -> None:
|
|||||||
# Grouping the document tree into Texinfo files. List of tuples
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
# (source start file, target name, title, author,
|
# (source start file, target name, title, author,
|
||||||
# dir menu entry, description, category)
|
# dir menu entry, description, category)
|
||||||
texinfo_documents = [
|
texinfo_documents = [(
|
||||||
(
|
master_doc,
|
||||||
master_doc,
|
"Black",
|
||||||
"Black",
|
"Documentation for Black",
|
||||||
"Documentation for Black",
|
author,
|
||||||
author,
|
"Black",
|
||||||
"Black",
|
"The uncompromising Python code formatter",
|
||||||
"The uncompromising Python code formatter",
|
"Miscellaneous",
|
||||||
"Miscellaneous",
|
)]
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Epub output -------------------------------------------------
|
# -- Options for Epub output -------------------------------------------------
|
||||||
@ -227,7 +228,14 @@ def make_pypi_svg(version: str) -> None:
|
|||||||
|
|
||||||
autodoc_member_order = "bysource"
|
autodoc_member_order = "bysource"
|
||||||
|
|
||||||
|
# -- sphinx-copybutton configuration ----------------------------------------
|
||||||
|
copybutton_prompt_text = (
|
||||||
|
r">>> |\.\.\. |> |\$ |\# | In \[\d*\]: | {2,5}\.\.\.: | {5,8}: "
|
||||||
|
)
|
||||||
|
copybutton_prompt_is_regexp = True
|
||||||
|
copybutton_remove_prompts = True
|
||||||
|
|
||||||
# -- Options for intersphinx extension ---------------------------------------
|
# -- Options for intersphinx extension ---------------------------------------
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
intersphinx_mapping = {"https://docs.python.org/3/": None}
|
intersphinx_mapping = {"<name>": ("https://docs.python.org/3/", None)}
|
||||||
|
@ -7,36 +7,52 @@ It's recommended you evaluate the quantifiable changes your _Black_ formatting
|
|||||||
modification causes before submitting a PR. Think about if the change seems disruptive
|
modification causes before submitting a PR. Think about if the change seems disruptive
|
||||||
enough to cause frustration to projects that are already "black formatted".
|
enough to cause frustration to projects that are already "black formatted".
|
||||||
|
|
||||||
## black-primer
|
## diff-shades
|
||||||
|
|
||||||
`black-primer` is a tool built for CI (and humans) to have _Black_ `--check` a number of
|
diff-shades is a tool that runs _Black_ across a list of open-source projects recording
|
||||||
Git accessible projects in parallel. (configured in `primer.json`) _(A PR will be
|
the results. The main highlight feature of diff-shades is being able to compare two
|
||||||
accepted to add Mercurial support.)_
|
revisions of _Black_. This is incredibly useful as it allows us to see what exact
|
||||||
|
changes will occur, say merging a certain PR.
|
||||||
|
|
||||||
### Run flow
|
For more information, please see the [diff-shades documentation][diff-shades].
|
||||||
|
|
||||||
- Ensure we have a `black` + `git` in PATH
|
### CI integration
|
||||||
- Load projects from `primer.json`
|
|
||||||
- Run projects in parallel with `--worker` workers (defaults to CPU count / 2)
|
|
||||||
- Checkout projects
|
|
||||||
- Run black and record result
|
|
||||||
- Clean up repository checkout _(can optionally be disabled via `--keep`)_
|
|
||||||
- Display results summary to screen
|
|
||||||
- Default to cleaning up `--work-dir` (which defaults to tempfile schemantics)
|
|
||||||
- Return
|
|
||||||
- 0 for successful run
|
|
||||||
- \< 0 for environment / internal error
|
|
||||||
- \> 0 for each project with an error
|
|
||||||
|
|
||||||
### Speed up runs 🏎
|
diff-shades is also the tool behind the "diff-shades results comparing ..." /
|
||||||
|
"diff-shades reports zero changes ..." comments on PRs. The project has a GitHub Actions
|
||||||
|
workflow that analyzes and compares two revisions of _Black_ according to these rules:
|
||||||
|
|
||||||
If you're running locally yourself to test black on lots of code try:
|
| | Baseline revision | Target revision |
|
||||||
|
| --------------------- | ----------------------- | ---------------------------- |
|
||||||
|
| On PRs | latest commit on `main` | PR commit with `main` merged |
|
||||||
|
| On pushes (main only) | latest PyPI version | the pushed commit |
|
||||||
|
|
||||||
- Using `-k` / `--keep` + `-w` / `--work-dir` so you don't have to re-checkout the repo
|
For pushes to main, there's only one analysis job named `preview-changes` where the
|
||||||
each run
|
preview style is used for all projects.
|
||||||
|
|
||||||
### CLI arguments
|
For PRs they get one more analysis job: `assert-no-changes`. It's similar to
|
||||||
|
`preview-changes` but runs with the stable code style. It will fail if changes were
|
||||||
|
made. This makes sure code won't be reformatted again and again within the same year in
|
||||||
|
accordance to Black's stability policy.
|
||||||
|
|
||||||
```{program-output} black-primer --help
|
Additionally for PRs, a PR comment will be posted embedding a summary of the preview
|
||||||
|
changes and links to further information. If there's a pre-existing diff-shades comment,
|
||||||
|
it'll be updated instead the next time the workflow is triggered on the same PR.
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
The `preview-changes` job will only fail intentionally if while analyzing a file failed to
|
||||||
|
format. Otherwise a failure indicates a bug in the workflow.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The workflow uploads several artifacts upon completion:
|
||||||
|
|
||||||
|
- The raw analyses (.json)
|
||||||
|
- HTML diffs (.html)
|
||||||
|
- `.pr-comment.json` (if triggered by a PR)
|
||||||
|
|
||||||
|
The last one is downloaded by the `diff-shades-comment` workflow and shouldn't be
|
||||||
|
downloaded locally. The HTML diffs come in handy for push-based where there's no PR to
|
||||||
|
post a comment. And the analyses exist just in case you want to do further analysis
|
||||||
|
using the collected data locally.
|
||||||
|
|
||||||
|
[diff-shades]: https://github.com/ichard26/diff-shades#readme
|
||||||
|
45
docs/contributing/index.md
Normal file
45
docs/contributing/index.md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
hidden:
|
||||||
|
---
|
||||||
|
|
||||||
|
the_basics
|
||||||
|
gauging_changes
|
||||||
|
issue_triage
|
||||||
|
release_process
|
||||||
|
```
|
||||||
|
|
||||||
|
Welcome! Happy to see you willing to make the project better. Have you read the entire
|
||||||
|
[user documentation](https://black.readthedocs.io/en/latest/) yet?
|
||||||
|
|
||||||
|
```{rubric} Bird's eye view
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
In terms of inspiration, _Black_ is about as configurable as _gofmt_ (which is to say,
|
||||||
|
not very). This is deliberate. _Black_ aims to provide a consistent style and take away
|
||||||
|
opportunities for arguing about style.
|
||||||
|
|
||||||
|
Bug reports and fixes are always welcome! Please follow the
|
||||||
|
[issue templates on GitHub](https://github.com/psf/black/issues/new/choose) for best
|
||||||
|
results.
|
||||||
|
|
||||||
|
Before you suggest a new feature or configuration knob, ask yourself why you want it. If
|
||||||
|
it enables better integration with some workflow, fixes an inconsistency, speeds things
|
||||||
|
up, and so on - go for it! On the other hand, if your answer is "because I don't like a
|
||||||
|
particular formatting" then you're not ready to embrace _Black_ yet. Such changes are
|
||||||
|
unlikely to get accepted. You can still try but prepare to be disappointed.
|
||||||
|
|
||||||
|
```{rubric} Contents
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
This section covers the following topics:
|
||||||
|
|
||||||
|
- {doc}`the_basics`
|
||||||
|
- {doc}`gauging_changes`
|
||||||
|
- {doc}`release_process`
|
||||||
|
|
||||||
|
For an overview on contributing to the _Black_, please checkout {doc}`the_basics`.
|
@ -1,42 +0,0 @@
|
|||||||
Contributing
|
|
||||||
============
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
the_basics
|
|
||||||
gauging_changes
|
|
||||||
issue_triage
|
|
||||||
release_process
|
|
||||||
reference/reference_summary
|
|
||||||
|
|
||||||
Welcome! Happy to see you willing to make the project better. Have you read the entire
|
|
||||||
`user documentation <https://black.readthedocs.io/en/latest/>`_ yet?
|
|
||||||
|
|
||||||
.. rubric:: Bird's eye view
|
|
||||||
|
|
||||||
In terms of inspiration, *Black* is about as configurable as *gofmt*. This is
|
|
||||||
deliberate.
|
|
||||||
|
|
||||||
Bug reports and fixes are always welcome! Please follow the
|
|
||||||
`issue template on GitHub <https://github.com/psf/black/issues/new>`_ for best results.
|
|
||||||
|
|
||||||
Before you suggest a new feature or configuration knob, ask yourself why you want it. If
|
|
||||||
it enables better integration with some workflow, fixes an inconsistency, speeds things
|
|
||||||
up, and so on - go for it! On the other hand, if your answer is "because I don't like a
|
|
||||||
particular formatting" then you're not ready to embrace *Black* yet. Such changes are
|
|
||||||
unlikely to get accepted. You can still try but prepare to be disappointed.
|
|
||||||
|
|
||||||
.. rubric:: Contents
|
|
||||||
|
|
||||||
This section covers the following topics:
|
|
||||||
|
|
||||||
- :doc:`the_basics`
|
|
||||||
- :doc:`gauging_changes`
|
|
||||||
- :doc:`release_process`
|
|
||||||
- :doc:`reference/reference_summary`
|
|
||||||
|
|
||||||
For an overview on contributing to the *Black*, please checkout :doc:`the_basics`.
|
|
||||||
|
|
||||||
If you need a reference of the functions, classes, etc. available to you while
|
|
||||||
developing *Black*, there's the :doc:`reference/reference_summary` docs.
|
|
@ -1,6 +1,6 @@
|
|||||||
# Issue triage
|
# Issue triage
|
||||||
|
|
||||||
Currently, _Black_ uses the issue tracker for bugs, feature requests, proposed design
|
Currently, _Black_ uses the issue tracker for bugs, feature requests, proposed style
|
||||||
modifications, and general user support. Each of these issues have to be triaged so they
|
modifications, and general user support. Each of these issues have to be triaged so they
|
||||||
can be eventually be resolved somehow. This document outlines the triaging process and
|
can be eventually be resolved somehow. This document outlines the triaging process and
|
||||||
also the current guidelines and recommendations.
|
also the current guidelines and recommendations.
|
||||||
@ -42,7 +42,7 @@ The lifecycle of a bug report or user support issue typically goes something lik
|
|||||||
1. _the issue is waiting for triage_
|
1. _the issue is waiting for triage_
|
||||||
2. **identified** - has been marked with a type label and other relevant labels, more
|
2. **identified** - has been marked with a type label and other relevant labels, more
|
||||||
details or a functional reproduction may be still needed (and therefore should be
|
details or a functional reproduction may be still needed (and therefore should be
|
||||||
marked with `S: needs repro` or `S: awaiting reponse`)
|
marked with `S: needs repro` or `S: awaiting response`)
|
||||||
3. **confirmed** - the issue can reproduced and necessary details have been provided
|
3. **confirmed** - the issue can reproduced and necessary details have been provided
|
||||||
4. **discussion** - initial triage has been done and now the general details on how the
|
4. **discussion** - initial triage has been done and now the general details on how the
|
||||||
issue should be best resolved are being hashed out
|
issue should be best resolved are being hashed out
|
||||||
@ -53,13 +53,13 @@ The lifecycle of a bug report or user support issue typically goes something lik
|
|||||||
- the issue has been fixed
|
- the issue has been fixed
|
||||||
- duplicate of another pre-existing issue or is invalid
|
- duplicate of another pre-existing issue or is invalid
|
||||||
|
|
||||||
For enhancement, documentation, and design issues, the lifecycle looks very similar but
|
For enhancement, documentation, and style issues, the lifecycle looks very similar but
|
||||||
the details are different:
|
the details are different:
|
||||||
|
|
||||||
1. _the issue is waiting for triage_
|
1. _the issue is waiting for triage_
|
||||||
2. **identified** - has been marked with a type label and other relevant labels
|
2. **identified** - has been marked with a type label and other relevant labels
|
||||||
3. **discussion** - the merits of the suggested changes are currently being discussed, a
|
3. **discussion** - the merits of the suggested changes are currently being discussed, a
|
||||||
PR would be acceptable but would be at sigificant risk of being rejected
|
PR would be acceptable but would be at significant risk of being rejected
|
||||||
4. **accepted & awaiting PR** - it's been determined the suggested changes are OK and a
|
4. **accepted & awaiting PR** - it's been determined the suggested changes are OK and a
|
||||||
PR would be welcomed (`S: accepted`)
|
PR would be welcomed (`S: accepted`)
|
||||||
5. **closed**: - the issue has been resolved, reasons include:
|
5. **closed**: - the issue has been resolved, reasons include:
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
*Black* classes
|
|
||||||
===============
|
|
||||||
|
|
||||||
*Contents are subject to change.*
|
|
||||||
|
|
||||||
.. currentmodule:: black
|
|
||||||
|
|
||||||
:class:`BracketTracker`
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
.. autoclass:: black.brackets.BracketTracker
|
|
||||||
:members:
|
|
||||||
|
|
||||||
:class:`EmptyLineTracker`
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. autoclass:: black.EmptyLineTracker
|
|
||||||
:members:
|
|
||||||
|
|
||||||
:class:`Line`
|
|
||||||
-------------
|
|
||||||
|
|
||||||
.. autoclass:: black.Line
|
|
||||||
:members:
|
|
||||||
:special-members: __str__, __bool__
|
|
||||||
|
|
||||||
:class:`LineGenerator`
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
.. autoclass:: black.LineGenerator
|
|
||||||
:show-inheritance:
|
|
||||||
:members:
|
|
||||||
|
|
||||||
:class:`ProtoComment`
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
.. autoclass:: black.comments.ProtoComment
|
|
||||||
:members:
|
|
||||||
|
|
||||||
:class:`Report`
|
|
||||||
---------------
|
|
||||||
|
|
||||||
.. autoclass:: black.Report
|
|
||||||
:members:
|
|
||||||
:special-members: __str__
|
|
||||||
|
|
||||||
:class:`Visitor`
|
|
||||||
----------------
|
|
||||||
|
|
||||||
.. autoclass:: black.nodes.Visitor
|
|
||||||
:show-inheritance:
|
|
||||||
:members:
|
|
||||||
|
|
||||||
Enums
|
|
||||||
=====
|
|
||||||
|
|
||||||
:class:`Changed`
|
|
||||||
----------------
|
|
||||||
|
|
||||||
.. autoclass:: black.Changed
|
|
||||||
:show-inheritance:
|
|
||||||
:members:
|
|
||||||
|
|
||||||
:class:`Mode`
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
.. autoclass:: black.Mode
|
|
||||||
:show-inheritance:
|
|
||||||
:members:
|
|
||||||
|
|
||||||
:class:`WriteBack`
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. autoclass:: black.WriteBack
|
|
||||||
:show-inheritance:
|
|
||||||
:members:
|
|
@ -1,12 +0,0 @@
|
|||||||
*Black* exceptions
|
|
||||||
==================
|
|
||||||
|
|
||||||
*Contents are subject to change.*
|
|
||||||
|
|
||||||
.. currentmodule:: black
|
|
||||||
|
|
||||||
.. autoexception:: black.linegen.CannotSplit
|
|
||||||
|
|
||||||
.. autoexception:: black.NothingChanged
|
|
||||||
|
|
||||||
.. autoexception:: black.InvalidInput
|
|
@ -1,178 +0,0 @@
|
|||||||
*Black* functions
|
|
||||||
=================
|
|
||||||
|
|
||||||
*Contents are subject to change.*
|
|
||||||
|
|
||||||
.. currentmodule:: black
|
|
||||||
|
|
||||||
Assertions and checks
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
.. autofunction:: black.assert_equivalent
|
|
||||||
|
|
||||||
.. autofunction:: black.assert_stable
|
|
||||||
|
|
||||||
.. autofunction:: black.lines.can_be_split
|
|
||||||
|
|
||||||
.. autofunction:: black.lines.can_omit_invisible_parens
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.is_empty_tuple
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.is_import
|
|
||||||
|
|
||||||
.. autofunction:: black.lines.is_line_short_enough
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.is_multiline_string
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.is_one_tuple
|
|
||||||
|
|
||||||
.. autofunction:: black.brackets.is_split_after_delimiter
|
|
||||||
|
|
||||||
.. autofunction:: black.brackets.is_split_before_delimiter
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.is_stub_body
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.is_stub_suite
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.is_vararg
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.is_yield
|
|
||||||
|
|
||||||
|
|
||||||
Formatting
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. autofunction:: black.format_file_contents
|
|
||||||
|
|
||||||
.. autofunction:: black.format_file_in_place
|
|
||||||
|
|
||||||
.. autofunction:: black.format_stdin_to_stdout
|
|
||||||
|
|
||||||
.. autofunction:: black.format_str
|
|
||||||
|
|
||||||
.. autofunction:: black.reformat_one
|
|
||||||
|
|
||||||
.. autofunction:: black.schedule_formatting
|
|
||||||
|
|
||||||
File operations
|
|
||||||
---------------
|
|
||||||
|
|
||||||
.. autofunction:: black.dump_to_file
|
|
||||||
|
|
||||||
.. autofunction:: black.find_project_root
|
|
||||||
|
|
||||||
.. autofunction:: black.gen_python_files
|
|
||||||
|
|
||||||
.. autofunction:: black.read_pyproject_toml
|
|
||||||
|
|
||||||
Parsing
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. autofunction:: black.decode_bytes
|
|
||||||
|
|
||||||
.. autofunction:: black.parsing.lib2to3_parse
|
|
||||||
|
|
||||||
.. autofunction:: black.parsing.lib2to3_unparse
|
|
||||||
|
|
||||||
Split functions
|
|
||||||
---------------
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.bracket_split_build_line
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.bracket_split_succeeded_or_raise
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.delimiter_split
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.left_hand_split
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.right_hand_split
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.standalone_comment_split
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.transform_line
|
|
||||||
|
|
||||||
Caching
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. autofunction:: black.cache.filter_cached
|
|
||||||
|
|
||||||
.. autofunction:: black.cache.get_cache_file
|
|
||||||
|
|
||||||
.. autofunction:: black.cache.get_cache_info
|
|
||||||
|
|
||||||
.. autofunction:: black.cache.read_cache
|
|
||||||
|
|
||||||
.. autofunction:: black.cache.write_cache
|
|
||||||
|
|
||||||
Utilities
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. py:function:: black.debug.DebugVisitor.show(code: str) -> None
|
|
||||||
|
|
||||||
Pretty-print the lib2to3 AST of a given string of `code`.
|
|
||||||
|
|
||||||
.. autofunction:: black.concurrency.cancel
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.child_towards
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.container_of
|
|
||||||
|
|
||||||
.. autofunction:: black.comments.convert_one_fmt_off_pair
|
|
||||||
|
|
||||||
.. autofunction:: black.diff
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.dont_increase_indentation
|
|
||||||
|
|
||||||
.. autofunction:: black.numerics.format_float_or_int_string
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.ensure_visible
|
|
||||||
|
|
||||||
.. autofunction:: black.lines.enumerate_reversed
|
|
||||||
|
|
||||||
.. autofunction:: black.comments.generate_comments
|
|
||||||
|
|
||||||
.. autofunction:: black.comments.generate_ignored_nodes
|
|
||||||
|
|
||||||
.. autofunction:: black.comments.is_fmt_on
|
|
||||||
|
|
||||||
.. autofunction:: black.comments.contains_fmt_on_at_column
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.first_leaf_column
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.generate_trailers_to_omit
|
|
||||||
|
|
||||||
.. autofunction:: black.get_future_imports
|
|
||||||
|
|
||||||
.. autofunction:: black.comments.list_comments
|
|
||||||
|
|
||||||
.. autofunction:: black.comments.make_comment
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.maybe_make_parens_invisible_in_atom
|
|
||||||
|
|
||||||
.. autofunction:: black.brackets.max_delimiter_priority_in_atom
|
|
||||||
|
|
||||||
.. autofunction:: black.normalize_fmt_off
|
|
||||||
|
|
||||||
.. autofunction:: black.numerics.normalize_numeric_literal
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.normalize_prefix
|
|
||||||
|
|
||||||
.. autofunction:: black.strings.normalize_string_prefix
|
|
||||||
|
|
||||||
.. autofunction:: black.strings.normalize_string_quotes
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.normalize_invisible_parens
|
|
||||||
|
|
||||||
.. autofunction:: black.patch_click
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.preceding_leaf
|
|
||||||
|
|
||||||
.. autofunction:: black.re_compile_maybe_verbose
|
|
||||||
|
|
||||||
.. autofunction:: black.linegen.should_split_line
|
|
||||||
|
|
||||||
.. autofunction:: black.shutdown
|
|
||||||
|
|
||||||
.. autofunction:: black.strings.sub_twice
|
|
||||||
|
|
||||||
.. autofunction:: black.nodes.whitespace
|
|
@ -1,16 +0,0 @@
|
|||||||
Developer reference
|
|
||||||
===================
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
The documentation here is quite outdated and has been neglected. Many objects worthy
|
|
||||||
of inclusion aren't documented. Contributions are appreciated!
|
|
||||||
|
|
||||||
*Contents are subject to change.*
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
reference_classes
|
|
||||||
reference_functions
|
|
||||||
reference_exceptions
|
|
@ -1,89 +1,174 @@
|
|||||||
# Release process
|
# Release process
|
||||||
|
|
||||||
_Black_ has had a lot of work automating its release process. This document sets out to
|
_Black_ has had a lot of work done into standardizing and automating its release
|
||||||
explain what everything does and how to release _Black_ using said automation.
|
process. This document sets out to explain how everything works and how to release
|
||||||
|
_Black_ using said automation.
|
||||||
|
|
||||||
## Cutting a Release
|
## Release cadence
|
||||||
|
|
||||||
To cut a release, you must be a _Black_ maintainer with `GitHub Release` creation
|
**We aim to release whatever is on `main` every 1-2 months.** This ensures merged
|
||||||
access. Using this access, the release process is:
|
improvements and bugfixes are shipped to users reasonably quickly, while not massively
|
||||||
|
fracturing the user-base with too many versions. This also keeps the workload on
|
||||||
|
maintainers consistent and predictable.
|
||||||
|
|
||||||
1. Cut a new PR editing `CHANGES.md` to version the latest changes
|
If there's not much new on `main` to justify a release, it's acceptable to skip a
|
||||||
1. Example PR: https://github.com/psf/black/pull/2192
|
month's release. Ideally January releases should not be skipped because as per our
|
||||||
2. Example title: `Update CHANGES.md for XX.X release`
|
[stability policy](labels/stability-policy), the first release in a new calendar year
|
||||||
2. Once the release PR is merged ensure all CI passes
|
may make changes to the _stable_ style. While the policy applies to the first release
|
||||||
1. If not, ensure there is an Issue open for the cause of failing CI (generally we'd
|
(instead of only January releases), confining changes to the stable style to January
|
||||||
want this fixed before cutting a release)
|
will keep things predictable (and nicer) for users.
|
||||||
3. Open `CHANGES.md` and copy the _raw markdown_ of the latest changes to use in the
|
|
||||||
description of the GitHub Release.
|
|
||||||
4. Go and [cut a release](https://github.com/psf/black/releases) using the GitHub UI so
|
|
||||||
that all workflows noted below are triggered.
|
|
||||||
1. The release version and tag should be the [CalVer](https://calver.org) version
|
|
||||||
_Black_ used for the current release e.g. `21.6` / `21.5b1`
|
|
||||||
2. _Black_ uses [setuptools scm](https://pypi.org/project/setuptools-scm/) to pull
|
|
||||||
the current version for the package builds and release.
|
|
||||||
5. Once the release is cut, you're basically done. It's a good practice to go and watch
|
|
||||||
to make sure all the [GitHub Actions](https://github.com/psf/black/actions) pass,
|
|
||||||
although you should receive an email to your registered GitHub email address should
|
|
||||||
one fail.
|
|
||||||
1. You should see all the release workflows and lint/unittests workflows running on
|
|
||||||
the new tag in the Actions UI
|
|
||||||
|
|
||||||
If anything fails, please go read the respective action's log output and configuration
|
Unless there is a serious regression or bug that requires immediate patching, **there
|
||||||
file to reverse engineer your way to a fix/soluton.
|
should not be more than one release per month**. While version numbers are cheap,
|
||||||
|
releases require a maintainer to both commit to do the actual cutting of a release, but
|
||||||
|
also to be able to deal with the potential fallout post-release. Releasing more
|
||||||
|
frequently than monthly nets rapidly diminishing returns.
|
||||||
|
|
||||||
|
## Cutting a release
|
||||||
|
|
||||||
|
**You must have `write` permissions for the _Black_ repository to cut a release.**
|
||||||
|
|
||||||
|
The 10,000 foot view of the release process is that you prepare a release PR and then
|
||||||
|
publish a [GitHub Release]. This triggers [release automation](#release-workflows) that
|
||||||
|
builds all release artifacts and publishes them to the various platforms we publish to.
|
||||||
|
|
||||||
|
We now have a `scripts/release.py` script to help with cutting the release PRs.
|
||||||
|
|
||||||
|
- `python3 scripts/release.py --help` is your friend.
|
||||||
|
- `release.py` has only been tested in Python 3.12 (so get with the times :D)
|
||||||
|
|
||||||
|
To cut a release:
|
||||||
|
|
||||||
|
1. Determine the release's version number
|
||||||
|
- **_Black_ follows the [CalVer] versioning standard using the `YY.M.N` format**
|
||||||
|
- So unless there already has been a release during this month, `N` should be `0`
|
||||||
|
- Example: the first release in January, 2022 → `22.1.0`
|
||||||
|
- `release.py` will calculate this and log to stderr for you copy paste pleasure
|
||||||
|
1. File a PR editing `CHANGES.md` and the docs to version the latest changes
|
||||||
|
- Run `python3 scripts/release.py [--debug]` to generate most changes
|
||||||
|
- Sub headings in the template, if they have no bullet points need manual removal
|
||||||
|
_PR welcome to improve :D_
|
||||||
|
1. If `release.py` fail manually edit; otherwise, yay, skip this step!
|
||||||
|
1. Replace the `## Unreleased` header with the version number
|
||||||
|
1. Remove any empty sections for the current release
|
||||||
|
1. (_optional_) Read through and copy-edit the changelog (eg. by moving entries,
|
||||||
|
fixing typos, or rephrasing entries)
|
||||||
|
1. Double-check that no changelog entries since the last release were put in the
|
||||||
|
wrong section (e.g., run `git diff <last release> CHANGES.md`)
|
||||||
|
1. Update references to the latest version in
|
||||||
|
{doc}`/integrations/source_version_control` and
|
||||||
|
{doc}`/usage_and_configuration/the_basics`
|
||||||
|
- Example PR: [GH-3139]
|
||||||
|
1. Once the release PR is merged, wait until all CI passes
|
||||||
|
- If CI does not pass, **stop** and investigate the failure(s) as generally we'd want
|
||||||
|
to fix failing CI before cutting a release
|
||||||
|
1. [Draft a new GitHub Release][new-release]
|
||||||
|
1. Click `Choose a tag` and type in the version number, then select the
|
||||||
|
`Create new tag: YY.M.N on publish` option that appears
|
||||||
|
1. Verify that the new tag targets the `main` branch
|
||||||
|
1. You can leave the release title blank, GitHub will default to the tag name
|
||||||
|
1. Copy and paste the _raw changelog Markdown_ for the current release into the
|
||||||
|
description box
|
||||||
|
1. Publish the GitHub Release, triggering [release automation](#release-workflows) that
|
||||||
|
will handle the rest
|
||||||
|
1. Once CI is done add + commit (git push - No review) a new empty template for the next
|
||||||
|
release to CHANGES.md _(Template is able to be copy pasted from release.py should we
|
||||||
|
fail)_
|
||||||
|
1. `python3 scripts/release.py --add-changes-template|-a [--debug]`
|
||||||
|
1. Should that fail, please return to copy + paste
|
||||||
|
1. At this point, you're basically done. It's good practice to go and [watch and verify
|
||||||
|
that all the release workflows pass][black-actions], although you will receive a
|
||||||
|
GitHub notification should something fail.
|
||||||
|
- If something fails, don't panic. Please go read the respective workflow's logs and
|
||||||
|
configuration file to reverse-engineer your way to a fix/solution.
|
||||||
|
|
||||||
|
Congratulations! You've successfully cut a new release of _Black_. Go and stand up and
|
||||||
|
take a break, you deserve it.
|
||||||
|
|
||||||
|
```{important}
|
||||||
|
Once the release artifacts reach PyPI, you may see new issues being filed indicating
|
||||||
|
regressions. While regressions are not great, they don't automatically mean a hotfix
|
||||||
|
release is warranted. Unless the regressions are serious and impact many users, a hotfix
|
||||||
|
release is probably unnecessary.
|
||||||
|
|
||||||
|
In the end, use your best judgement and ask other maintainers for their thoughts.
|
||||||
|
```
|
||||||
|
|
||||||
## Release workflows
|
## Release workflows
|
||||||
|
|
||||||
All _Blacks_'s automation workflows use GitHub Actions. All workflows are therefore
|
All of _Black_'s release automation uses [GitHub Actions]. All workflows are therefore
|
||||||
configured using `.yml` files in the `.github/workflows` directory of the _Black_
|
configured using YAML files in the `.github/workflows` directory of the _Black_
|
||||||
repository.
|
repository.
|
||||||
|
|
||||||
|
They are triggered by the publication of a [GitHub Release].
|
||||||
|
|
||||||
Below are descriptions of our release workflows.
|
Below are descriptions of our release workflows.
|
||||||
|
|
||||||
### Docker
|
### Publish to PyPI
|
||||||
|
|
||||||
This workflow uses the QEMU powered `buildx` feature of docker to upload a `arm64` and
|
This is our main workflow. It builds an [sdist] and [wheels] to upload to PyPI where the
|
||||||
`amd64`/`x86_64` build of the official _Black_ docker image™.
|
vast majority of users will download Black from. It's divided into three job groups:
|
||||||
|
|
||||||
- Currently this workflow uses an API Token associated with @cooperlees account
|
#### sdist + pure wheel
|
||||||
|
|
||||||
### pypi_upload
|
This single job builds the sdist and pure Python wheel (i.e., a wheel that only contains
|
||||||
|
Python code) using [build] and then uploads them to PyPI using [twine]. These artifacts
|
||||||
|
are general-purpose and can be used on basically any platform supported by Python.
|
||||||
|
|
||||||
This workflow builds a Python
|
#### mypyc wheels (…)
|
||||||
[sdist](https://docs.python.org/3/distutils/sourcedist.html) and
|
|
||||||
[wheel](https://pythonwheels.com) using the latest
|
|
||||||
[setuptools](https://pypi.org/project/setuptools/) and
|
|
||||||
[wheel](https://pypi.org/project/wheel/) modules.
|
|
||||||
|
|
||||||
It will then use [twine](https://pypi.org/project/twine/) to upload both release formats
|
We use [mypyc] to compile _Black_ into a CPython C extension for significantly improved
|
||||||
to PyPI for general downloading of the _Black_ Python package. This is where
|
performance. Wheels built with mypyc are platform and Python version specific.
|
||||||
[pip](https://pypi.org/project/pip/) looks by default.
|
[Supported platforms are documented in the FAQ](labels/mypyc-support).
|
||||||
|
|
||||||
- Currently this workflow uses an API token associated with @ambv's PyPI account
|
These matrix jobs use [cibuildwheel] which handles the complicated task of building C
|
||||||
|
extensions for many environments for us. Since building these wheels is slow, there are
|
||||||
|
multiple mypyc wheels jobs (hence the term "matrix") that build for a specific platform
|
||||||
|
(as noted in the job name in parentheses).
|
||||||
|
|
||||||
### Upload self-contained binaries
|
Like the previous job group, the built wheels are uploaded to PyPI using [twine].
|
||||||
|
|
||||||
This workflow builds self-contained binaries for multiple platforms. This allows people
|
#### Update stable branch
|
||||||
to download the executable for their platform and run _Black_ without a
|
|
||||||
[Python Runtime](https://wiki.python.org/moin/PythonImplementations) installed.
|
|
||||||
|
|
||||||
The created binaries are attached/stored on the associated
|
So this job doesn't _really_ belong here, but updating the `stable` branch after the
|
||||||
[GitHub Release](https://github.com/psf/black/releases) for download over _IPv4 only_
|
other PyPI jobs pass (they must pass for this job to start) makes the most sense. This
|
||||||
(GitHub still does not have IPv6 access 😢).
|
saves us from remembering to update the branch sometime after cutting the release.
|
||||||
|
|
||||||
## Moving the `stable` tag
|
- _Currently this workflow uses an API token associated with @ambv's PyPI account_
|
||||||
|
|
||||||
_Black_ provides a stable tag for people who want to move along as _Black_ developers
|
### Publish executables
|
||||||
deem the newest version reliable. Here the _Black_ developers will move once the release
|
|
||||||
has been problem free for at least ~24 hours from release. Given the large _Black_
|
|
||||||
userbase we hear about bad bugs quickly. We do strive to continually improve our CI too.
|
|
||||||
|
|
||||||
### Tag moving process
|
This workflow builds native executables for multiple platforms using [PyInstaller]. This
|
||||||
|
allows people to download the executable for their platform and run _Black_ without a
|
||||||
|
[Python runtime](https://wiki.python.org/moin/PythonImplementations) installed.
|
||||||
|
|
||||||
#### stable
|
The created binaries are stored on the associated GitHub Release for download over _IPv4
|
||||||
|
only_ (GitHub still does not have IPv6 access 😢).
|
||||||
|
|
||||||
From a rebased `main` checkout:
|
### docker
|
||||||
|
|
||||||
1. `git tag -f stable VERSION_TAG`
|
This workflow uses the QEMU powered `buildx` feature of Docker to upload an `arm64` and
|
||||||
1. e.g. `git tag -f stable 21.5b1`
|
`amd64`/`x86_64` build of the official _Black_ Docker image™.
|
||||||
1. `git push --tags -f`
|
|
||||||
|
- _Currently this workflow uses an API Token associated with @cooperlees account_
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
This also runs on each push to `main`.
|
||||||
|
```
|
||||||
|
|
||||||
|
[black-actions]: https://github.com/psf/black/actions
|
||||||
|
[build]: https://pypa-build.readthedocs.io/
|
||||||
|
[calver]: https://calver.org
|
||||||
|
[cibuildwheel]: https://cibuildwheel.readthedocs.io/
|
||||||
|
[gh-3139]: https://github.com/psf/black/pull/3139
|
||||||
|
[github actions]: https://github.com/features/actions
|
||||||
|
[github release]: https://github.com/psf/black/releases
|
||||||
|
[new-release]: https://github.com/psf/black/releases/new
|
||||||
|
[mypyc]: https://mypyc.readthedocs.io/
|
||||||
|
[mypyc-platform-support]:
|
||||||
|
/faq.html#what-is-compiled-yes-no-all-about-in-the-version-output
|
||||||
|
[pyinstaller]: https://www.pyinstaller.org/
|
||||||
|
[sdist]:
|
||||||
|
https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist
|
||||||
|
[twine]: https://github.com/features/actions
|
||||||
|
[wheels]: https://packaging.python.org/en/latest/glossary/#term-Wheel
|
||||||
|
@ -4,26 +4,27 @@ An overview on contributing to the _Black_ project.
|
|||||||
|
|
||||||
## Technicalities
|
## Technicalities
|
||||||
|
|
||||||
Development on the latest version of Python is preferred. As of this writing it's 3.9.
|
Development on the latest version of Python is preferred. You can use any operating
|
||||||
You can use any operating system.
|
system.
|
||||||
|
|
||||||
Install all development dependencies using:
|
First clone the _Black_ repository:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ pipenv install --dev
|
$ git clone https://github.com/psf/black.git
|
||||||
$ pipenv shell
|
$ cd black
|
||||||
$ pre-commit install
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you haven't used `pipenv` before but are comfortable with virtualenvs, just run
|
Then install development dependencies inside a virtual environment of your choice, for
|
||||||
`pip install pipenv` in the virtualenv you're already using and invoke the command above
|
example:
|
||||||
from the cloned _Black_ repo. It will do the correct thing.
|
|
||||||
|
|
||||||
Non pipenv install works too:
|
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ pip install -r test_requirements.txt
|
$ python3 -m venv .venv
|
||||||
$ pip install -e .[d]
|
$ source .venv/bin/activate # activation for linux and mac
|
||||||
|
$ .venv\Scripts\activate # activation for windows
|
||||||
|
|
||||||
|
(.venv)$ pip install -r test_requirements.txt
|
||||||
|
(.venv)$ pip install -e ".[d]"
|
||||||
|
(.venv)$ pre-commit install
|
||||||
```
|
```
|
||||||
|
|
||||||
Before submitting pull requests, run lints and tests with the following commands from
|
Before submitting pull requests, run lints and tests with the following commands from
|
||||||
@ -31,69 +32,125 @@ the root of the black repo:
|
|||||||
|
|
||||||
```console
|
```console
|
||||||
# Linting
|
# Linting
|
||||||
$ pre-commit run -a
|
(.venv)$ pre-commit run -a
|
||||||
|
|
||||||
# Unit tests
|
# Unit tests
|
||||||
$ tox -e py
|
(.venv)$ tox -e py
|
||||||
|
|
||||||
# Optional Fuzz testing
|
# Optional Fuzz testing
|
||||||
$ tox -e fuzz
|
(.venv)$ tox -e fuzz
|
||||||
|
|
||||||
# Optional CI run to test your changes on many popular python projects
|
# Format Black itself
|
||||||
$ black-primer [-k -w /tmp/black_test_repos]
|
(.venv)$ tox -e run_self
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
Further examples of invoking the tests
|
||||||
|
|
||||||
|
```console
|
||||||
|
# Run all of the above mentioned, in parallel
|
||||||
|
(.venv)$ tox --parallel=auto
|
||||||
|
|
||||||
|
# Run tests on a specific python version
|
||||||
|
(.venv)$ tox -e py39
|
||||||
|
|
||||||
|
# Run an individual test
|
||||||
|
(.venv)$ pytest -k <test name>
|
||||||
|
|
||||||
|
# Pass arguments to pytest
|
||||||
|
(.venv)$ tox -e py -- --no-cov
|
||||||
|
|
||||||
|
# Print full tree diff, see documentation below
|
||||||
|
(.venv)$ tox -e py -- --print-full-tree
|
||||||
|
|
||||||
|
# Disable diff printing, see documentation below
|
||||||
|
(.venv)$ tox -e py -- --print-tree-diff=False
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
All aspects of the _Black_ style should be tested. Normally, tests should be created as
|
||||||
|
files in the `tests/data/cases` directory. These files consist of up to three parts:
|
||||||
|
|
||||||
|
- A line that starts with `# flags: ` followed by a set of command-line options. For
|
||||||
|
example, if the line is `# flags: --preview --skip-magic-trailing-comma`, the test
|
||||||
|
case will be run with preview mode on and the magic trailing comma off. The options
|
||||||
|
accepted are mostly a subset of those of _Black_ itself, except for the
|
||||||
|
`--minimum-version=` flag, which should be used when testing a grammar feature that
|
||||||
|
works only in newer versions of Python. This flag ensures that we don't try to
|
||||||
|
validate the AST on older versions and tests that we autodetect the Python version
|
||||||
|
correctly when the feature is used. For the exact flags accepted, see the function
|
||||||
|
`get_flags_parser` in `tests/util.py`. If this line is omitted, the default options
|
||||||
|
are used.
|
||||||
|
- A block of Python code used as input for the formatter.
|
||||||
|
- The line `# output`, followed by the output of _Black_ when run on the previous block.
|
||||||
|
If this is omitted, the test asserts that _Black_ will leave the input code unchanged.
|
||||||
|
|
||||||
|
_Black_ has two pytest command-line options affecting test files in `tests/data/` that
|
||||||
|
are split into an input part, and an output part, separated by a line with`# output`.
|
||||||
|
These can be passed to `pytest` through `tox`, or directly into pytest if not using
|
||||||
|
`tox`.
|
||||||
|
|
||||||
|
#### `--print-full-tree`
|
||||||
|
|
||||||
|
Upon a failing test, print the full concrete syntax tree (CST) as it is after processing
|
||||||
|
the input ("actual"), and the tree that's yielded after parsing the output ("expected").
|
||||||
|
Note that a test can fail with different output with the same CST. This used to be the
|
||||||
|
default, but now defaults to `False`.
|
||||||
|
|
||||||
|
#### `--print-tree-diff`
|
||||||
|
|
||||||
|
Upon a failing test, print the diff of the trees as described above. This is the
|
||||||
|
default. To turn it off pass `--print-tree-diff=False`.
|
||||||
|
|
||||||
### News / Changelog Requirement
|
### News / Changelog Requirement
|
||||||
|
|
||||||
`Black` has CI that will check for an entry corresponding to your PR in `CHANGES.md`. If
|
`Black` has CI that will check for an entry corresponding to your PR in `CHANGES.md`. If
|
||||||
you feel this PR does not require a changelog entry please state that in a comment and a
|
you feel this PR does not require a changelog entry please state that in a comment and a
|
||||||
maintainer can add a `skip news` label to make the CI pass. Otherwise, please ensure you
|
maintainer can add a `skip news` label to make the CI pass. Otherwise, please ensure you
|
||||||
have a line in the following format:
|
have a line in the following format added below the appropriate header:
|
||||||
|
|
||||||
```md
|
```md
|
||||||
- `Black` is now more awesome (#X)
|
- `Black` is now more awesome (#X)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!---
|
||||||
|
The Next PR Number link uses HTML because of a bug in MyST-Parser that double-escapes the ampersand, causing the query parameters to not be processed.
|
||||||
|
MyST-Parser issue: https://github.com/executablebooks/MyST-Parser/issues/760
|
||||||
|
MyST-Parser stalled fix PR: https://github.com/executablebooks/MyST-Parser/pull/929
|
||||||
|
-->
|
||||||
|
|
||||||
Note that X should be your PR number, not issue number! To workout X, please use
|
Note that X should be your PR number, not issue number! To workout X, please use
|
||||||
[Next PR Number](https://ichard26.github.io/next-pr-number/?owner=psf&name=black). This
|
<a href="https://ichard26.github.io/next-pr-number/?owner=psf&name=black">Next PR
|
||||||
is not perfect but saves a lot of release overhead as now the releaser does not need to
|
Number</a>. This is not perfect but saves a lot of release overhead as now the releaser
|
||||||
go back and workout what to add to the `CHANGES.md` for each release.
|
does not need to go back and workout what to add to the `CHANGES.md` for each release.
|
||||||
|
|
||||||
### Style Changes
|
### Style Changes
|
||||||
|
|
||||||
If a change would affect the advertised code style, please modify the documentation (The
|
If a change would affect the advertised code style, please modify the documentation (The
|
||||||
_Black_ code style) to reflect that change. Patches that fix unintended bugs in
|
_Black_ code style) to reflect that change. Patches that fix unintended bugs in
|
||||||
formatting don't need to be mentioned separately though.
|
formatting don't need to be mentioned separately though. If the change is implemented
|
||||||
|
with the `--preview` flag, please include the change in the future style document
|
||||||
|
instead and write the changelog entry under the dedicated "Preview style" heading.
|
||||||
|
|
||||||
### Docs Testing
|
### Docs Testing
|
||||||
|
|
||||||
If you make changes to docs, you can test they still build locally too.
|
If you make changes to docs, you can test they still build locally too.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ pip install -r docs/requirements.txt
|
(.venv)$ pip install -r docs/requirements.txt
|
||||||
$ pip install [-e] .[d]
|
(.venv)$ pip install -e ".[d]"
|
||||||
$ sphinx-build -a -b html -W docs/ docs/_build/
|
(.venv)$ sphinx-build -a -b html -W docs/ docs/_build/
|
||||||
```
|
```
|
||||||
|
|
||||||
## black-primer
|
|
||||||
|
|
||||||
`black-primer` is used by CI to pull down well-known _Black_ formatted projects and see
|
|
||||||
if we get source code changes. It will error on formatting changes or errors. Please run
|
|
||||||
before pushing your PR to see if you get the actions you would expect from _Black_ with
|
|
||||||
your PR. You may need to change
|
|
||||||
[primer.json](https://github.com/psf/black/blob/main/src/black_primer/primer.json)
|
|
||||||
configuration for it to pass.
|
|
||||||
|
|
||||||
For more `black-primer` information visit the
|
|
||||||
[documentation](./gauging_changes.md#black-primer).
|
|
||||||
|
|
||||||
## Hygiene
|
## Hygiene
|
||||||
|
|
||||||
If you're fixing a bug, add a test. Run it first to confirm it fails, then fix the bug,
|
If you're fixing a bug, add a test. Run it first to confirm it fails, then fix the bug,
|
||||||
run it again to confirm it's really fixed.
|
and run the test again to confirm it's really fixed.
|
||||||
|
|
||||||
If adding a new feature, add a test. In fact, always add a test. But wait, before adding
|
If adding a new feature, add a test. In fact, always add a test. If adding a large
|
||||||
any large feature, first open an issue for us to discuss the idea first.
|
feature, please first open an issue to discuss it beforehand.
|
||||||
|
|
||||||
## Finally
|
## Finally
|
||||||
|
|
||||||
|
116
docs/faq.md
116
docs/faq.md
@ -5,20 +5,32 @@ The most common questions and issues users face are aggregated to this FAQ.
|
|||||||
```{contents}
|
```{contents}
|
||||||
:local:
|
:local:
|
||||||
:backlinks: none
|
:backlinks: none
|
||||||
|
:class: this-will-duplicate-information-and-it-is-still-useful-here
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Why spaces? I prefer tabs
|
||||||
|
|
||||||
|
PEP 8 recommends spaces over tabs, and they are used by most of the Python community.
|
||||||
|
_Black_ provides no options to configure the indentation style, and requests for such
|
||||||
|
options will not be considered.
|
||||||
|
|
||||||
|
However, we recognise that using tabs is an accessibility issue as well. While the
|
||||||
|
option will never be added to _Black_, visually impaired developers may find conversion
|
||||||
|
tools such as `expand/unexpand` (for Linux) useful when contributing to Python projects.
|
||||||
|
A workflow might consist of e.g. setting up appropriate pre-commit and post-merge git
|
||||||
|
hooks, and scripting `unexpand` to run after applying _Black_.
|
||||||
|
|
||||||
## Does Black have an API?
|
## Does Black have an API?
|
||||||
|
|
||||||
Not yet. _Black_ is fundamentally a command line tool. Many
|
Not yet. _Black_ is fundamentally a command line tool. Many
|
||||||
[integrations](integrations/index.rst) are provided, but a Python interface is not one
|
[integrations](/integrations/index.md) are provided, but a Python interface is not one
|
||||||
of them. A simple API is being [planned](https://github.com/psf/black/issues/779)
|
of them. A simple API is being [planned](https://github.com/psf/black/issues/779)
|
||||||
though.
|
though.
|
||||||
|
|
||||||
## Is Black safe to use?
|
## Is Black safe to use?
|
||||||
|
|
||||||
Yes, for the most part. _Black_ is strictly about formatting, nothing else. But because
|
Yes. _Black_ is strictly about formatting, nothing else. Black strives to ensure that
|
||||||
_Black_ is still in [beta](index.rst), some edges are still a bit rough. To combat
|
after formatting the AST is
|
||||||
issues, the equivalence of code after formatting is
|
|
||||||
[checked](the_black_code_style/current_style.md#ast-before-and-after-formatting) with
|
[checked](the_black_code_style/current_style.md#ast-before-and-after-formatting) with
|
||||||
limited special cases where the code is allowed to differ. If issues are found, an error
|
limited special cases where the code is allowed to differ. If issues are found, an error
|
||||||
is raised and the file is left untouched. Magical comments that influence linters and
|
is raised and the file is left untouched. Magical comments that influence linters and
|
||||||
@ -26,10 +38,13 @@ other tools, such as `# noqa`, may be moved by _Black_. See below for more detai
|
|||||||
|
|
||||||
## How stable is Black's style?
|
## How stable is Black's style?
|
||||||
|
|
||||||
Quite stable. _Black_ aims to enforce one style and one style only, with some room for
|
Stable. _Black_ aims to enforce one style and one style only, with some room for
|
||||||
pragmatism. However, _Black_ is still in beta so style changes are both planned and
|
pragmatism. See [The Black Code Style](the_black_code_style/index.md) for more details.
|
||||||
still proposed on the issue tracker. See
|
|
||||||
[The Black Code Style](the_black_code_style/index.rst) for more details.
|
Starting in 2022, the formatting output is stable for the releases made in the same year
|
||||||
|
(other than unintentional bugs). At the beginning of every year, the first release will
|
||||||
|
make changes to the stable style. It is possible to opt in to the latest formatting
|
||||||
|
styles using the `--preview` flag.
|
||||||
|
|
||||||
## Why is my file not formatted?
|
## Why is my file not formatted?
|
||||||
|
|
||||||
@ -37,20 +52,51 @@ Most likely because it is ignored in `.gitignore` or excluded with configuration
|
|||||||
[file collection and discovery](usage_and_configuration/file_collection_and_discovery.md)
|
[file collection and discovery](usage_and_configuration/file_collection_and_discovery.md)
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
## Why are Flake8's E203 and W503 violated?
|
## Why is my Jupyter Notebook cell not formatted?
|
||||||
|
|
||||||
Because they go against PEP 8. E203 falsely triggers on list
|
_Black_ is timid about formatting Jupyter Notebooks. Cells containing any of the
|
||||||
[slices](the_black_code_style/current_style.md#slices), and adhering to W503 hinders
|
following will not be formatted:
|
||||||
readability because operators are misaligned. Disable W503 and enable the
|
|
||||||
disabled-by-default counterpart W504. E203 should be disabled while changes are still
|
|
||||||
[discussed](https://github.com/PyCQA/pycodestyle/issues/373).
|
|
||||||
|
|
||||||
## Does Black support Python 2?
|
- automagics (e.g. `pip install black`)
|
||||||
|
- non-Python cell magics (e.g. `%%writefile`). These can be added with the flag
|
||||||
|
`--python-cell-magics`, e.g. `black --python-cell-magics writefile hello.ipynb`.
|
||||||
|
- multiline magics, e.g.:
|
||||||
|
|
||||||
For formatting, yes! [Install](getting_started.md#installation) with the `python2` extra
|
```python
|
||||||
to format Python 2 files too! There are no current plans to drop support, but most
|
%timeit f(1, \
|
||||||
likely it is bound to happen. Sometime. Eventually. In terms of running _Black_ though,
|
2, \
|
||||||
Python 3.6 or newer is required.
|
3)
|
||||||
|
```
|
||||||
|
|
||||||
|
- code which `IPython`'s `TransformerManager` would transform magics into, e.g.:
|
||||||
|
|
||||||
|
```python
|
||||||
|
get_ipython().system('ls')
|
||||||
|
```
|
||||||
|
|
||||||
|
- invalid syntax, as it can't be safely distinguished from automagics in the absence of
|
||||||
|
a running `IPython` kernel.
|
||||||
|
|
||||||
|
## Why does Flake8 report warnings?
|
||||||
|
|
||||||
|
Some of Flake8's rules conflict with Black's style. We recommend disabling these rules.
|
||||||
|
See [Using _Black_ with other tools](labels/why-pycodestyle-warnings).
|
||||||
|
|
||||||
|
## Which Python versions does Black support?
|
||||||
|
|
||||||
|
_Black_ generally supports all Python versions supported by CPython (see
|
||||||
|
[the Python devguide](https://devguide.python.org/versions/) for current information).
|
||||||
|
We promise to support at least all Python versions that have not reached their end of
|
||||||
|
life. This is the case for both running _Black_ and formatting code.
|
||||||
|
|
||||||
|
Support for formatting Python 2 code was removed in version 22.0. While we've made no
|
||||||
|
plans to stop supporting older Python 3 minor versions immediately, their support might
|
||||||
|
also be removed some time in the future without a deprecation period.
|
||||||
|
|
||||||
|
`await`/`async` as soft keywords/indentifiers are no longer supported as of 25.2.0.
|
||||||
|
|
||||||
|
Runtime support for 3.6 was removed in version 22.10.0, for 3.7 in version 23.7.0, and
|
||||||
|
for 3.8 in version 24.10.0.
|
||||||
|
|
||||||
## Why does my linter or typechecker complain after I format my code?
|
## Why does my linter or typechecker complain after I format my code?
|
||||||
|
|
||||||
@ -59,3 +105,35 @@ influence their behavior. While Black does its best to recognize such comments a
|
|||||||
them in the right place, this detection is not and cannot be perfect. Therefore, you'll
|
them in the right place, this detection is not and cannot be perfect. Therefore, you'll
|
||||||
sometimes have to manually move these comments to the right place after you format your
|
sometimes have to manually move these comments to the right place after you format your
|
||||||
codebase with _Black_.
|
codebase with _Black_.
|
||||||
|
|
||||||
|
## Can I run Black with PyPy?
|
||||||
|
|
||||||
|
Yes, there is support for PyPy 3.8 and higher.
|
||||||
|
|
||||||
|
## Why does Black not detect syntax errors in my code?
|
||||||
|
|
||||||
|
_Black_ is an autoformatter, not a Python linter or interpreter. Detecting all syntax
|
||||||
|
errors is not a goal. It can format all code accepted by CPython (if you find an example
|
||||||
|
where that doesn't hold, please report a bug!), but it may also format some code that
|
||||||
|
CPython doesn't accept.
|
||||||
|
|
||||||
|
(labels/mypyc-support)=
|
||||||
|
|
||||||
|
## What is `compiled: yes/no` all about in the version output?
|
||||||
|
|
||||||
|
While _Black_ is indeed a pure Python project, we use [mypyc] to compile _Black_ into a
|
||||||
|
C Python extension, usually doubling performance. These compiled wheels are available
|
||||||
|
for 64-bit versions of Windows, Linux (via the manylinux standard), and macOS across all
|
||||||
|
supported CPython versions.
|
||||||
|
|
||||||
|
Platforms including musl-based and/or ARM Linux distributions, and ARM Windows are
|
||||||
|
currently **not** supported. These platforms will fall back to the slower pure Python
|
||||||
|
wheel available on PyPI.
|
||||||
|
|
||||||
|
If you are experiencing exceptionally weird issues or even segfaults, you can try
|
||||||
|
passing `--no-binary black` to your pip install invocation. This flag excludes all
|
||||||
|
wheels (including the pure Python wheel), so this command will use the [sdist].
|
||||||
|
|
||||||
|
[mypyc]: https://mypyc.readthedocs.io/en/latest/
|
||||||
|
[sdist]:
|
||||||
|
https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist
|
||||||
|
@ -16,13 +16,14 @@ Also, you can try out _Black_ online for minimal fuss on the
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
_Black_ can be installed by running `pip install black`. It requires Python 3.6.2+ to
|
_Black_ can be installed by running `pip install black`. It requires Python 3.9+ to run.
|
||||||
run, but can format Python 2 code too. Python 2 support needs the `typed_ast`
|
If you want to format Jupyter Notebooks, install with `pip install "black[jupyter]"`.
|
||||||
dependency, which be installed with `pip install black[python2]`.
|
|
||||||
|
If you use pipx, you can install Black with `pipx install black`.
|
||||||
|
|
||||||
If you can't wait for the latest _hotness_ and want to install from GitHub, use:
|
If you can't wait for the latest _hotness_ and want to install from GitHub, use:
|
||||||
|
|
||||||
`pip install git+git://github.com/psf/black`
|
`pip install git+https://github.com/psf/black`
|
||||||
|
|
||||||
## Basic usage
|
## Basic usage
|
||||||
|
|
||||||
|
16
docs/guides/index.md
Normal file
16
docs/guides/index.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Guides
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
hidden:
|
||||||
|
---
|
||||||
|
|
||||||
|
introducing_black_to_your_project
|
||||||
|
using_black_with_other_tools
|
||||||
|
```
|
||||||
|
|
||||||
|
Wondering how to do something specific? You've found the right place! Listed below are
|
||||||
|
topic specific guides available:
|
||||||
|
|
||||||
|
- {doc}`introducing_black_to_your_project`
|
||||||
|
- {doc}`using_black_with_other_tools`
|
@ -1,14 +0,0 @@
|
|||||||
Guides
|
|
||||||
======
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
introducing_black_to_your_project
|
|
||||||
using_black_with_other_tools
|
|
||||||
|
|
||||||
Wondering how to do something specific? You've found the right place! Listed below
|
|
||||||
are topic specific guides available:
|
|
||||||
|
|
||||||
- :doc:`introducing_black_to_your_project`
|
|
||||||
- :doc:`using_black_with_other_tools`
|
|
@ -18,7 +18,8 @@ previous revision that modified those lines.
|
|||||||
|
|
||||||
So when migrating your project's code style to _Black_, reformat everything and commit
|
So when migrating your project's code style to _Black_, reformat everything and commit
|
||||||
the changes (preferably in one massive commit). Then put the full 40 characters commit
|
the changes (preferably in one massive commit). Then put the full 40 characters commit
|
||||||
identifier(s) into a file.
|
identifier(s) into a file usually called `.git-blame-ignore-revs` at the root of your
|
||||||
|
project directory.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
# Migrate code style to Black
|
# Migrate code style to Black
|
||||||
@ -43,8 +44,9 @@ call to `git blame`.
|
|||||||
$ git config blame.ignoreRevsFile .git-blame-ignore-revs
|
$ git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||||
```
|
```
|
||||||
|
|
||||||
**The one caveat is that GitHub and GitLab do not yet support ignoring revisions using
|
**The one caveat is that some online Git-repositories like GitLab do not yet support
|
||||||
their native UI of blame.** So blame information will be cluttered with a reformatting
|
ignoring revisions using their native blame UI.** So blame information will be cluttered
|
||||||
commit on those platforms. (If you'd like this feature, there's an open issue for
|
with a reformatting commit on those platforms. (If you'd like this feature, there's an
|
||||||
[GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/31423) and please let GitHub
|
open issue for [GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/31423)).
|
||||||
know!)
|
[GitHub supports `.git-blame-ignore-revs`](https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view)
|
||||||
|
by default in blame views however.
|
||||||
|
@ -24,10 +24,10 @@ to conflicting changes.
|
|||||||
#### Profile
|
#### Profile
|
||||||
|
|
||||||
Since version 5.0.0, isort supports
|
Since version 5.0.0, isort supports
|
||||||
[profiles](https://pycqa.github.io/isort/docs/configuration/profiles/) to allow easy
|
[profiles](https://pycqa.github.io/isort/docs/configuration/profiles.html) to allow easy
|
||||||
interoperability with common code styles. You can set the black profile in any of the
|
interoperability with common code styles. You can set the black profile in any of the
|
||||||
[config files](https://pycqa.github.io/isort/docs/configuration/config_files/) supported
|
[config files](https://pycqa.github.io/isort/docs/configuration/config_files.html)
|
||||||
by isort. Below, an example for `pyproject.toml`:
|
supported by isort. Below, an example for `pyproject.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[tool.isort]
|
[tool.isort]
|
||||||
@ -51,9 +51,9 @@ line_length = 88
|
|||||||
|
|
||||||
#### Why those options above?
|
#### Why those options above?
|
||||||
|
|
||||||
_Black_ wraps imports that surpass `line-length` by moving identifiers into their own
|
_Black_ wraps imports that surpass `line-length` by moving identifiers onto separate
|
||||||
indented line. If that still doesn't fit the bill, it will put all of them in separate
|
lines and by adding a trailing comma after each. A more detailed explanation of this
|
||||||
lines and put a trailing comma. A more detailed explanation of this behaviour can be
|
behaviour can be
|
||||||
[found here](../the_black_code_style/current_style.md#how-black-wraps-lines).
|
[found here](../the_black_code_style/current_style.md#how-black-wraps-lines).
|
||||||
|
|
||||||
isort's default mode of wrapping imports that extend past the `line_length` limit is
|
isort's default mode of wrapping imports that extend past the `line_length` limit is
|
||||||
@ -97,7 +97,7 @@ does not break older versions so you can keep it if you are running previous ver
|
|||||||
<details>
|
<details>
|
||||||
<summary>.isort.cfg</summary>
|
<summary>.isort.cfg</summary>
|
||||||
|
|
||||||
```cfg
|
```ini
|
||||||
[settings]
|
[settings]
|
||||||
profile = black
|
profile = black
|
||||||
```
|
```
|
||||||
@ -107,7 +107,7 @@ profile = black
|
|||||||
<details>
|
<details>
|
||||||
<summary>setup.cfg</summary>
|
<summary>setup.cfg</summary>
|
||||||
|
|
||||||
```cfg
|
```ini
|
||||||
[isort]
|
[isort]
|
||||||
profile = black
|
profile = black
|
||||||
```
|
```
|
||||||
@ -134,10 +134,10 @@ profile = black
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Flake8
|
### pycodestyle
|
||||||
|
|
||||||
[Flake8](https://pypi.org/p/flake8/) is a code linter. It warns you of syntax errors,
|
[pycodestyle](https://pycodestyle.pycqa.org/) is a code linter. It warns you of syntax
|
||||||
possible bugs, stylistic errors, etc. For the most part, Flake8 follows
|
errors, possible bugs, stylistic errors, etc. For the most part, pycodestyle follows
|
||||||
[PEP 8](https://www.python.org/dev/peps/pep-0008/) when warning about stylistic errors.
|
[PEP 8](https://www.python.org/dev/peps/pep-0008/) when warning about stylistic errors.
|
||||||
There are a few deviations that cause incompatibilities with _Black_.
|
There are a few deviations that cause incompatibilities with _Black_.
|
||||||
|
|
||||||
@ -145,96 +145,129 @@ There are a few deviations that cause incompatibilities with _Black_.
|
|||||||
|
|
||||||
```
|
```
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203
|
ignore = E203,E701
|
||||||
```
|
```
|
||||||
|
|
||||||
|
(labels/why-pycodestyle-warnings)=
|
||||||
|
|
||||||
#### Why those options above?
|
#### Why those options above?
|
||||||
|
|
||||||
|
##### `max-line-length`
|
||||||
|
|
||||||
|
As with isort, pycodestyle should be configured to allow lines up to the length limit of
|
||||||
|
`88`, _Black_'s default.
|
||||||
|
|
||||||
|
##### `E203`
|
||||||
|
|
||||||
In some cases, as determined by PEP 8, _Black_ will enforce an equal amount of
|
In some cases, as determined by PEP 8, _Black_ will enforce an equal amount of
|
||||||
whitespace around slice operators. Due to this, Flake8 will raise
|
whitespace around slice operators. Due to this, pycodestyle will raise
|
||||||
`E203 whitespace before ':'` warnings. Since this warning is not PEP 8 compliant, Flake8
|
`E203 whitespace before ':'` warnings. Since this warning is not PEP 8 compliant, it
|
||||||
should be configured to ignore it via `extend-ignore = E203`.
|
should be disabled.
|
||||||
|
|
||||||
|
##### `E701` / `E704`
|
||||||
|
|
||||||
|
_Black_ will collapse implementations of classes and functions consisting solely of `..`
|
||||||
|
to a single line. This matches how such examples are formatted in PEP 8. It remains true
|
||||||
|
that in all other cases Black will prevent multiple statements on the same line, in
|
||||||
|
accordance with PEP 8 generally discouraging this.
|
||||||
|
|
||||||
|
However, `pycodestyle` does not mirror this logic and may raise
|
||||||
|
`E701 multiple statements on one line (colon)` in this situation. Its
|
||||||
|
disabled-by-default `E704 multiple statements on one line (def)` rule may also raise
|
||||||
|
warnings and should not be enabled.
|
||||||
|
|
||||||
|
##### `W503`
|
||||||
|
|
||||||
When breaking a line, _Black_ will break it before a binary operator. This is compliant
|
When breaking a line, _Black_ will break it before a binary operator. This is compliant
|
||||||
with PEP 8 as of
|
with PEP 8 as of
|
||||||
[April 2016](https://github.com/python/peps/commit/c59c4376ad233a62ca4b3a6060c81368bd21e85b#diff-64ec08cc46db7540f18f2af46037f599).
|
[April 2016](https://github.com/python/peps/commit/c59c4376ad233a62ca4b3a6060c81368bd21e85b#diff-64ec08cc46db7540f18f2af46037f599).
|
||||||
There's a disabled-by-default warning in Flake8 which goes against this PEP 8
|
There's a disabled-by-default warning in Flake8 which goes against this PEP 8
|
||||||
recommendation called `W503 line break before binary operator`. It should not be enabled
|
recommendation called `W503 line break before binary operator`. It should not be enabled
|
||||||
in your configuration.
|
in your configuration. You can use its counterpart
|
||||||
|
`W504 line break after binary operator` instead.
|
||||||
Also, as like with isort, flake8 should be configured to allow lines up to the length
|
|
||||||
limit of `88`, _Black_'s default. This explains `max-line-length = 88`.
|
|
||||||
|
|
||||||
#### Formats
|
#### Formats
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>.flake8</summary>
|
<summary>setup.cfg, .pycodestyle, tox.ini</summary>
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[flake8]
|
[pycodestyle]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203
|
ignore = E203,E701
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
### Flake8
|
||||||
<summary>setup.cfg</summary>
|
|
||||||
|
|
||||||
```cfg
|
[Flake8](https://pypi.org/p/flake8/) is a wrapper around multiple linters, including
|
||||||
|
pycodestyle. As such, it has many of the same issues.
|
||||||
|
|
||||||
|
#### Bugbear
|
||||||
|
|
||||||
|
It's recommended to use [the Bugbear plugin](https://github.com/PyCQA/flake8-bugbear)
|
||||||
|
and enable
|
||||||
|
[its B950 check](https://github.com/PyCQA/flake8-bugbear#opinionated-warnings#:~:text=you%20expect%20it.-,B950,-%3A%20Line%20too%20long)
|
||||||
|
instead of using Flake8's E501, because it aligns with
|
||||||
|
[Black's 10% rule](labels/line-length).
|
||||||
|
|
||||||
|
Install Bugbear and use the following config:
|
||||||
|
|
||||||
|
```
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 80
|
||||||
extend-ignore = E203
|
extend-select = B950
|
||||||
|
extend-ignore = E203,E501,E701
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
#### Minimal Configuration
|
||||||
|
|
||||||
|
In cases where you can't or don't want to install Bugbear, you can use this minimally
|
||||||
|
compatible config:
|
||||||
|
|
||||||
|
```
|
||||||
|
[flake8]
|
||||||
|
max-line-length = 88
|
||||||
|
extend-ignore = E203,E701
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Why those options above?
|
||||||
|
|
||||||
|
See [the pycodestyle section](labels/why-pycodestyle-warnings) above.
|
||||||
|
|
||||||
|
#### Formats
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>tox.ini</summary>
|
<summary>.flake8, setup.cfg, tox.ini</summary>
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203
|
extend-ignore = E203,E701
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Pylint
|
### Pylint
|
||||||
|
|
||||||
[Pylint](https://pypi.org/p/pylint/) is also a code linter like Flake8. It has the same
|
[Pylint](https://pypi.org/p/pylint/) is also a code linter like Flake8. It has many of
|
||||||
checks as flake8 and more. In particular, it has more formatting checks regarding style
|
the same checks as Flake8 and more. It particularly has more formatting checks regarding
|
||||||
conventions like variable naming. With so many checks, Pylint is bound to have some
|
style conventions like variable naming.
|
||||||
mixed feelings about _Black_'s formatting style.
|
|
||||||
|
|
||||||
#### Configuration
|
#### Configuration
|
||||||
|
|
||||||
```
|
```
|
||||||
disable = C0330, C0326
|
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Why those options above?
|
#### Why those options above?
|
||||||
|
|
||||||
When _Black_ is folding very long expressions, the closing brackets will
|
Pylint should be configured to only complain about lines that surpass `88` characters
|
||||||
[be dedented](../the_black_code_style/current_style.md#how-black-wraps-lines).
|
via `max-line-length = 88`.
|
||||||
|
|
||||||
```py3
|
If using `pylint<2.6.0`, also disable `C0326` and `C0330` as these are incompatible with
|
||||||
ImportantClass.important_method(
|
_Black_ formatting and have since been removed.
|
||||||
exc, limit, lookup_lines, capture_locals, callback
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
Although this style is PEP 8 compliant, Pylint will raise
|
|
||||||
`C0330: Wrong hanging indentation before block (add 4 spaces)` warnings. Since _Black_
|
|
||||||
isn't configurable on this style, Pylint should be told to ignore these warnings via
|
|
||||||
`disable = C0330`.
|
|
||||||
|
|
||||||
Also, since _Black_ deals with whitespace around operators and brackets, Pylint's
|
|
||||||
warning `C0326: Bad whitespace` should be disabled using `disable = C0326`.
|
|
||||||
|
|
||||||
And as usual, Pylint should be configured to only complain about lines that surpass `88`
|
|
||||||
characters via `max-line-length = 88`.
|
|
||||||
|
|
||||||
#### Formats
|
#### Formats
|
||||||
|
|
||||||
@ -242,9 +275,6 @@ characters via `max-line-length = 88`.
|
|||||||
<summary>pylintrc</summary>
|
<summary>pylintrc</summary>
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[MESSAGES CONTROL]
|
|
||||||
disable = C0330, C0326
|
|
||||||
|
|
||||||
[format]
|
[format]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
```
|
```
|
||||||
@ -257,9 +287,6 @@ max-line-length = 88
|
|||||||
```cfg
|
```cfg
|
||||||
[pylint]
|
[pylint]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
|
|
||||||
[pylint.messages_control]
|
|
||||||
disable = C0330, C0326
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
@ -268,9 +295,6 @@ disable = C0330, C0326
|
|||||||
<summary>pyproject.toml</summary>
|
<summary>pyproject.toml</summary>
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[tool.pylint.messages_control]
|
|
||||||
disable = "C0330, C0326"
|
|
||||||
|
|
||||||
[tool.pylint.format]
|
[tool.pylint.format]
|
||||||
max-line-length = "88"
|
max-line-length = "88"
|
||||||
```
|
```
|
||||||
|
139
docs/index.md
Normal file
139
docs/index.md
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<!--
|
||||||
|
black documentation master file, created by
|
||||||
|
sphinx-quickstart on Fri Mar 23 10:53:30 2018.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# The uncompromising code formatter
|
||||||
|
|
||||||
|
> “Any color you like.”
|
||||||
|
|
||||||
|
By using _Black_, you agree to cede control over minutiae of hand-formatting. In return,
|
||||||
|
_Black_ gives you speed, determinism, and freedom from `pycodestyle` nagging about
|
||||||
|
formatting. You will save time and mental energy for more important matters.
|
||||||
|
|
||||||
|
_Black_ makes code review faster by producing the smallest diffs possible. Blackened
|
||||||
|
code looks the same regardless of the project you're reading. Formatting becomes
|
||||||
|
transparent after a while and you can focus on the content instead.
|
||||||
|
|
||||||
|
Try it out now using the [Black Playground](https://black.vercel.app).
|
||||||
|
|
||||||
|
```{admonition} Note - Black is now stable!
|
||||||
|
*Black* is [successfully used](https://github.com/psf/black#used-by) by
|
||||||
|
many projects, small and big. *Black* has a comprehensive test suite, with efficient
|
||||||
|
parallel tests, our own auto formatting and parallel Continuous Integration runner.
|
||||||
|
Now that we have become stable, you should not expect large changes to formatting in
|
||||||
|
the future. Stylistic changes will mostly be responses to bug reports and support for new Python
|
||||||
|
syntax.
|
||||||
|
|
||||||
|
Also, as a safety measure which slows down processing, *Black* will check that the
|
||||||
|
reformatted code still produces a valid AST that is effectively equivalent to the
|
||||||
|
original (see the
|
||||||
|
[Pragmatism](./the_black_code_style/current_style.md#pragmatism)
|
||||||
|
section for details). If you're feeling confident, use `--fast`.
|
||||||
|
```
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
{doc}`Black is licensed under the MIT license <license>`.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testimonials
|
||||||
|
|
||||||
|
**Mike Bayer**, author of [SQLAlchemy](https://www.sqlalchemy.org/):
|
||||||
|
|
||||||
|
> _I can't think of any single tool in my entire programming career that has given me a
|
||||||
|
> bigger productivity increase by its introduction. I can now do refactorings in about
|
||||||
|
> 1% of the keystrokes that it would have taken me previously when we had no way for
|
||||||
|
> code to format itself._
|
||||||
|
|
||||||
|
**Dusty Phillips**,
|
||||||
|
[writer](https://smile.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=dusty+phillips):
|
||||||
|
|
||||||
|
> _Black is opinionated so you don't have to be._
|
||||||
|
|
||||||
|
**Hynek Schlawack**, creator of [attrs](https://www.attrs.org/), core developer of
|
||||||
|
Twisted and CPython:
|
||||||
|
|
||||||
|
> _An auto-formatter that doesn't suck is all I want for Xmas!_
|
||||||
|
|
||||||
|
**Carl Meyer**, [Django](https://www.djangoproject.com/) core developer:
|
||||||
|
|
||||||
|
> _At least the name is good._
|
||||||
|
|
||||||
|
**Kenneth Reitz**, creator of [requests](http://python-requests.org/) and
|
||||||
|
[pipenv](https://docs.pipenv.org/):
|
||||||
|
|
||||||
|
> _This vastly improves the formatting of our code. Thanks a ton!_
|
||||||
|
|
||||||
|
## Show your style
|
||||||
|
|
||||||
|
Use the badge in your project's README.md:
|
||||||
|
|
||||||
|
```md
|
||||||
|
[](https://github.com/psf/black)
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the badge in README.rst:
|
||||||
|
|
||||||
|
```rst
|
||||||
|
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||||
|
:target: https://github.com/psf/black
|
||||||
|
```
|
||||||
|
|
||||||
|
Looks like this:
|
||||||
|
|
||||||
|
```{image} https://img.shields.io/badge/code%20style-black-000000.svg
|
||||||
|
:target: https://github.com/psf/black
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
maxdepth: 3
|
||||||
|
includehidden:
|
||||||
|
---
|
||||||
|
|
||||||
|
the_black_code_style/index
|
||||||
|
```
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
maxdepth: 3
|
||||||
|
includehidden:
|
||||||
|
caption: User Guide
|
||||||
|
---
|
||||||
|
|
||||||
|
getting_started
|
||||||
|
usage_and_configuration/index
|
||||||
|
integrations/index
|
||||||
|
guides/index
|
||||||
|
faq
|
||||||
|
```
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
maxdepth: 2
|
||||||
|
includehidden:
|
||||||
|
caption: Development
|
||||||
|
---
|
||||||
|
|
||||||
|
contributing/index
|
||||||
|
change_log
|
||||||
|
authors
|
||||||
|
```
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
hidden:
|
||||||
|
caption: Project Links
|
||||||
|
---
|
||||||
|
|
||||||
|
GitHub <https://github.com/psf/black>
|
||||||
|
PyPI <https://pypi.org/project/black>
|
||||||
|
Chat <https://discord.gg/RtVdv86PrH>
|
||||||
|
```
|
||||||
|
|
||||||
|
# Indices and tables
|
||||||
|
|
||||||
|
- {ref}`genindex`
|
||||||
|
- {ref}`search`
|
128
docs/index.rst
128
docs/index.rst
@ -1,128 +0,0 @@
|
|||||||
.. black documentation master file, created by
|
|
||||||
sphinx-quickstart on Fri Mar 23 10:53:30 2018.
|
|
||||||
|
|
||||||
The uncompromising code formatter
|
|
||||||
=================================
|
|
||||||
|
|
||||||
By using *Black*, you agree to cede control over minutiae of
|
|
||||||
hand-formatting. In return, *Black* gives you speed, determinism, and
|
|
||||||
freedom from `pycodestyle` nagging about formatting. You will save time
|
|
||||||
and mental energy for more important matters.
|
|
||||||
|
|
||||||
*Black* makes code review faster by producing the smallest diffs
|
|
||||||
possible. Blackened code looks the same regardless of the project
|
|
||||||
you're reading. Formatting becomes transparent after a while and you
|
|
||||||
can focus on the content instead.
|
|
||||||
|
|
||||||
Try it out now using the `Black Playground <https://black.vercel.app>`_.
|
|
||||||
|
|
||||||
.. admonition:: Note - this is a beta product
|
|
||||||
|
|
||||||
*Black* is already `successfully used <https://github.com/psf/black#used-by>`_ by
|
|
||||||
many projects, small and big. *Black* has a comprehensive test suite, with efficient
|
|
||||||
parallel tests, our own auto formatting and parallel Continuous Integration runner.
|
|
||||||
However, *Black* is still beta. Things will probably be wonky for a while. This is
|
|
||||||
made explicit by the "Beta" trove classifier, as well as by the "b" in the version
|
|
||||||
number. What this means for you is that **until the formatter becomes stable, you
|
|
||||||
should expect some formatting to change in the future**. That being said, no drastic
|
|
||||||
stylistic changes are planned, mostly responses to bug reports.
|
|
||||||
|
|
||||||
Also, as a safety measure which slows down processing, *Black* will check that the
|
|
||||||
reformatted code still produces a valid AST that is effectively equivalent to the
|
|
||||||
original (see the
|
|
||||||
`Pragmatism <./the_black_code_style/current_style.html#pragmatism>`_
|
|
||||||
section for details). If you're feeling confident, use ``--fast``.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
:doc:`Black is licensed under the MIT license <license>`.
|
|
||||||
|
|
||||||
Testimonials
|
|
||||||
------------
|
|
||||||
|
|
||||||
**Mike Bayer**, author of `SQLAlchemy <https://www.sqlalchemy.org/>`_:
|
|
||||||
|
|
||||||
*I can't think of any single tool in my entire programming career that has given me a
|
|
||||||
bigger productivity increase by its introduction. I can now do refactorings in about
|
|
||||||
1% of the keystrokes that it would have taken me previously when we had no way for
|
|
||||||
code to format itself.*
|
|
||||||
|
|
||||||
**Dusty Phillips**, `writer <https://smile.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=dusty+phillips>`_:
|
|
||||||
|
|
||||||
*Black is opinionated so you don't have to be.*
|
|
||||||
|
|
||||||
**Hynek Schlawack**, creator of `attrs <https://www.attrs.org/>`_, core
|
|
||||||
developer of Twisted and CPython:
|
|
||||||
|
|
||||||
*An auto-formatter that doesn't suck is all I want for Xmas!*
|
|
||||||
|
|
||||||
**Carl Meyer**, `Django <https://www.djangoproject.com/>`_ core developer:
|
|
||||||
|
|
||||||
*At least the name is good.*
|
|
||||||
|
|
||||||
**Kenneth Reitz**, creator of `requests <http://python-requests.org/>`_
|
|
||||||
and `pipenv <https://docs.pipenv.org/>`_:
|
|
||||||
|
|
||||||
*This vastly improves the formatting of our code. Thanks a ton!*
|
|
||||||
|
|
||||||
|
|
||||||
Show your style
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Use the badge in your project's README.md:
|
|
||||||
|
|
||||||
.. code-block:: md
|
|
||||||
|
|
||||||
[](https://github.com/psf/black)
|
|
||||||
|
|
||||||
|
|
||||||
Using the badge in README.rst:
|
|
||||||
|
|
||||||
.. code-block:: rst
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
|
||||||
:target: https://github.com/psf/black
|
|
||||||
|
|
||||||
Looks like this:
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
|
||||||
:target: https://github.com/psf/black
|
|
||||||
|
|
||||||
Contents
|
|
||||||
--------
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 3
|
|
||||||
:includehidden:
|
|
||||||
|
|
||||||
the_black_code_style/index
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 3
|
|
||||||
:includehidden:
|
|
||||||
|
|
||||||
getting_started
|
|
||||||
usage_and_configuration/index
|
|
||||||
integrations/index
|
|
||||||
guides/index
|
|
||||||
faq
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 3
|
|
||||||
:includehidden:
|
|
||||||
|
|
||||||
contributing/index
|
|
||||||
change_log
|
|
||||||
authors
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
GitHub ↪ <https://github.com/psf/black>
|
|
||||||
PyPI ↪ <https://pypi.org/project/black>
|
|
||||||
IRC ↪ <https://webchat.freenode.net/?channels=%23blackformatter>
|
|
||||||
|
|
||||||
Indices and tables
|
|
||||||
==================
|
|
||||||
|
|
||||||
* :ref:`genindex`
|
|
||||||
* :ref:`search`
|
|
@ -10,6 +10,67 @@ Options include the following:
|
|||||||
|
|
||||||
## PyCharm/IntelliJ IDEA
|
## PyCharm/IntelliJ IDEA
|
||||||
|
|
||||||
|
There are several different ways you can use _Black_ from PyCharm:
|
||||||
|
|
||||||
|
1. Using the built-in _Black_ integration (PyCharm 2023.2 and later). This option is the
|
||||||
|
simplest to set up.
|
||||||
|
1. As local server using the BlackConnect plugin. This option formats the fastest. It
|
||||||
|
spins up {doc}`Black's HTTP server </usage_and_configuration/black_as_a_server>`, to
|
||||||
|
avoid the startup cost on subsequent formats.
|
||||||
|
1. As external tool.
|
||||||
|
1. As file watcher.
|
||||||
|
|
||||||
|
### Built-in _Black_ integration
|
||||||
|
|
||||||
|
1. Install `black`.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pip install black
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Go to `Preferences or Settings -> Tools -> Black` and configure _Black_ to your
|
||||||
|
liking.
|
||||||
|
|
||||||
|
### As local server
|
||||||
|
|
||||||
|
1. Install _Black_ with the `d` extra.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pip install 'black[d]'
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Install
|
||||||
|
[BlackConnect IntelliJ IDEs plugin](https://plugins.jetbrains.com/plugin/14321-blackconnect).
|
||||||
|
|
||||||
|
1. Open plugin configuration in PyCharm/IntelliJ IDEA
|
||||||
|
|
||||||
|
On macOS:
|
||||||
|
|
||||||
|
`PyCharm -> Preferences -> Tools -> BlackConnect`
|
||||||
|
|
||||||
|
On Windows / Linux / BSD:
|
||||||
|
|
||||||
|
`File -> Settings -> Tools -> BlackConnect`
|
||||||
|
|
||||||
|
1. In `Local Instance (shared between projects)` section:
|
||||||
|
|
||||||
|
1. Check `Start local blackd instance when plugin loads`.
|
||||||
|
1. Press the `Detect` button near `Path` input. The plugin should detect the `blackd`
|
||||||
|
executable.
|
||||||
|
|
||||||
|
1. In `Trigger Settings` section check `Trigger on code reformat` to enable code
|
||||||
|
reformatting with _Black_.
|
||||||
|
|
||||||
|
1. Format the currently opened file by selecting `Code -> Reformat Code` or using a
|
||||||
|
shortcut.
|
||||||
|
|
||||||
|
1. Optionally, to run _Black_ on every file save:
|
||||||
|
|
||||||
|
- In `Trigger Settings` section of plugin configuration check
|
||||||
|
`Trigger when saving changed files`.
|
||||||
|
|
||||||
|
### As external tool
|
||||||
|
|
||||||
1. Install `black`.
|
1. Install `black`.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
@ -57,29 +118,7 @@ Options include the following:
|
|||||||
- Alternatively, you can set a keyboard shortcut by navigating to
|
- Alternatively, you can set a keyboard shortcut by navigating to
|
||||||
`Preferences or Settings -> Keymap -> External Tools -> External Tools - Black`.
|
`Preferences or Settings -> Keymap -> External Tools -> External Tools - Black`.
|
||||||
|
|
||||||
1. Optionally, run _Black_ on every file save:
|
### As file watcher
|
||||||
|
|
||||||
1. Make sure you have the
|
|
||||||
[File Watchers](https://plugins.jetbrains.com/plugin/7177-file-watchers) plugin
|
|
||||||
installed.
|
|
||||||
1. Go to `Preferences or Settings -> Tools -> File Watchers` and click `+` to add a
|
|
||||||
new watcher:
|
|
||||||
- Name: Black
|
|
||||||
- File type: Python
|
|
||||||
- Scope: Project Files
|
|
||||||
- Program: \<install_location_from_step_2>
|
|
||||||
- Arguments: `$FilePath$`
|
|
||||||
- Output paths to refresh: `$FilePath$`
|
|
||||||
- Working directory: `$ProjectFileDir$`
|
|
||||||
|
|
||||||
- In Advanced Options
|
|
||||||
- Uncheck "Auto-save edited files to trigger the watcher"
|
|
||||||
- Uncheck "Trigger the watcher on external changes"
|
|
||||||
|
|
||||||
## Wing IDE
|
|
||||||
|
|
||||||
Wing supports black via the OS Commands tool, as explained in the Wing documentation on
|
|
||||||
[pep8 formatting](https://wingware.com/doc/edit/pep8). The detailed procedure is:
|
|
||||||
|
|
||||||
1. Install `black`.
|
1. Install `black`.
|
||||||
|
|
||||||
@ -87,27 +126,89 @@ Wing supports black via the OS Commands tool, as explained in the Wing documenta
|
|||||||
$ pip install black
|
$ pip install black
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Make sure it runs from the command line, e.g.
|
1. Locate your `black` installation folder.
|
||||||
|
|
||||||
|
On macOS / Linux / BSD:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ black --help
|
$ which black
|
||||||
|
/usr/local/bin/black # possible location
|
||||||
```
|
```
|
||||||
|
|
||||||
1. In Wing IDE, activate the **OS Commands** panel and define the command **black** to
|
On Windows:
|
||||||
execute black on the currently selected file:
|
|
||||||
|
|
||||||
- Use the Tools -> OS Commands menu selection
|
```console
|
||||||
- click on **+** in **OS Commands** -> New: Command line..
|
$ where black
|
||||||
- Title: black
|
%LocalAppData%\Programs\Python\Python36-32\Scripts\black.exe # possible location
|
||||||
- Command Line: black %s
|
```
|
||||||
- I/O Encoding: Use Default
|
|
||||||
- Key Binding: F1
|
|
||||||
- [x] Raise OS Commands when executed
|
|
||||||
- [x] Auto-save files before execution
|
|
||||||
- [x] Line mode
|
|
||||||
|
|
||||||
1. Select a file in the editor and press **F1** , or whatever key binding you selected
|
Note that if you are using a virtual environment detected by PyCharm, this is an
|
||||||
in step 3, to reformat the file.
|
unneeded step. In this case the path to `black` is `$PyInterpreterDirectory$/black`.
|
||||||
|
|
||||||
|
1. Make sure you have the
|
||||||
|
[File Watchers](https://plugins.jetbrains.com/plugin/7177-file-watchers) plugin
|
||||||
|
installed.
|
||||||
|
1. Go to `Preferences or Settings -> Tools -> File Watchers` and click `+` to add a new
|
||||||
|
watcher:
|
||||||
|
- Name: Black
|
||||||
|
- File type: Python
|
||||||
|
- Scope: Project Files
|
||||||
|
- Program: \<install_location_from_step_2>
|
||||||
|
- Arguments: `$FilePath$`
|
||||||
|
- Output paths to refresh: `$FilePath$`
|
||||||
|
- Working directory: `$ProjectFileDir$`
|
||||||
|
|
||||||
|
- In Advanced Options
|
||||||
|
- Uncheck "Auto-save edited files to trigger the watcher"
|
||||||
|
- Uncheck "Trigger the watcher on external changes"
|
||||||
|
|
||||||
|
## Wing IDE
|
||||||
|
|
||||||
|
Wing IDE supports `black` via **Preference Settings** for system wide settings and
|
||||||
|
**Project Properties** for per-project or workspace specific settings, as explained in
|
||||||
|
the Wing documentation on
|
||||||
|
[Auto-Reformatting](https://wingware.com/doc/edit/auto-reformatting). The detailed
|
||||||
|
procedure is:
|
||||||
|
|
||||||
|
### Prerequistes
|
||||||
|
|
||||||
|
- Wing IDE version 8.0+
|
||||||
|
|
||||||
|
- Install `black`.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pip install black
|
||||||
|
```
|
||||||
|
|
||||||
|
- Make sure it runs from the command line, e.g.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black --help
|
||||||
|
```
|
||||||
|
|
||||||
|
### Preference Settings
|
||||||
|
|
||||||
|
If you want Wing IDE to always reformat with `black` for every project, follow these
|
||||||
|
steps:
|
||||||
|
|
||||||
|
1. In menubar navigate to `Edit -> Preferences -> Editor -> Reformatting`.
|
||||||
|
|
||||||
|
1. Set **Auto-Reformat** from `disable` (default) to `Line after edit` or
|
||||||
|
`Whole files before save`.
|
||||||
|
|
||||||
|
1. Set **Reformatter** from `PEP8` (default) to `Black`.
|
||||||
|
|
||||||
|
### Project Properties
|
||||||
|
|
||||||
|
If you want to just reformat for a specific project and not intervene with Wing IDE
|
||||||
|
global setting, follow these steps:
|
||||||
|
|
||||||
|
1. In menubar navigate to `Project -> Project Properties -> Options`.
|
||||||
|
|
||||||
|
1. Set **Auto-Reformat** from `Use Preferences setting` (default) to `Line after edit`
|
||||||
|
or `Whole files before save`.
|
||||||
|
|
||||||
|
1. Set **Reformatter** from `Use Preferences setting` (default) to `Black`.
|
||||||
|
|
||||||
## Vim
|
## Vim
|
||||||
|
|
||||||
@ -116,23 +217,61 @@ Wing supports black via the OS Commands tool, as explained in the Wing documenta
|
|||||||
Commands and shortcuts:
|
Commands and shortcuts:
|
||||||
|
|
||||||
- `:Black` to format the entire file (ranges not supported);
|
- `:Black` to format the entire file (ranges not supported);
|
||||||
|
- you can optionally pass `target_version=<version>` with the same values as in the
|
||||||
|
command line.
|
||||||
- `:BlackUpgrade` to upgrade _Black_ inside the virtualenv;
|
- `:BlackUpgrade` to upgrade _Black_ inside the virtualenv;
|
||||||
- `:BlackVersion` to get the current version of _Black_ inside the virtualenv.
|
- `:BlackVersion` to get the current version of _Black_ in use.
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
|
|
||||||
- `g:black_fast` (defaults to `0`)
|
- `g:black_fast` (defaults to `0`)
|
||||||
- `g:black_linelength` (defaults to `88`)
|
- `g:black_linelength` (defaults to `88`)
|
||||||
- `g:black_skip_string_normalization` (defaults to `0`)
|
- `g:black_skip_string_normalization` (defaults to `0`)
|
||||||
|
- `g:black_skip_magic_trailing_comma` (defaults to `0`)
|
||||||
- `g:black_virtualenv` (defaults to `~/.vim/black` or `~/.local/share/nvim/black`)
|
- `g:black_virtualenv` (defaults to `~/.vim/black` or `~/.local/share/nvim/black`)
|
||||||
|
- `g:black_use_virtualenv` (defaults to `1`)
|
||||||
|
- `g:black_target_version` (defaults to `""`)
|
||||||
- `g:black_quiet` (defaults to `0`)
|
- `g:black_quiet` (defaults to `0`)
|
||||||
|
- `g:black_preview` (defaults to `0`)
|
||||||
|
|
||||||
|
#### Installation
|
||||||
|
|
||||||
|
This plugin **requires Vim 7.0+ built with Python 3.9+ support**. It needs Python 3.9 to
|
||||||
|
be able to run _Black_ inside the Vim process which is much faster than calling an
|
||||||
|
external command.
|
||||||
|
|
||||||
|
##### `vim-plug`
|
||||||
|
|
||||||
To install with [vim-plug](https://github.com/junegunn/vim-plug):
|
To install with [vim-plug](https://github.com/junegunn/vim-plug):
|
||||||
|
|
||||||
|
_Black_'s `stable` branch tracks official version updates, and can be used to simply
|
||||||
|
follow the most recent stable version.
|
||||||
|
|
||||||
```
|
```
|
||||||
Plug 'psf/black', { 'branch': 'stable' }
|
Plug 'psf/black', { 'branch': 'stable' }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Another option which is a bit more explicit and offers more control is to use
|
||||||
|
`vim-plug`'s `tag` option with a shell wildcard. This will resolve to the latest tag
|
||||||
|
which matches the given pattern.
|
||||||
|
|
||||||
|
The following matches all stable versions (see the
|
||||||
|
[Release Process](../contributing/release_process.md) section for documentation of
|
||||||
|
version scheme used by Black):
|
||||||
|
|
||||||
|
```
|
||||||
|
Plug 'psf/black', { 'tag': '*.*.*' }
|
||||||
|
```
|
||||||
|
|
||||||
|
and the following demonstrates pinning to a specific year's stable style (2022 in this
|
||||||
|
case):
|
||||||
|
|
||||||
|
```
|
||||||
|
Plug 'psf/black', { 'tag': '22.*.*' }
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Vundle
|
||||||
|
|
||||||
or with [Vundle](https://github.com/VundleVim/Vundle.vim):
|
or with [Vundle](https://github.com/VundleVim/Vundle.vim):
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -146,6 +285,14 @@ $ cd ~/.vim/bundle/black
|
|||||||
$ git checkout origin/stable -b stable
|
$ git checkout origin/stable -b stable
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### Arch Linux
|
||||||
|
|
||||||
|
On Arch Linux, the plugin is shipped with the
|
||||||
|
[`python-black`](https://archlinux.org/packages/extra/any/python-black/) package, so you
|
||||||
|
can start using it in Vim after install with no additional setup.
|
||||||
|
|
||||||
|
##### Vim 8 Native Plugin Management
|
||||||
|
|
||||||
or you can copy the plugin files from
|
or you can copy the plugin files from
|
||||||
[plugin/black.vim](https://github.com/psf/black/blob/stable/plugin/black.vim) and
|
[plugin/black.vim](https://github.com/psf/black/blob/stable/plugin/black.vim) and
|
||||||
[autoload/black.vim](https://github.com/psf/black/blob/stable/autoload/black.vim).
|
[autoload/black.vim](https://github.com/psf/black/blob/stable/autoload/black.vim).
|
||||||
@ -160,9 +307,7 @@ curl https://raw.githubusercontent.com/psf/black/stable/autoload/black.vim -o ~/
|
|||||||
Let me know if this requires any changes to work with Vim 8's builtin `packadd`, or
|
Let me know if this requires any changes to work with Vim 8's builtin `packadd`, or
|
||||||
Pathogen, and so on.
|
Pathogen, and so on.
|
||||||
|
|
||||||
This plugin **requires Vim 7.0+ built with Python 3.6+ support**. It needs Python 3.6 to
|
#### Usage
|
||||||
be able to run _Black_ inside the Vim process which is much faster than calling an
|
|
||||||
external command.
|
|
||||||
|
|
||||||
On first run, the plugin creates its own virtualenv using the right Python version and
|
On first run, the plugin creates its own virtualenv using the right Python version and
|
||||||
automatically installs _Black_. You can upgrade it later by calling `:BlackUpgrade` and
|
automatically installs _Black_. You can upgrade it later by calling `:BlackUpgrade` and
|
||||||
@ -172,10 +317,25 @@ If you need to do anything special to make your virtualenv work and install _Bla
|
|||||||
example you want to run a version from main), create a virtualenv manually and point
|
example you want to run a version from main), create a virtualenv manually and point
|
||||||
`g:black_virtualenv` to it. The plugin will use it.
|
`g:black_virtualenv` to it. The plugin will use it.
|
||||||
|
|
||||||
To run _Black_ on save, add the following line to `.vimrc` or `init.vim`:
|
If you would prefer to use the system installation of _Black_ rather than a virtualenv,
|
||||||
|
then add this to your vimrc:
|
||||||
|
|
||||||
```
|
```
|
||||||
autocmd BufWritePre *.py execute ':Black'
|
let g:black_use_virtualenv = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the `:BlackUpgrade` command is only usable and useful with a virtualenv, so
|
||||||
|
when the virtualenv is not in use, `:BlackUpgrade` is disabled. If you need to upgrade
|
||||||
|
the system installation of _Black_, then use your system package manager or pip--
|
||||||
|
whatever tool you used to install _Black_ originally.
|
||||||
|
|
||||||
|
To run _Black_ on save, add the following lines to `.vimrc` or `init.vim`:
|
||||||
|
|
||||||
|
```
|
||||||
|
augroup black_on_save
|
||||||
|
autocmd!
|
||||||
|
autocmd BufWritePre *.py Black
|
||||||
|
augroup end
|
||||||
```
|
```
|
||||||
|
|
||||||
To run _Black_ on a key press (e.g. F9 below), add this:
|
To run _Black_ on a key press (e.g. F9 below), add this:
|
||||||
@ -184,60 +344,6 @@ To run _Black_ on a key press (e.g. F9 below), add this:
|
|||||||
nnoremap <F9> :Black<CR>
|
nnoremap <F9> :Black<CR>
|
||||||
```
|
```
|
||||||
|
|
||||||
**How to get Vim with Python 3.6?** On Ubuntu 17.10 Vim comes with Python 3.6 by
|
|
||||||
default. On macOS with Homebrew run: `brew install vim`. When building Vim from source,
|
|
||||||
use: `./configure --enable-python3interp=yes`. There's many guides online how to do
|
|
||||||
this.
|
|
||||||
|
|
||||||
**I get an import error when using _Black_ from a virtual environment**: If you get an
|
|
||||||
error message like this:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "<string>", line 63, in <module>
|
|
||||||
File "/home/gui/.vim/black/lib/python3.7/site-packages/black.py", line 45, in <module>
|
|
||||||
from typed_ast import ast3, ast27
|
|
||||||
File "/home/gui/.vim/black/lib/python3.7/site-packages/typed_ast/ast3.py", line 40, in <module>
|
|
||||||
from typed_ast import _ast3
|
|
||||||
ImportError: /home/gui/.vim/black/lib/python3.7/site-packages/typed_ast/_ast3.cpython-37m-x86_64-linux-gnu.so: undefined symbool: PyExc_KeyboardInterrupt
|
|
||||||
```
|
|
||||||
|
|
||||||
Then you need to install `typed_ast` and `regex` directly from the source code. The
|
|
||||||
error happens because `pip` will download [Python wheels](https://pythonwheels.com/) if
|
|
||||||
they are available. Python wheels are a new standard of distributing Python packages and
|
|
||||||
packages that have Cython and extensions written in C are already compiled, so the
|
|
||||||
installation is much more faster. The problem here is that somehow the Python
|
|
||||||
environment inside Vim does not match with those already compiled C extensions and these
|
|
||||||
kind of errors are the result. Luckily there is an easy fix: installing the packages
|
|
||||||
from the source code.
|
|
||||||
|
|
||||||
The two packages that cause the problem are:
|
|
||||||
|
|
||||||
- [regex](https://pypi.org/project/regex/)
|
|
||||||
- [typed-ast](https://pypi.org/project/typed-ast/)
|
|
||||||
|
|
||||||
Now remove those two packages:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ pip uninstall regex typed-ast -y
|
|
||||||
```
|
|
||||||
|
|
||||||
And now you can install them with:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ pip install --no-binary :all: regex typed-ast
|
|
||||||
```
|
|
||||||
|
|
||||||
The C extensions will be compiled and now Vim's Python environment will match. Note that
|
|
||||||
you need to have the GCC compiler and the Python development files installed (on
|
|
||||||
Ubuntu/Debian do `sudo apt-get install build-essential python3-dev`).
|
|
||||||
|
|
||||||
If you later want to update _Black_, you should do it like this:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ pip install -U black --no-binary regex,typed-ast
|
|
||||||
```
|
|
||||||
|
|
||||||
### With ALE
|
### With ALE
|
||||||
|
|
||||||
1. Install [`ale`](https://github.com/dense-analysis/ale)
|
1. Install [`ale`](https://github.com/dense-analysis/ale)
|
||||||
@ -283,24 +389,27 @@ close and reopen your File, _Black_ will be done with its job.
|
|||||||
|
|
||||||
## Visual Studio Code
|
## Visual Studio Code
|
||||||
|
|
||||||
Use the
|
- Use the
|
||||||
[Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
|
[Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
|
||||||
([instructions](https://code.visualstudio.com/docs/python/editing#_formatting)).
|
([instructions](https://code.visualstudio.com/docs/python/formatting)).
|
||||||
|
|
||||||
## SublimeText 3
|
- Alternatively the pre-release
|
||||||
|
[Black Formatter](https://marketplace.visualstudio.com/items?itemName=ms-python.black-formatter)
|
||||||
|
extension can be used which runs a [Language Server Protocol](https://langserver.org/)
|
||||||
|
server for Black. Formatting is much more responsive using this extension, **but the
|
||||||
|
minimum supported version of Black is 22.3.0**.
|
||||||
|
|
||||||
Use [sublack plugin](https://github.com/jgirardet/sublack).
|
## SublimeText
|
||||||
|
|
||||||
## Jupyter Notebook Magic
|
For SublimeText 3, use [sublack plugin](https://github.com/jgirardet/sublack). For
|
||||||
|
higher versions, it is recommended to use [LSP](#python-lsp-server) as documented below.
|
||||||
|
|
||||||
Use [blackcellmagic](https://github.com/csurfer/blackcellmagic).
|
## Python LSP Server
|
||||||
|
|
||||||
## Python Language Server
|
|
||||||
|
|
||||||
If your editor supports the [Language Server Protocol](https://langserver.org/) (Atom,
|
If your editor supports the [Language Server Protocol](https://langserver.org/) (Atom,
|
||||||
Sublime Text, Visual Studio Code and many more), you can use the
|
Sublime Text, Visual Studio Code and many more), you can use the
|
||||||
[Python Language Server](https://github.com/palantir/python-language-server) with the
|
[Python LSP Server](https://github.com/python-lsp/python-lsp-server) with the
|
||||||
[pyls-black](https://github.com/rupert/pyls-black) plugin.
|
[python-lsp-black](https://github.com/python-lsp/python-lsp-black) plugin.
|
||||||
|
|
||||||
## Atom/Nuclide
|
## Atom/Nuclide
|
||||||
|
|
||||||
@ -323,4 +432,4 @@ hook global WinSetOption filetype=python %{
|
|||||||
|
|
||||||
## Thonny
|
## Thonny
|
||||||
|
|
||||||
Use [Thonny-black-code-format](https://github.com/Franccisco/thonny-black-code-format).
|
Use [Thonny-black-formatter](https://pypi.org/project/thonny-black-formatter/).
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
You can use _Black_ within a GitHub Actions workflow without setting your own Python
|
You can use _Black_ within a GitHub Actions workflow without setting your own Python
|
||||||
environment. Great for enforcing that your code matches the _Black_ code style.
|
environment. Great for enforcing that your code matches the _Black_ code style.
|
||||||
|
|
||||||
## Compatiblity
|
## Compatibility
|
||||||
|
|
||||||
This action is known to support all GitHub-hosted runner OSes. In addition, only
|
This action is known to support all GitHub-hosted runner OSes. In addition, only
|
||||||
published versions of _Black_ are supported (i.e. whatever is available on PyPI).
|
published versions of _Black_ are supported (i.e. whatever is available on PyPI).
|
||||||
|
|
||||||
Finally, this action installs _Black_ with both the `colorama` and `python2` extras so
|
Finally, this action installs _Black_ with the `colorama` extra so the `--color` flag
|
||||||
the `--color` flag and formatting Python 2 code are supported.
|
should work fine.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ jobs:
|
|||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: psf/black@stable
|
- uses: psf/black@stable
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -32,12 +32,24 @@ We recommend the use of the `@stable` tag, but per version tags also exist if yo
|
|||||||
that. Note that the action's version you select is independent of the version of _Black_
|
that. Note that the action's version you select is independent of the version of _Black_
|
||||||
the action will use.
|
the action will use.
|
||||||
|
|
||||||
The version of _Black_ the action will use can be configured via `version`. The action
|
The version of _Black_ the action will use can be configured via `version` or read from
|
||||||
defaults to the latest release available on PyPI. Only versions available from PyPI are
|
the `pyproject.toml` file. `version` can be any
|
||||||
supported, so no commit SHAs or branch names.
|
[valid version specifier](https://packaging.python.org/en/latest/glossary/#term-Version-Specifier)
|
||||||
|
or just the version number if you want an exact version. To read the version from the
|
||||||
|
`pyproject.toml` file instead, set `use_pyproject` to `true`. This will first look into
|
||||||
|
the `tool.black.required-version` field, then the `dependency-groups` table, then the
|
||||||
|
`project.dependencies` array and finally the `project.optional-dependencies` table. The
|
||||||
|
action defaults to the latest release available on PyPI. Only versions available from
|
||||||
|
PyPI are supported, so no commit SHAs or branch names.
|
||||||
|
|
||||||
|
If you want to include Jupyter Notebooks, _Black_ must be installed with the `jupyter`
|
||||||
|
extra. Installing the extra and including Jupyter Notebook files can be configured via
|
||||||
|
`jupyter` (default is `false`).
|
||||||
|
|
||||||
You can also configure the arguments passed to _Black_ via `options` (defaults to
|
You can also configure the arguments passed to _Black_ via `options` (defaults to
|
||||||
`'--check --diff'`) and `src` (default is `'.'`)
|
`'--check --diff'`) and `src` (default is `'.'`). Please note that the
|
||||||
|
[`--check` flag](labels/exit-code) is required so that the workflow fails if _Black_
|
||||||
|
finds files that need to be formatted.
|
||||||
|
|
||||||
Here's an example configuration:
|
Here's an example configuration:
|
||||||
|
|
||||||
@ -46,5 +58,33 @@ Here's an example configuration:
|
|||||||
with:
|
with:
|
||||||
options: "--check --verbose"
|
options: "--check --verbose"
|
||||||
src: "./src"
|
src: "./src"
|
||||||
|
jupyter: true
|
||||||
version: "21.5b1"
|
version: "21.5b1"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to match versions covered by Black's
|
||||||
|
[stability policy](labels/stability-policy), you can use the compatible release operator
|
||||||
|
(`~=`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: psf/black@stable
|
||||||
|
with:
|
||||||
|
options: "--check --verbose"
|
||||||
|
src: "./src"
|
||||||
|
version: "~= 22.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to read the version from `pyproject.toml`, set `use_pyproject` to `true`.
|
||||||
|
Note that this requires Python >= 3.11, so using the setup-python action may be
|
||||||
|
required, for example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.13"
|
||||||
|
- uses: psf/black@stable
|
||||||
|
with:
|
||||||
|
options: "--check --verbose"
|
||||||
|
src: "./src"
|
||||||
|
use_pyproject: true
|
||||||
|
```
|
||||||
|
31
docs/integrations/index.md
Normal file
31
docs/integrations/index.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Integrations
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
hidden:
|
||||||
|
---
|
||||||
|
|
||||||
|
editors
|
||||||
|
github_actions
|
||||||
|
source_version_control
|
||||||
|
```
|
||||||
|
|
||||||
|
_Black_ can be integrated into many environments, providing a better and smoother
|
||||||
|
experience. Documentation for integrating _Black_ with a tool can be found for the
|
||||||
|
following areas:
|
||||||
|
|
||||||
|
- {doc}`Editor / IDE <./editors>`
|
||||||
|
- {doc}`GitHub Actions <./github_actions>`
|
||||||
|
- {doc}`Source version control <./source_version_control>`
|
||||||
|
|
||||||
|
Editors and tools not listed will require external contributions.
|
||||||
|
|
||||||
|
Patches welcome! ✨ 🍰 ✨
|
||||||
|
|
||||||
|
Any tool can pipe code through _Black_ using its stdio mode (just
|
||||||
|
[use `-` as the file name](https://www.tldp.org/LDP/abs/html/special-chars.html#DASHREF2)).
|
||||||
|
The formatted code will be returned on stdout (unless `--check` was passed). _Black_
|
||||||
|
will still emit messages on stderr but that shouldn't affect your use case.
|
||||||
|
|
||||||
|
This can be used for example with PyCharm's or IntelliJ's
|
||||||
|
[File Watchers](https://www.jetbrains.com/help/pycharm/file-watchers.html).
|
@ -1,28 +0,0 @@
|
|||||||
Integrations
|
|
||||||
============
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
editors
|
|
||||||
github_actions
|
|
||||||
source_version_control
|
|
||||||
|
|
||||||
*Black* can be integrated into many environments, providing a better and smoother experience. Documentation for integrating *Black* with a tool can be found for the
|
|
||||||
following areas:
|
|
||||||
|
|
||||||
- :doc:`Editor / IDE <./editors>`
|
|
||||||
- :doc:`GitHub Actions <./github_actions>`
|
|
||||||
- :doc:`Source version control <./source_version_control>`
|
|
||||||
|
|
||||||
Editors and tools not listed will require external contributions.
|
|
||||||
|
|
||||||
Patches welcome! ✨ 🍰 ✨
|
|
||||||
|
|
||||||
Any tool can pipe code through *Black* using its stdio mode (just
|
|
||||||
`use \`-\` as the file name <https://www.tldp.org/LDP/abs/html/special-chars.html#DASHREF2>`_).
|
|
||||||
The formatted code will be returned on stdout (unless ``--check`` was passed). *Black*
|
|
||||||
will still emit messages on stderr but that shouldn't affect your use case.
|
|
||||||
|
|
||||||
This can be used for example with PyCharm's or IntelliJ's
|
|
||||||
`File Watchers <https://www.jetbrains.com/help/pycharm/file-watchers.html>`_.
|
|
@ -6,9 +6,48 @@ Use [pre-commit](https://pre-commit.com/). Once you
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/psf/black
|
# Using this mirror lets us use mypyc-compiled black, which is about 2x faster
|
||||||
rev: stable # Replace by any tag/version: https://github.com/psf/black/tags
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||||
|
rev: 25.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
language_version: python3 # Should be a command that runs python3.6+
|
# It is recommended to specify the latest version of Python
|
||||||
|
# supported by your project here, or alternatively use
|
||||||
|
# pre-commit's default_language_version, see
|
||||||
|
# https://pre-commit.com/#top_level-default_language_version
|
||||||
|
language_version: python3.11
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Feel free to switch out the `rev` value to a different version of Black.
|
||||||
|
|
||||||
|
Note if you'd like to use a specific commit in `rev`, you'll need to swap the repo
|
||||||
|
specified from the mirror to https://github.com/psf/black. We discourage the use of
|
||||||
|
branches or other mutable refs since the hook [won't auto update as you may
|
||||||
|
expect][pre-commit-mutable-rev].
|
||||||
|
|
||||||
|
## Jupyter Notebooks
|
||||||
|
|
||||||
|
There is an alternate hook `black-jupyter` that expands the targets of `black` to
|
||||||
|
include Jupyter Notebooks. To use this hook, simply replace the hook's `id: black` with
|
||||||
|
`id: black-jupyter` in the `.pre-commit-config.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
repos:
|
||||||
|
# Using this mirror lets us use mypyc-compiled black, which is about 2x faster
|
||||||
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||||
|
rev: 25.1.0
|
||||||
|
hooks:
|
||||||
|
- id: black-jupyter
|
||||||
|
# It is recommended to specify the latest version of Python
|
||||||
|
# supported by your project here, or alternatively use
|
||||||
|
# pre-commit's default_language_version, see
|
||||||
|
# https://pre-commit.com/#top_level-default_language_version
|
||||||
|
language_version: python3.11
|
||||||
|
```
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
The `black-jupyter` hook became available in version 21.8b0.
|
||||||
|
```
|
||||||
|
|
||||||
|
[pre-commit-mutable-rev]:
|
||||||
|
https://pre-commit.com/#using-the-latest-version-for-a-repository
|
||||||
|
9
docs/license.md
Normal file
9
docs/license.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
orphan: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
```{include} ../LICENSE
|
||||||
|
|
||||||
|
```
|
@ -1,6 +0,0 @@
|
|||||||
:orphan:
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
.. include:: ../LICENSE
|
|
@ -1,6 +1,9 @@
|
|||||||
# Used by ReadTheDocs; pinned requirements for stability.
|
# Used by ReadTheDocs; pinned requirements for stability.
|
||||||
|
|
||||||
MyST-Parser==0.14.0
|
myst-parser==4.0.1
|
||||||
Sphinx==3.5.4
|
Sphinx==8.2.3
|
||||||
sphinxcontrib-programoutput==0.17
|
# Older versions break Sphinx even though they're declared to be supported.
|
||||||
sphinx_copybutton==0.3.1
|
docutils==0.21.2
|
||||||
|
sphinxcontrib-programoutput==0.18
|
||||||
|
sphinx_copybutton==0.5.2
|
||||||
|
furo==2024.8.6
|
||||||
|
@ -2,20 +2,21 @@
|
|||||||
|
|
||||||
## Code style
|
## Code style
|
||||||
|
|
||||||
_Black_ reformats entire files in place. Style configuration options are deliberately
|
_Black_ aims for consistency, generality, readability and reducing git diffs. Similar
|
||||||
limited and rarely added. It doesn't take previous formatting into account, except for
|
language constructs are formatted with similar rules. Style configuration options are
|
||||||
the magic trailing comma and preserving newlines. It doesn't reformat blocks that start
|
deliberately limited and rarely added. Previous formatting is taken into account as
|
||||||
with `# fmt: off` and end with `# fmt: on`, or lines that ends with `# fmt: skip`.
|
little as possible, with rare exceptions like the magic trailing comma. The coding style
|
||||||
`# fmt: on/off` have to be on the same level of indentation. It also recognizes
|
used by _Black_ can be viewed as a strict subset of PEP 8.
|
||||||
[YAPF](https://github.com/google/yapf)'s block comments to the same effect, as a
|
|
||||||
courtesy for straddling code.
|
This document describes the current formatting style. If you're interested in trying out
|
||||||
|
where the style is heading, see [future style](./future_style.md) and try running
|
||||||
|
`black --preview`.
|
||||||
|
|
||||||
### How _Black_ wraps lines
|
### How _Black_ wraps lines
|
||||||
|
|
||||||
_Black_ ignores previous formatting and applies uniform horizontal and vertical
|
_Black_ ignores previous formatting and applies uniform horizontal and vertical
|
||||||
whitespace to your code. The rules for horizontal whitespace can be summarized as: do
|
whitespace to your code. The rules for horizontal whitespace can be summarized as: do
|
||||||
whatever makes `pycodestyle` happy. The coding style used by _Black_ can be viewed as a
|
whatever makes `pycodestyle` happy.
|
||||||
strict subset of PEP 8.
|
|
||||||
|
|
||||||
As for vertical whitespace, _Black_ tries to render one full expression or simple
|
As for vertical whitespace, _Black_ tries to render one full expression or simple
|
||||||
statement per line. If this fits the allotted line length, great.
|
statement per line. If this fits the allotted line length, great.
|
||||||
@ -77,6 +78,19 @@ def very_important_function(
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If a data structure literal (tuple, list, set, dict) or a line of "from" imports cannot
|
||||||
|
fit in the allotted length, it's always split into one element per line. This minimizes
|
||||||
|
diffs as well as enables readers of code to find which commit introduced a particular
|
||||||
|
entry. This also makes _Black_ compatible with
|
||||||
|
[isort](../guides/using_black_with_other_tools.md#isort) with the ready-made `black`
|
||||||
|
profile or manual configuration.
|
||||||
|
|
||||||
|
You might have noticed that closing brackets are always dedented and that a trailing
|
||||||
|
comma is always added. Such formatting produces smaller diffs; when you add or remove an
|
||||||
|
element, it's always just one line. Also, having the closing bracket dedented provides a
|
||||||
|
clear delimiter between two distinct sections of the code that otherwise share the same
|
||||||
|
indentation level (like the arguments list and the docstring in the example above).
|
||||||
|
|
||||||
(labels/why-no-backslashes)=
|
(labels/why-no-backslashes)=
|
||||||
|
|
||||||
_Black_ prefers parentheses over backslashes, and will remove backslashes if found.
|
_Black_ prefers parentheses over backslashes, and will remove backslashes if found.
|
||||||
@ -119,18 +133,7 @@ If you're reaching for backslashes, that's a clear signal that you can do better
|
|||||||
slightly refactor your code. I hope some of the examples above show you that there are
|
slightly refactor your code. I hope some of the examples above show you that there are
|
||||||
many ways in which you can do it.
|
many ways in which you can do it.
|
||||||
|
|
||||||
You might have noticed that closing brackets are always dedented and that a trailing
|
(labels/line-length)=
|
||||||
comma is always added. Such formatting produces smaller diffs; when you add or remove an
|
|
||||||
element, it's always just one line. Also, having the closing bracket dedented provides a
|
|
||||||
clear delimiter between two distinct sections of the code that otherwise share the same
|
|
||||||
indentation level (like the arguments list and the docstring in the example above).
|
|
||||||
|
|
||||||
If a data structure literal (tuple, list, set, dict) or a line of "from" imports cannot
|
|
||||||
fit in the allotted length, it's always split into one element per line. This minimizes
|
|
||||||
diffs as well as enables readers of code to find which commit introduced a particular
|
|
||||||
entry. This also makes _Black_ compatible with
|
|
||||||
[isort](../guides/using_black_with_other_tools.md#isort) with the ready-made `black`
|
|
||||||
profile or manual configuration.
|
|
||||||
|
|
||||||
### Line length
|
### Line length
|
||||||
|
|
||||||
@ -140,7 +143,7 @@ significantly shorter files than sticking with 80 (the most popular), or even 79
|
|||||||
by the standard library). In general,
|
by the standard library). In general,
|
||||||
[90-ish seems like the wise choice](https://youtu.be/wf-BqAjZb8M?t=260).
|
[90-ish seems like the wise choice](https://youtu.be/wf-BqAjZb8M?t=260).
|
||||||
|
|
||||||
If you're paid by the line of code you write, you can pass `--line-length` with a lower
|
If you're paid by the lines of code you write, you can pass `--line-length` with a lower
|
||||||
number. _Black_ will try to respect that. However, sometimes it won't be able to without
|
number. _Black_ will try to respect that. However, sometimes it won't be able to without
|
||||||
breaking other rules. In those rare cases, auto-formatted code will exceed your allotted
|
breaking other rules. In those rare cases, auto-formatted code will exceed your allotted
|
||||||
limit.
|
limit.
|
||||||
@ -150,33 +153,10 @@ harder to work with line lengths exceeding 100 characters. It also adversely aff
|
|||||||
side-by-side diff review on typical screen resolutions. Long lines also make it harder
|
side-by-side diff review on typical screen resolutions. Long lines also make it harder
|
||||||
to present code neatly in documentation or talk slides.
|
to present code neatly in documentation or talk slides.
|
||||||
|
|
||||||
If you're using Flake8, you can bump `max-line-length` to 88 and mostly forget about it.
|
#### Flake8 and other linters
|
||||||
However, it's better if you use [Bugbear](https://github.com/PyCQA/flake8-bugbear)'s
|
|
||||||
B950 warning instead of E501, and bump the max line length to 88 (or the `--line-length`
|
|
||||||
you used for black), which will align more with black's _"try to respect
|
|
||||||
`--line-length`, but don't become crazy if you can't"_. You'd do it like this:
|
|
||||||
|
|
||||||
```ini
|
See [Using _Black_ with other tools](../guides/using_black_with_other_tools.md) about
|
||||||
[flake8]
|
linter compatibility.
|
||||||
max-line-length = 88
|
|
||||||
...
|
|
||||||
select = C,E,F,W,B,B950
|
|
||||||
extend-ignore = E203, E501
|
|
||||||
```
|
|
||||||
|
|
||||||
Explanation of why E203 is disabled can be found further in this documentation. And if
|
|
||||||
you're curious about the reasoning behind B950,
|
|
||||||
[Bugbear's documentation](https://github.com/PyCQA/flake8-bugbear#opinionated-warnings)
|
|
||||||
explains it. The tl;dr is "it's like highway speed limits, we won't bother you if you
|
|
||||||
overdo it by a few km/h".
|
|
||||||
|
|
||||||
**If you're looking for a minimal, black-compatible flake8 configuration:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[flake8]
|
|
||||||
max-line-length = 88
|
|
||||||
extend-ignore = E203
|
|
||||||
```
|
|
||||||
|
|
||||||
### Empty lines
|
### Empty lines
|
||||||
|
|
||||||
@ -188,6 +168,35 @@ lines on module level left by the original editors, except when they're within
|
|||||||
parenthesized expressions. Since such expressions are always reformatted to fit minimal
|
parenthesized expressions. Since such expressions are always reformatted to fit minimal
|
||||||
space, this whitespace is lost.
|
space, this whitespace is lost.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# in:
|
||||||
|
|
||||||
|
def function(
|
||||||
|
some_argument: int,
|
||||||
|
|
||||||
|
other_argument: int = 5,
|
||||||
|
) -> EmptyLineInParenWillBeDeleted:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print("One empty line above me will be kept!")
|
||||||
|
|
||||||
|
def this_is_okay_too():
|
||||||
|
print("No empty line here")
|
||||||
|
# out:
|
||||||
|
|
||||||
|
def function(
|
||||||
|
some_argument: int,
|
||||||
|
other_argument: int = 5,
|
||||||
|
) -> EmptyLineInParenWillBeDeleted:
|
||||||
|
|
||||||
|
print("One empty line above me will be kept!")
|
||||||
|
|
||||||
|
|
||||||
|
def this_is_okay_too():
|
||||||
|
print("No empty line here")
|
||||||
|
```
|
||||||
|
|
||||||
It will also insert proper spacing before and after function definitions. It's one line
|
It will also insert proper spacing before and after function definitions. It's one line
|
||||||
before and after inner functions and two lines before and after module-level functions
|
before and after inner functions and two lines before and after module-level functions
|
||||||
and classes. _Black_ will not put empty lines between function/class definitions and
|
and classes. _Black_ will not put empty lines between function/class definitions and
|
||||||
@ -204,11 +213,12 @@ required due to an inner function starting immediately after.
|
|||||||
|
|
||||||
_Black_ does not format comment contents, but it enforces two spaces between code and a
|
_Black_ does not format comment contents, but it enforces two spaces between code and a
|
||||||
comment on the same line, and a space before the comment text begins. Some types of
|
comment on the same line, and a space before the comment text begins. Some types of
|
||||||
comments that require specific spacing rules are respected: doc comments (`#: comment`),
|
comments that require specific spacing rules are respected: shebangs (`#! comment`), doc
|
||||||
section comments with long runs of hashes, and Spyder cells. Non-breaking spaces after
|
comments (`#: comment`), section comments with long runs of hashes, and Spyder cells.
|
||||||
hashes are also preserved. Comments may sometimes be moved because of formatting
|
Non-breaking spaces after hashes are also preserved. Comments may sometimes be moved
|
||||||
changes, which can break tools that assign special meaning to them. See
|
because of formatting changes, which can break tools that assign special meaning to
|
||||||
[AST before and after formatting](#ast-before-and-after-formatting) for more discussion.
|
them. See [AST before and after formatting](#ast-before-and-after-formatting) for more
|
||||||
|
discussion.
|
||||||
|
|
||||||
### Trailing commas
|
### Trailing commas
|
||||||
|
|
||||||
@ -227,16 +237,23 @@ A pre-existing trailing comma informs _Black_ to always explode contents of the
|
|||||||
bracket pair into one item per line. Read more about this in the
|
bracket pair into one item per line. Read more about this in the
|
||||||
[Pragmatism](#pragmatism) section below.
|
[Pragmatism](#pragmatism) section below.
|
||||||
|
|
||||||
|
(labels/strings)=
|
||||||
|
|
||||||
### Strings
|
### Strings
|
||||||
|
|
||||||
_Black_ prefers double quotes (`"` and `"""`) over single quotes (`'` and `'''`). It
|
_Black_ prefers double quotes (`"` and `"""`) over single quotes (`'` and `'''`). It
|
||||||
will replace the latter with the former as long as it does not result in more backslash
|
will replace the latter with the former as long as it does not result in more backslash
|
||||||
escapes than before.
|
escapes than before.
|
||||||
|
|
||||||
_Black_ also standardizes string prefixes, making them always lowercase. On top of that,
|
_Black_ also standardizes string prefixes. Prefix characters are made lowercase with the
|
||||||
if your code is already Python 3.6+ only or it's using the `unicode_literals` future
|
exception of [capital "R" prefixes](#rstrings-and-rstrings), unicode literal markers
|
||||||
import, _Black_ will remove `u` from the string prefix as it is meaningless in those
|
(`u`) are removed because they are meaningless in Python 3, and in the case of multiple
|
||||||
scenarios.
|
characters "r" is put first as in spoken language: "raw f-string".
|
||||||
|
|
||||||
|
Another area where Python allows multiple ways to format a string is escape sequences.
|
||||||
|
For example, `"\uabcd"` and `"\uABCD"` evaluate to the same string. _Black_ normalizes
|
||||||
|
such escape sequences to lowercase, but uses uppercase for `\N` named character escapes,
|
||||||
|
such as `"\N{MEETEI MAYEK LETTER HUK}"`.
|
||||||
|
|
||||||
The main reason to standardize on a single form of quotes is aesthetics. Having one kind
|
The main reason to standardize on a single form of quotes is aesthetics. Having one kind
|
||||||
of quotes everywhere reduces reader distraction. It will also enable a future version of
|
of quotes everywhere reduces reader distraction. It will also enable a future version of
|
||||||
@ -260,29 +277,18 @@ If you are adopting _Black_ in a large project with pre-existing string conventi
|
|||||||
you can pass `--skip-string-normalization` on the command line. This is meant as an
|
you can pass `--skip-string-normalization` on the command line. This is meant as an
|
||||||
adoption helper, avoid using this for new projects.
|
adoption helper, avoid using this for new projects.
|
||||||
|
|
||||||
(labels/experimental-string)=
|
|
||||||
|
|
||||||
As an experimental option (can be enabled by `--experimental-string-processing`),
|
|
||||||
_Black_ splits long strings (using parentheses where appropriate) and merges short ones.
|
|
||||||
When split, parts of f-strings that don't need formatting are converted to plain
|
|
||||||
strings. User-made splits are respected when they do not exceed the line length limit.
|
|
||||||
Line continuation backslashes are converted into parenthesized strings. Unnecessary
|
|
||||||
parentheses are stripped. Because the functionality is experimental, feedback and issue
|
|
||||||
reports are highly encouraged!
|
|
||||||
|
|
||||||
_Black_ also processes docstrings. Firstly the indentation of docstrings is corrected
|
_Black_ also processes docstrings. Firstly the indentation of docstrings is corrected
|
||||||
for both quotations and the text within, although relative indentation in the text is
|
for both quotations and the text within, although relative indentation in the text is
|
||||||
preserved. Superfluous trailing whitespace on each line and unnecessary new lines at the
|
preserved. Superfluous trailing whitespace on each line and unnecessary new lines at the
|
||||||
end of the docstring are removed. All leading tabs are converted to spaces, but tabs
|
end of the docstring are removed. All leading tabs are converted to spaces, but tabs
|
||||||
inside text are preserved. Whitespace leading and trailing one-line docstrings is
|
inside text are preserved. Whitespace leading and trailing one-line docstrings is
|
||||||
removed. The quotations of an empty docstring are separated with one space.
|
removed.
|
||||||
|
|
||||||
### Numeric literals
|
### Numeric literals
|
||||||
|
|
||||||
_Black_ standardizes most numeric literals to use lowercase letters for the syntactic
|
_Black_ standardizes most numeric literals to use lowercase letters for the syntactic
|
||||||
parts and uppercase letters for the digits themselves: `0xAB` instead of `0XAB` and
|
parts and uppercase letters for the digits themselves: `0xAB` instead of `0XAB` and
|
||||||
`1e10` instead of `1E10`. Python 2 long literals are styled as `2L` instead of `2l` to
|
`1e10` instead of `1E10`.
|
||||||
avoid confusion between `l` and `1`.
|
|
||||||
|
|
||||||
### Line breaks & binary operators
|
### Line breaks & binary operators
|
||||||
|
|
||||||
@ -291,6 +297,26 @@ multiple lines. This is so that _Black_ is compliant with the recent changes in
|
|||||||
[PEP 8](https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator)
|
[PEP 8](https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator)
|
||||||
style guide, which emphasizes that this approach improves readability.
|
style guide, which emphasizes that this approach improves readability.
|
||||||
|
|
||||||
|
Almost all operators will be surrounded by single spaces, the only exceptions are unary
|
||||||
|
operators (`+`, `-`, and `~`), and power operators when both operands are simple. For
|
||||||
|
powers, an operand is considered simple if it's only a NAME, numeric CONSTANT, or
|
||||||
|
attribute access (chained attribute access is allowed), with or without a preceding
|
||||||
|
unary operator.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# For example, these won't be surrounded by whitespace
|
||||||
|
a = x**y
|
||||||
|
b = config.base**5.2
|
||||||
|
c = config.base**runtime.config.exponent
|
||||||
|
d = 2**5
|
||||||
|
e = 2**~5
|
||||||
|
|
||||||
|
# ... but these will be surrounded by whitespace
|
||||||
|
f = 2 ** get_exponent()
|
||||||
|
g = get_x() ** get_y()
|
||||||
|
h = config['base'] ** 2
|
||||||
|
```
|
||||||
|
|
||||||
### Slices
|
### Slices
|
||||||
|
|
||||||
PEP 8
|
PEP 8
|
||||||
@ -383,16 +409,22 @@ recommended code style for those files is more terse than PEP 8:
|
|||||||
_Black_ enforces the above rules. There are additional guidelines for formatting `.pyi`
|
_Black_ enforces the above rules. There are additional guidelines for formatting `.pyi`
|
||||||
file that are not enforced yet but might be in a future version of the formatter:
|
file that are not enforced yet but might be in a future version of the formatter:
|
||||||
|
|
||||||
- all function bodies should be empty (contain `...` instead of the body);
|
|
||||||
- do not use docstrings;
|
|
||||||
- prefer `...` over `pass`;
|
- prefer `...` over `pass`;
|
||||||
- for arguments with a default, use `...` instead of the actual default;
|
|
||||||
- avoid using string literals in type annotations, stub files support forward references
|
- avoid using string literals in type annotations, stub files support forward references
|
||||||
natively (like Python 3.7 code with `from __future__ import annotations`);
|
natively (like Python 3.7 code with `from __future__ import annotations`);
|
||||||
- use variable annotations instead of type comments, even for stubs that target older
|
- use variable annotations instead of type comments, even for stubs that target older
|
||||||
versions of Python;
|
versions of Python.
|
||||||
- for arguments that default to `None`, use `Optional[]` explicitly;
|
|
||||||
- use `float` instead of `Union[int, float]`.
|
### Line endings
|
||||||
|
|
||||||
|
_Black_ will normalize line endings (`\n` or `\r\n`) based on the first line ending of
|
||||||
|
the file.
|
||||||
|
|
||||||
|
### Form feed characters
|
||||||
|
|
||||||
|
_Black_ will retain form feed characters on otherwise empty lines at the module level.
|
||||||
|
Only one form feed is retained for a group of consecutive empty lines. Where there are
|
||||||
|
two empty lines in a row, the form feed is placed on the second line.
|
||||||
|
|
||||||
## Pragmatism
|
## Pragmatism
|
||||||
|
|
||||||
@ -402,6 +434,8 @@ there were not many users anyway. Not many edge cases were reported. As a mature
|
|||||||
_Black_ does make some exceptions to rules it otherwise holds. This section documents
|
_Black_ does make some exceptions to rules it otherwise holds. This section documents
|
||||||
what those exceptions are and why this is the case.
|
what those exceptions are and why this is the case.
|
||||||
|
|
||||||
|
(labels/magic-trailing-comma)=
|
||||||
|
|
||||||
### The magic trailing comma
|
### The magic trailing comma
|
||||||
|
|
||||||
_Black_ in general does not take existing formatting into account.
|
_Black_ in general does not take existing formatting into account.
|
||||||
@ -438,17 +472,19 @@ default by (among others) GitHub and Visual Studio Code, differentiates between
|
|||||||
r-strings and R-strings. The former are syntax highlighted as regular expressions while
|
r-strings and R-strings. The former are syntax highlighted as regular expressions while
|
||||||
the latter are treated as true raw strings with no special semantics.
|
the latter are treated as true raw strings with no special semantics.
|
||||||
|
|
||||||
|
(labels/ast-changes)=
|
||||||
|
|
||||||
### AST before and after formatting
|
### AST before and after formatting
|
||||||
|
|
||||||
When run with `--safe`, _Black_ checks that the code before and after is semantically
|
When run with `--safe` (the default), _Black_ checks that the code before and after is
|
||||||
equivalent. This check is done by comparing the AST of the source with the AST of the
|
semantically equivalent. This check is done by comparing the AST of the source with the
|
||||||
target. There are three limited cases in which the AST does differ:
|
AST of the target. There are three limited cases in which the AST does differ:
|
||||||
|
|
||||||
1. _Black_ cleans up leading and trailing whitespace of docstrings, re-indenting them if
|
1. _Black_ cleans up leading and trailing whitespace of docstrings, re-indenting them if
|
||||||
needed. It's been one of the most popular user-reported features for the formatter to
|
needed. It's been one of the most popular user-reported features for the formatter to
|
||||||
fix whitespace issues with docstrings. While the result is technically an AST
|
fix whitespace issues with docstrings. While the result is technically an AST
|
||||||
difference, due to the various possibilities of forming docstrings, all realtime use
|
difference, due to the various possibilities of forming docstrings, all real-world
|
||||||
of docstrings that we're aware of sanitizes indentation and leading/trailing
|
uses of docstrings that we're aware of sanitize indentation and leading/trailing
|
||||||
whitespace anyway.
|
whitespace anyway.
|
||||||
|
|
||||||
1. _Black_ manages optional parentheses for some statements. In the case of the `del`
|
1. _Black_ manages optional parentheses for some statements. In the case of the `del`
|
||||||
|
@ -1,42 +1,269 @@
|
|||||||
# The (future of the) Black code style
|
# The (future of the) Black code style
|
||||||
|
|
||||||
```{warning}
|
## Preview style
|
||||||
Changes to this document often aren't tied and don't relate to releases of
|
|
||||||
_Black_. It's recommended that you read the latest version available.
|
(labels/preview-style)=
|
||||||
|
|
||||||
|
Experimental, potentially disruptive style changes are gathered under the `--preview`
|
||||||
|
CLI flag. At the end of each year, these changes may be adopted into the default style,
|
||||||
|
as described in [The Black Code Style](index.md). Because the functionality is
|
||||||
|
experimental, feedback and issue reports are highly encouraged!
|
||||||
|
|
||||||
|
In the past, the preview style included some features with known bugs, so that we were
|
||||||
|
unable to move these features to the stable style. Therefore, such features are now
|
||||||
|
moved to the `--unstable` style. All features in the `--preview` style are expected to
|
||||||
|
make it to next year's stable style; features in the `--unstable` style will be
|
||||||
|
stabilized only if issues with them are fixed. If bugs are discovered in a `--preview`
|
||||||
|
feature, it is demoted to the `--unstable` style. To avoid thrash when a feature is
|
||||||
|
demoted from the `--preview` to the `--unstable` style, users can use the
|
||||||
|
`--enable-unstable-feature` flag to enable specific unstable features.
|
||||||
|
|
||||||
|
(labels/preview-features)=
|
||||||
|
|
||||||
|
Currently, the following features are included in the preview style:
|
||||||
|
|
||||||
|
- `always_one_newline_after_import`: Always force one blank line after import
|
||||||
|
statements, except when the line after the import is a comment or an import statement
|
||||||
|
- `wrap_long_dict_values_in_parens`: Add parentheses around long values in dictionaries
|
||||||
|
([see below](labels/wrap-long-dict-values))
|
||||||
|
- `fix_fmt_skip_in_one_liners`: Fix `# fmt: skip` behaviour on one-liner declarations,
|
||||||
|
such as `def foo(): return "mock" # fmt: skip`, where previously the declaration
|
||||||
|
would have been incorrectly collapsed.
|
||||||
|
|
||||||
|
(labels/unstable-features)=
|
||||||
|
|
||||||
|
The unstable style additionally includes the following features:
|
||||||
|
|
||||||
|
- `string_processing`: split long string literals and related changes
|
||||||
|
([see below](labels/string-processing))
|
||||||
|
- `multiline_string_handling`: more compact formatting of expressions involving
|
||||||
|
multiline strings ([see below](labels/multiline-string-handling))
|
||||||
|
- `hug_parens_with_braces_and_square_brackets`: more compact formatting of nested
|
||||||
|
brackets ([see below](labels/hug-parens))
|
||||||
|
|
||||||
|
(labels/wrap-long-dict-values)=
|
||||||
|
|
||||||
|
### Improved parentheses management in dicts
|
||||||
|
|
||||||
|
For dict literals with long values, they are now wrapped in parentheses. Unnecessary
|
||||||
|
parentheses are now removed. For example:
|
||||||
|
|
||||||
|
```python
|
||||||
|
my_dict = {
|
||||||
|
"a key in my dict": a_very_long_variable
|
||||||
|
* and_a_very_long_function_call()
|
||||||
|
/ 100000.0,
|
||||||
|
"another key": (short_value),
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Using backslashes for with statements
|
will be changed to:
|
||||||
|
|
||||||
[Backslashes are bad and should be never be used](labels/why-no-backslashes) however
|
```python
|
||||||
there is one exception: `with` statements using multiple context managers. Before Python
|
my_dict = {
|
||||||
3.9 Python's grammar does not allow organizing parentheses around the series of context
|
"a key in my dict": (
|
||||||
managers.
|
a_very_long_variable * and_a_very_long_function_call() / 100000.0
|
||||||
|
),
|
||||||
We don't want formatting like:
|
"another key": short_value,
|
||||||
|
}
|
||||||
```py3
|
|
||||||
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
|
|
||||||
... # nothing to split on - line too long
|
|
||||||
```
|
```
|
||||||
|
|
||||||
So _Black_ will eventually format it like this:
|
(labels/hug-parens)=
|
||||||
|
|
||||||
```py3
|
### Improved multiline dictionary and list indentation for sole function parameter
|
||||||
with \
|
|
||||||
make_context_manager(1) as cm1, \
|
For better readability and less verticality, _Black_ now pairs parentheses ("(", ")")
|
||||||
make_context_manager(2) as cm2, \
|
with braces ("{", "}") and square brackets ("[", "]") on the same line. For example:
|
||||||
make_context_manager(3) as cm3, \
|
|
||||||
make_context_manager(4) as cm4 \
|
```python
|
||||||
:
|
foo(
|
||||||
... # backslashes and an ugly stranded colon
|
[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
nested_array = [
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
]
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Although when the target version is Python 3.9 or higher, _Black_ will use parentheses
|
will be changed to:
|
||||||
instead since they're allowed in Python 3.9 and higher.
|
|
||||||
|
|
||||||
## Improved string processing
|
```python
|
||||||
|
foo([
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
])
|
||||||
|
|
||||||
Currently, _Black_ does not split long strings to fit the line length limit. Currently,
|
nested_array = [[
|
||||||
there is [an experimental option](labels/experimental-string) to enable splitting
|
1,
|
||||||
strings. We plan to enable this option by default once it is fully stable. This is
|
2,
|
||||||
tracked in [this issue](https://github.com/psf/black/issues/2188).
|
3,
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
|
||||||
|
This also applies to list and dictionary unpacking:
|
||||||
|
|
||||||
|
```python
|
||||||
|
foo(
|
||||||
|
*[
|
||||||
|
a_long_function_name(a_long_variable_name)
|
||||||
|
for a_long_variable_name in some_generator
|
||||||
|
]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
will become:
|
||||||
|
|
||||||
|
```python
|
||||||
|
foo(*[
|
||||||
|
a_long_function_name(a_long_variable_name)
|
||||||
|
for a_long_variable_name in some_generator
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use a magic trailing comma to avoid this compacting behavior; by default,
|
||||||
|
_Black_ will not reformat the following code:
|
||||||
|
|
||||||
|
```python
|
||||||
|
foo(
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
(labels/string-processing)=
|
||||||
|
|
||||||
|
### Improved string processing
|
||||||
|
|
||||||
|
_Black_ will split long string literals and merge short ones. Parentheses are used where
|
||||||
|
appropriate. When split, parts of f-strings that don't need formatting are converted to
|
||||||
|
plain strings. f-strings will not be merged if they contain internal quotes and it would
|
||||||
|
change their quotation mark style. User-made splits are respected when they do not
|
||||||
|
exceed the line length limit. Line continuation backslashes are converted into
|
||||||
|
parenthesized strings. Unnecessary parentheses are stripped. The stability and status of
|
||||||
|
this feature istracked in [this issue](https://github.com/psf/black/issues/2188).
|
||||||
|
|
||||||
|
(labels/multiline-string-handling)=
|
||||||
|
|
||||||
|
### Improved multiline string handling
|
||||||
|
|
||||||
|
_Black_ is smarter when formatting multiline strings, especially in function arguments,
|
||||||
|
to avoid introducing extra line breaks. Previously, it would always consider multiline
|
||||||
|
strings as not fitting on a single line. With this new feature, _Black_ looks at the
|
||||||
|
context around the multiline string to decide if it should be inlined or split to a
|
||||||
|
separate line. For example, when a multiline string is passed to a function, _Black_
|
||||||
|
will only split the multiline string if a line is too long or if multiple arguments are
|
||||||
|
being passed.
|
||||||
|
|
||||||
|
For example, _Black_ will reformat
|
||||||
|
|
||||||
|
```python
|
||||||
|
textwrap.dedent(
|
||||||
|
"""\
|
||||||
|
This is a
|
||||||
|
multiline string
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
to:
|
||||||
|
|
||||||
|
```python
|
||||||
|
textwrap.dedent("""\
|
||||||
|
This is a
|
||||||
|
multiline string
|
||||||
|
""")
|
||||||
|
```
|
||||||
|
|
||||||
|
And:
|
||||||
|
|
||||||
|
```python
|
||||||
|
MULTILINE = """
|
||||||
|
foobar
|
||||||
|
""".replace(
|
||||||
|
"\n", ""
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
to:
|
||||||
|
|
||||||
|
```python
|
||||||
|
MULTILINE = """
|
||||||
|
foobar
|
||||||
|
""".replace("\n", "")
|
||||||
|
```
|
||||||
|
|
||||||
|
Implicit multiline strings are special, because they can have inline comments. Strings
|
||||||
|
without comments are merged, for example
|
||||||
|
|
||||||
|
```python
|
||||||
|
s = (
|
||||||
|
"An "
|
||||||
|
"implicit "
|
||||||
|
"multiline "
|
||||||
|
"string"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes
|
||||||
|
|
||||||
|
```python
|
||||||
|
s = "An implicit multiline string"
|
||||||
|
```
|
||||||
|
|
||||||
|
A comment on any line of the string (or between two string lines) will block the
|
||||||
|
merging, so
|
||||||
|
|
||||||
|
```python
|
||||||
|
s = (
|
||||||
|
"An " # Important comment concerning just this line
|
||||||
|
"implicit "
|
||||||
|
"multiline "
|
||||||
|
"string"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
```python
|
||||||
|
s = (
|
||||||
|
"An "
|
||||||
|
"implicit "
|
||||||
|
# Comment in between
|
||||||
|
"multiline "
|
||||||
|
"string"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
will not be merged. Having the comment after or before the string lines (but still
|
||||||
|
inside the parens) will merge the string. For example
|
||||||
|
|
||||||
|
```python
|
||||||
|
s = ( # Top comment
|
||||||
|
"An "
|
||||||
|
"implicit "
|
||||||
|
"multiline "
|
||||||
|
"string"
|
||||||
|
# Bottom comment
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes
|
||||||
|
|
||||||
|
```python
|
||||||
|
s = ( # Top comment
|
||||||
|
"An implicit multiline string"
|
||||||
|
# Bottom comment
|
||||||
|
)
|
||||||
|
```
|
||||||
|
54
docs/the_black_code_style/index.md
Normal file
54
docs/the_black_code_style/index.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# The Black Code Style
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
hidden:
|
||||||
|
---
|
||||||
|
|
||||||
|
Current style <current_style>
|
||||||
|
Future style <future_style>
|
||||||
|
```
|
||||||
|
|
||||||
|
_Black_ is a PEP 8 compliant opinionated formatter with its own style.
|
||||||
|
|
||||||
|
While keeping the style unchanged throughout releases has always been a goal, the
|
||||||
|
_Black_ code style isn't set in stone. It evolves to accommodate for new features in the
|
||||||
|
Python language and, occasionally, in response to user feedback. Large-scale style
|
||||||
|
preferences presented in {doc}`current_style` are very unlikely to change, but minor
|
||||||
|
style aspects and details might change according to the stability policy presented
|
||||||
|
below. Ongoing style considerations are tracked on GitHub with the
|
||||||
|
[style](https://github.com/psf/black/labels/T%3A%20style) issue label.
|
||||||
|
|
||||||
|
(labels/stability-policy)=
|
||||||
|
|
||||||
|
## Stability Policy
|
||||||
|
|
||||||
|
The following policy applies for the _Black_ code style, in non pre-release versions of
|
||||||
|
_Black_:
|
||||||
|
|
||||||
|
- If code has been formatted with _Black_, it will remain unchanged when formatted with
|
||||||
|
the same options using any other release in the same calendar year.
|
||||||
|
|
||||||
|
This means projects can safely use `black ~= 22.0` without worrying about formatting
|
||||||
|
changes disrupting their project in 2022. We may still fix bugs where _Black_ crashes
|
||||||
|
on some code, and make other improvements that do not affect formatting.
|
||||||
|
|
||||||
|
In rare cases, we may make changes affecting code that has not been previously
|
||||||
|
formatted with _Black_. For example, we have had bugs where we accidentally removed
|
||||||
|
some comments. Such bugs can be fixed without breaking the stability policy.
|
||||||
|
|
||||||
|
- The first release in a new calendar year _may_ contain formatting changes, although
|
||||||
|
these will be minimised as much as possible. This is to allow for improved formatting
|
||||||
|
enabled by newer Python language syntax as well as due to improvements in the
|
||||||
|
formatting logic.
|
||||||
|
|
||||||
|
- The `--preview` and `--unstable` flags are exempt from this policy. There are no
|
||||||
|
guarantees around the stability of the output with these flags passed into _Black_.
|
||||||
|
They are intended for allowing experimentation with proposed changes to the _Black_
|
||||||
|
code style. The `--preview` style at the end of a year should closely match the stable
|
||||||
|
style for the next year, but we may always make changes.
|
||||||
|
|
||||||
|
Documentation for both the current and future styles can be found:
|
||||||
|
|
||||||
|
- {doc}`current_style`
|
||||||
|
- {doc}`future_style`
|
@ -1,19 +0,0 @@
|
|||||||
The Black Code Style
|
|
||||||
====================
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
Current style <current_style>
|
|
||||||
Future style <future_style>
|
|
||||||
|
|
||||||
*Black* is a PEP 8 compliant opinionated formatter with its own style.
|
|
||||||
|
|
||||||
It should be noted that while keeping the style unchanged throughout releases is a
|
|
||||||
goal, the *Black* code style isn't set in stone. Sometimes it's modified in response to
|
|
||||||
user feedback or even changes to the Python language!
|
|
||||||
|
|
||||||
Documentation for both the current and future styles can be found:
|
|
||||||
|
|
||||||
- :doc:`current_style`
|
|
||||||
- :doc:`future_style`
|
|
@ -4,10 +4,15 @@
|
|||||||
protocol. The main benefit of using it is to avoid the cost of starting up a new _Black_
|
protocol. The main benefit of using it is to avoid the cost of starting up a new _Black_
|
||||||
process every time you want to blacken a file.
|
process every time you want to blacken a file.
|
||||||
|
|
||||||
|
```{warning}
|
||||||
|
`blackd` should not be run as a publicly accessible server as there are no security
|
||||||
|
precautions in place to prevent abuse. **It is intended for local use only**.
|
||||||
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
`blackd` is not packaged alongside _Black_ by default because it has additional
|
`blackd` is not packaged alongside _Black_ by default because it has additional
|
||||||
dependencies. You will need to execute `pip install black[d]` to install it.
|
dependencies. You will need to execute `pip install 'black[d]'` to install it.
|
||||||
|
|
||||||
You can start the server on the default port, binding only to the local interface by
|
You can start the server on the default port, binding only to the local interface by
|
||||||
running `blackd`. You will see a single line mentioning the server's version, and the
|
running `blackd`. You will see a single line mentioning the server's version, and the
|
||||||
@ -45,12 +50,24 @@ is rejected with `HTTP 501` (Not Implemented).
|
|||||||
The headers controlling how source code is formatted are:
|
The headers controlling how source code is formatted are:
|
||||||
|
|
||||||
- `X-Line-Length`: corresponds to the `--line-length` command line flag.
|
- `X-Line-Length`: corresponds to the `--line-length` command line flag.
|
||||||
|
- `X-Skip-Source-First-Line`: corresponds to the `--skip-source-first-line` command line
|
||||||
|
flag. If present and its value is not an empty string, the first line of the source
|
||||||
|
code will be ignored.
|
||||||
- `X-Skip-String-Normalization`: corresponds to the `--skip-string-normalization`
|
- `X-Skip-String-Normalization`: corresponds to the `--skip-string-normalization`
|
||||||
command line flag. If present and its value is not the empty string, no string
|
command line flag. If present and its value is not the empty string, no string
|
||||||
normalization will be performed.
|
normalization will be performed.
|
||||||
- `X-Skip-Magic-Trailing-Comma`: corresponds to the `--skip-magic-trailing-comma`
|
- `X-Skip-Magic-Trailing-Comma`: corresponds to the `--skip-magic-trailing-comma`
|
||||||
command line flag. If present and its value is not the empty string, trailing commas
|
command line flag. If present and its value is not an empty string, trailing commas
|
||||||
will not be used as a reason to split lines.
|
will not be used as a reason to split lines.
|
||||||
|
- `X-Preview`: corresponds to the `--preview` command line flag. If present and its
|
||||||
|
value is not an empty string, experimental and potentially disruptive style changes
|
||||||
|
will be used.
|
||||||
|
- `X-Unstable`: corresponds to the `--unstable` command line flag. If present and its
|
||||||
|
value is not an empty string, experimental style changes that are known to be buggy
|
||||||
|
will be used.
|
||||||
|
- `X-Enable-Unstable-Feature`: corresponds to the `--enable-unstable-feature` flag. The
|
||||||
|
contents of the flag must be a comma-separated list of unstable features to be
|
||||||
|
enabled. Example: `X-Enable-Unstable-Feature: feature1, feature2`.
|
||||||
- `X-Fast-Or-Safe`: if set to `fast`, `blackd` will act as _Black_ does when passed the
|
- `X-Fast-Or-Safe`: if set to `fast`, `blackd` will act as _Black_ does when passed the
|
||||||
`--fast` command line flag.
|
`--fast` command line flag.
|
||||||
- `X-Python-Variant`: if set to `pyi`, `blackd` will act as _Black_ does when passed the
|
- `X-Python-Variant`: if set to `pyi`, `blackd` will act as _Black_ does when passed the
|
||||||
|
53
docs/usage_and_configuration/black_docker_image.md
Normal file
53
docs/usage_and_configuration/black_docker_image.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Black Docker image
|
||||||
|
|
||||||
|
Official _Black_ Docker images are available on
|
||||||
|
[Docker Hub](https://hub.docker.com/r/pyfound/black).
|
||||||
|
|
||||||
|
_Black_ images with the following tags are available:
|
||||||
|
|
||||||
|
- release numbers, e.g. `21.5b2`, `21.6b0`, `21.7b0` etc.\
|
||||||
|
ℹ Recommended for users who want to use a particular version of _Black_.
|
||||||
|
- `latest_release` - tag created when a new version of _Black_ is released.\
|
||||||
|
ℹ Recommended for users who want to use released versions of _Black_. It maps to
|
||||||
|
[the latest release](https://github.com/psf/black/releases/latest) of _Black_.
|
||||||
|
- `latest_prerelease` - tag created when a new alpha (prerelease) version of _Black_ is
|
||||||
|
released.\
|
||||||
|
ℹ Recommended for users who want to preview or test alpha versions of _Black_. Note
|
||||||
|
that the most recent release may be newer than any prerelease, because no prereleases
|
||||||
|
are created before most releases.
|
||||||
|
- `latest` - tag used for the newest image of _Black_.\
|
||||||
|
ℹ Recommended for users who always want to use the latest version of _Black_, even
|
||||||
|
before it is released.
|
||||||
|
|
||||||
|
There is one more tag used for _Black_ Docker images - `latest_non_release`. It is
|
||||||
|
created for all unreleased
|
||||||
|
[commits on the `main` branch](https://github.com/psf/black/commits/main). This tag is
|
||||||
|
not meant to be used by external users.
|
||||||
|
|
||||||
|
From version 23.11.0 the Docker image installs a compiled black into the image.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
A permanent container doesn't have to be created to use _Black_ as a Docker image. It's
|
||||||
|
enough to run _Black_ commands for the chosen image denoted as `:tag`. In the below
|
||||||
|
examples, the `latest_release` tag is used. If `:tag` is omitted, the `latest` tag will
|
||||||
|
be used.
|
||||||
|
|
||||||
|
More about _Black_ usage can be found in
|
||||||
|
[Usage and Configuration: The basics](./the_basics.md).
|
||||||
|
|
||||||
|
### Check Black version
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker run --rm pyfound/black:latest_release black --version
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check code
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker run --rm --volume $(pwd):/src --workdir /src pyfound/black:latest_release black --check .
|
||||||
|
```
|
||||||
|
|
||||||
|
_Remark_: besides [regular _Black_ exit codes](./the_basics.md) returned by `--check`
|
||||||
|
option, [Docker exit codes](https://docs.docker.com/engine/reference/run/#exit-status)
|
||||||
|
should also be considered.
|
@ -22,10 +22,12 @@ run. The file is non-portable. The standard location on common operating systems
|
|||||||
`file-mode` is an int flag that determines whether the file was formatted as 3.6+ only,
|
`file-mode` is an int flag that determines whether the file was formatted as 3.6+ only,
|
||||||
as .pyi, and whether string normalization was omitted.
|
as .pyi, and whether string normalization was omitted.
|
||||||
|
|
||||||
To override the location of these files on macOS or Linux, set the environment variable
|
To override the location of these files on all systems, set the environment variable
|
||||||
|
`BLACK_CACHE_DIR` to the preferred location. Alternatively on macOS and Linux, set
|
||||||
`XDG_CACHE_HOME` to your preferred location. For example, if you want to put the cache
|
`XDG_CACHE_HOME` to your preferred location. For example, if you want to put the cache
|
||||||
in the directory you're running _Black_ from, set `XDG_CACHE_HOME=.cache`. _Black_ will
|
in the directory you're running _Black_ from, set `BLACK_CACHE_DIR=.cache/black`.
|
||||||
then write the above files to `.cache/black/<version>/`.
|
_Black_ will then write the above files to `.cache/black`. Note that `BLACK_CACHE_DIR`
|
||||||
|
will take precedence over `XDG_CACHE_HOME` if both are set.
|
||||||
|
|
||||||
## .gitignore
|
## .gitignore
|
||||||
|
|
||||||
|
28
docs/usage_and_configuration/index.md
Normal file
28
docs/usage_and_configuration/index.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Usage and Configuration
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
hidden:
|
||||||
|
---
|
||||||
|
|
||||||
|
the_basics
|
||||||
|
file_collection_and_discovery
|
||||||
|
black_as_a_server
|
||||||
|
black_docker_image
|
||||||
|
```
|
||||||
|
|
||||||
|
Sometimes, running _Black_ with its defaults and passing filepaths to it just won't cut
|
||||||
|
it. Passing each file using paths will become burdensome, and maybe you would like
|
||||||
|
_Black_ to not touch your files and just output diffs. And yes, you _can_ tweak certain
|
||||||
|
parts of _Black_'s style, but please know that configurability in this area is
|
||||||
|
purposefully limited.
|
||||||
|
|
||||||
|
Using many of these more advanced features of _Black_ will require some configuration.
|
||||||
|
Configuration that will either live on the command line or in a TOML configuration file.
|
||||||
|
|
||||||
|
This section covers features of _Black_ and configuring _Black_ in detail:
|
||||||
|
|
||||||
|
- {doc}`The basics <./the_basics>`
|
||||||
|
- {doc}`File collection and discovery <file_collection_and_discovery>`
|
||||||
|
- {doc}`Black as a server (blackd) <./black_as_a_server>`
|
||||||
|
- {doc}`Black Docker image <./black_docker_image>`
|
@ -1,24 +0,0 @@
|
|||||||
Usage and Configuration
|
|
||||||
=======================
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
the_basics
|
|
||||||
file_collection_and_discovery
|
|
||||||
black_as_a_server
|
|
||||||
|
|
||||||
Sometimes, running *Black* with its defaults and passing filepaths to it just won't cut
|
|
||||||
it. Passing each file using paths will become burdensome, and maybe you would like
|
|
||||||
*Black* to not touch your files and just output diffs. And yes, you *can* tweak certain
|
|
||||||
parts of *Black*'s style, but please know that configurability in this area is
|
|
||||||
purposefully limited.
|
|
||||||
|
|
||||||
Using many of these more advanced features of *Black* will require some configuration.
|
|
||||||
Configuration that will either live on the command line or in a TOML configuration file.
|
|
||||||
|
|
||||||
This section covers features of *Black* and configuring *Black* in detail:
|
|
||||||
|
|
||||||
- :doc:`The basics <./the_basics>`
|
|
||||||
- :doc:`File collection and discovery <file_collection_and_discovery>`
|
|
||||||
- :doc:`Black as a server (blackd) <./black_as_a_server>`
|
|
@ -4,15 +4,16 @@ Foundational knowledge on using and configuring Black.
|
|||||||
|
|
||||||
_Black_ is a well-behaved Unix-style command-line tool:
|
_Black_ is a well-behaved Unix-style command-line tool:
|
||||||
|
|
||||||
- it does nothing if no sources are passed to it;
|
- it does nothing if it finds no sources to format;
|
||||||
- it will read from standard input and write to standard output if `-` is used as the
|
- it will read from standard input and write to standard output if `-` is used as the
|
||||||
filename;
|
filename;
|
||||||
- it only outputs messages to users on standard error;
|
- it only outputs messages to users on standard error;
|
||||||
- exits with code 0 unless an internal error occurred (or `--check` was used).
|
- exits with code 0 unless an internal error occurred or a CLI option prompted it.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
To get started right away with sensible defaults:
|
_Black_ will reformat entire files in place. To get started right away with sensible
|
||||||
|
defaults:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
black {source_file_or_directory}
|
black {source_file_or_directory}
|
||||||
@ -24,66 +25,167 @@ You can run _Black_ as a package if running it as a script doesn't work:
|
|||||||
python -m black {source_file_or_directory}
|
python -m black {source_file_or_directory}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Ignoring sections
|
||||||
|
|
||||||
|
Black will not reformat lines that contain `# fmt: skip` or blocks that start with
|
||||||
|
`# fmt: off` and end with `# fmt: on`. `# fmt: skip` can be mixed with other
|
||||||
|
pragmas/comments either with multiple comments (e.g. `# fmt: skip # pylint # noqa`) or
|
||||||
|
as a semicolon separated list (e.g. `# fmt: skip; pylint; noqa`). `# fmt: on/off` must
|
||||||
|
be on the same level of indentation and in the same block, meaning no unindents beyond
|
||||||
|
the initial indentation level between them. Black also recognizes
|
||||||
|
[YAPF](https://github.com/google/yapf)'s block comments to the same effect, as a
|
||||||
|
courtesy for straddling code.
|
||||||
|
|
||||||
### Command line options
|
### Command line options
|
||||||
|
|
||||||
_Black_ has quite a few knobs these days, although _Black_ is opinionated so style
|
The CLI options of _Black_ can be displayed by running `black --help`. All options are
|
||||||
configuration options are deliberately limited and rarely added. You can list them by
|
also covered in more detail below.
|
||||||
running `black --help`.
|
|
||||||
|
|
||||||
<details>
|
While _Black_ has quite a few knobs these days, it is still opinionated so style options
|
||||||
|
are deliberately limited and rarely added.
|
||||||
|
|
||||||
<summary>Help output</summary>
|
Note that all command-line options listed above can also be configured using a
|
||||||
|
`pyproject.toml` file (more on that below).
|
||||||
|
|
||||||
```{program-output} black --help
|
#### `-h`, `--help`
|
||||||
|
|
||||||
```
|
Show available command-line options and exit.
|
||||||
|
|
||||||
</details>
|
#### `-c`, `--code`
|
||||||
|
|
||||||
### Code input alternatives
|
Format the code passed in as a string.
|
||||||
|
|
||||||
#### Standard Input
|
|
||||||
|
|
||||||
_Black_ supports formatting code via stdin, with the result being printed to stdout.
|
|
||||||
Just let _Black_ know with `-` as the path.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ echo "print ( 'hello, world' )" | black -
|
|
||||||
print("hello, world")
|
|
||||||
reformatted -
|
|
||||||
All done! ✨ 🍰 ✨
|
|
||||||
1 file reformatted.
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tip:** if you need _Black_ to treat stdin input as a file passed directly via the CLI,
|
|
||||||
use `--stdin-filename`. Useful to make sure _Black_ will respect the `--force-exclude`
|
|
||||||
option on some editors that rely on using stdin.
|
|
||||||
|
|
||||||
#### As a string
|
|
||||||
|
|
||||||
You can also pass code as a string using the `-c` / `--code` option.
|
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ black --code "print ( 'hello, world' )"
|
$ black --code "print ( 'hello, world' )"
|
||||||
print("hello, world")
|
print("hello, world")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Writeback and reporting
|
#### `-l`, `--line-length`
|
||||||
|
|
||||||
By default _Black_ reformats the files given and/or found in place. Sometimes you need
|
How many characters per line to allow. The default is 88.
|
||||||
_Black_ to just tell you what it _would_ do without actually rewriting the Python files.
|
|
||||||
|
|
||||||
There's two variations to this mode that are independently enabled by their respective
|
See also [the style documentation](labels/line-length).
|
||||||
flags. Both variations can be enabled at once.
|
|
||||||
|
|
||||||
#### Exit code
|
#### `-t`, `--target-version`
|
||||||
|
|
||||||
Passing `--check` will make _Black_ exit with:
|
Python versions that should be supported by Black's output. You can run `black --help`
|
||||||
|
and look for the `--target-version` option to see the full list of supported versions.
|
||||||
|
You should include all versions that your code supports. If you support Python 3.11
|
||||||
|
through 3.13, you should write:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black -t py311 -t py312 -t py313
|
||||||
|
```
|
||||||
|
|
||||||
|
In a [configuration file](#configuration-via-a-file), you can write:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
target-version = ["py311", "py312", "py313"]
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, Black will infer target versions from the project metadata in
|
||||||
|
`pyproject.toml`, specifically the `[project.requires-python]` field. If this does not
|
||||||
|
yield conclusive results, Black will use per-file auto-detection.
|
||||||
|
|
||||||
|
_Black_ uses this option to decide what grammar to use to parse your code. In addition,
|
||||||
|
it may use it to decide what style to use. For example, support for a trailing comma
|
||||||
|
after `*args` in a function call was added in Python 3.5, so _Black_ will add this comma
|
||||||
|
only if the target versions are all Python 3.5 or higher:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black --line-length=10 --target-version=py35 -c 'f(a, *args)'
|
||||||
|
f(
|
||||||
|
a,
|
||||||
|
*args,
|
||||||
|
)
|
||||||
|
$ black --line-length=10 --target-version=py34 -c 'f(a, *args)'
|
||||||
|
f(
|
||||||
|
a,
|
||||||
|
*args
|
||||||
|
)
|
||||||
|
$ black --line-length=10 --target-version=py34 --target-version=py35 -c 'f(a, *args)'
|
||||||
|
f(
|
||||||
|
a,
|
||||||
|
*args
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `--pyi`
|
||||||
|
|
||||||
|
Format all input files like typing stubs regardless of file extension. This is useful
|
||||||
|
when piping source on standard input.
|
||||||
|
|
||||||
|
#### `--ipynb`
|
||||||
|
|
||||||
|
Format all input files like Jupyter Notebooks regardless of file extension. This is
|
||||||
|
useful when piping source on standard input.
|
||||||
|
|
||||||
|
#### `--python-cell-magics`
|
||||||
|
|
||||||
|
When processing Jupyter Notebooks, add the given magic to the list of known python-
|
||||||
|
magics. Useful for formatting cells with custom python magics.
|
||||||
|
|
||||||
|
#### `-x, --skip-source-first-line`
|
||||||
|
|
||||||
|
Skip the first line of the source code.
|
||||||
|
|
||||||
|
#### `-S, --skip-string-normalization`
|
||||||
|
|
||||||
|
By default, _Black_ uses double quotes for all strings and normalizes string prefixes,
|
||||||
|
as described in [the style documentation](labels/strings). If this option is given,
|
||||||
|
strings are left unchanged instead.
|
||||||
|
|
||||||
|
#### `-C, --skip-magic-trailing-comma`
|
||||||
|
|
||||||
|
By default, _Black_ uses existing trailing commas as an indication that short lines
|
||||||
|
should be left separate, as described in
|
||||||
|
[the style documentation](labels/magic-trailing-comma). If this option is given, the
|
||||||
|
magic trailing comma is ignored.
|
||||||
|
|
||||||
|
#### `--preview`
|
||||||
|
|
||||||
|
Enable potentially disruptive style changes that we expect to add to Black's main
|
||||||
|
functionality in the next major release. Use this if you want a taste of what next
|
||||||
|
year's style will look like.
|
||||||
|
|
||||||
|
Read more about [our preview style](labels/preview-style).
|
||||||
|
|
||||||
|
There is no guarantee on the code style produced by this flag across releases.
|
||||||
|
|
||||||
|
#### `--unstable`
|
||||||
|
|
||||||
|
Enable all style changes in `--preview`, plus additional changes that we would like to
|
||||||
|
make eventually, but that have known issues that need to be fixed before they can move
|
||||||
|
back to the `--preview` style. Use this if you want to experiment with these changes and
|
||||||
|
help fix issues with them.
|
||||||
|
|
||||||
|
There is no guarantee on the code style produced by this flag across releases.
|
||||||
|
|
||||||
|
#### `--enable-unstable-feature`
|
||||||
|
|
||||||
|
Enable specific features from the `--unstable` style. See
|
||||||
|
[the preview style documentation](labels/unstable-features) for the list of supported
|
||||||
|
features. This flag can only be used when `--preview` is enabled. Users are encouraged
|
||||||
|
to use this flag if they use `--preview` style and a feature that affects their code is
|
||||||
|
moved from the `--preview` to the `--unstable` style, but they want to avoid the thrash
|
||||||
|
from undoing this change.
|
||||||
|
|
||||||
|
There are no guarantees on the behavior of these features, or even their existence,
|
||||||
|
across releases.
|
||||||
|
|
||||||
|
(labels/exit-code)=
|
||||||
|
|
||||||
|
#### `--check`
|
||||||
|
|
||||||
|
Don't write the files back, just return the status. _Black_ will exit with:
|
||||||
|
|
||||||
- code 0 if nothing would change;
|
- code 0 if nothing would change;
|
||||||
- code 1 if some files would be reformatted; or
|
- code 1 if some files would be reformatted; or
|
||||||
- code 123 if there was an internal error
|
- code 123 if there was an internal error
|
||||||
|
|
||||||
|
If used in combination with `--quiet` then only the exit code will be returned, unless
|
||||||
|
there was an internal error.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ black test.py --check
|
$ black test.py --check
|
||||||
All done! ✨ 🍰 ✨
|
All done! ✨ 🍰 ✨
|
||||||
@ -106,17 +208,17 @@ $ echo $?
|
|||||||
123
|
123
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Diffs
|
#### `--diff`
|
||||||
|
|
||||||
Passing `--diff` will make _Black_ print out diffs that indicate what changes _Black_
|
Don't write the files back, just output a diff to indicate what changes _Black_ would've
|
||||||
would've made. They are printed to stdout so capturing them is simple.
|
made. They are printed to stdout so capturing them is simple.
|
||||||
|
|
||||||
If you'd like colored diffs, you can enable them with the `--color`.
|
If you'd like colored diffs, you can enable them with `--color`.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ black test.py --diff
|
$ black test.py --diff
|
||||||
--- test.py 2021-03-08 22:23:40.848954 +0000
|
--- test.py 2021-03-08 22:23:40.848954+00:00
|
||||||
+++ test.py 2021-03-08 22:23:47.126319 +0000
|
+++ test.py 2021-03-08 22:23:47.126319+00:00
|
||||||
@@ -1 +1 @@
|
@@ -1 +1 @@
|
||||||
-print ( 'hello, world' )
|
-print ( 'hello, world' )
|
||||||
+print("hello, world")
|
+print("hello, world")
|
||||||
@ -125,6 +227,198 @@ All done! ✨ 🍰 ✨
|
|||||||
1 file would be reformatted.
|
1 file would be reformatted.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `--color` / `--no-color`
|
||||||
|
|
||||||
|
Show (or do not show) colored diff. Only applies when `--diff` is given.
|
||||||
|
|
||||||
|
#### `--line-ranges`
|
||||||
|
|
||||||
|
When specified, _Black_ will try its best to only format these lines.
|
||||||
|
|
||||||
|
This option can be specified multiple times, and a union of the lines will be formatted.
|
||||||
|
Each range must be specified as two integers connected by a `-`: `<START>-<END>`. The
|
||||||
|
`<START>` and `<END>` integer indices are 1-based and inclusive on both ends.
|
||||||
|
|
||||||
|
_Black_ may still format lines outside of the ranges for multi-line statements.
|
||||||
|
Formatting more than one file or any ipynb files with this option is not supported. This
|
||||||
|
option cannot be specified in the `pyproject.toml` config.
|
||||||
|
|
||||||
|
Example: `black --line-ranges=1-10 --line-ranges=21-30 test.py` will format lines from
|
||||||
|
`1` to `10` and `21` to `30`.
|
||||||
|
|
||||||
|
This option is mainly for editor integrations, such as "Format Selection".
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
Due to [#4052](https://github.com/psf/black/issues/4052), `--line-ranges` might format
|
||||||
|
extra lines outside of the ranges when ther are unformatted lines with the exact
|
||||||
|
content. It also disables _Black_'s formatting stability check in `--safe` mode.
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `--fast` / `--safe`
|
||||||
|
|
||||||
|
By default, _Black_ performs [an AST safety check](labels/ast-changes) after formatting
|
||||||
|
your code. The `--fast` flag turns off this check and the `--safe` flag explicitly
|
||||||
|
enables it.
|
||||||
|
|
||||||
|
#### `--required-version`
|
||||||
|
|
||||||
|
Require a specific version of _Black_ to be running. This is useful for ensuring that
|
||||||
|
all contributors to your project are using the same version, because different versions
|
||||||
|
of _Black_ may format code a little differently. This option can be set in a
|
||||||
|
configuration file for consistent results across environments.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black --version
|
||||||
|
black, 25.1.0 (compiled: yes)
|
||||||
|
$ black --required-version 25.1.0 -c "format = 'this'"
|
||||||
|
format = "this"
|
||||||
|
$ black --required-version 31.5b2 -c "still = 'beta?!'"
|
||||||
|
Oh no! 💥 💔 💥 The required version does not match the running version!
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also pass just the major version:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black --required-version 22 -c "format = 'this'"
|
||||||
|
format = "this"
|
||||||
|
$ black --required-version 31 -c "still = 'beta?!'"
|
||||||
|
Oh no! 💥 💔 💥 The required version does not match the running version!
|
||||||
|
```
|
||||||
|
|
||||||
|
Because of our [stability policy](../the_black_code_style/index.md), this will guarantee
|
||||||
|
stable formatting, but still allow you to take advantage of improvements that do not
|
||||||
|
affect formatting.
|
||||||
|
|
||||||
|
#### `--exclude`
|
||||||
|
|
||||||
|
A regular expression that matches files and directories that should be excluded on
|
||||||
|
recursive searches. An empty value means no paths are excluded. Use forward slashes for
|
||||||
|
directories on all platforms (Windows, too). By default, Black also ignores all paths
|
||||||
|
listed in `.gitignore`. Changing this value will override all default exclusions.
|
||||||
|
|
||||||
|
If the regular expression contains newlines, it is treated as a
|
||||||
|
[verbose regular expression](https://docs.python.org/3/library/re.html#re.VERBOSE). This
|
||||||
|
is typically useful when setting these options in a `pyproject.toml` configuration file;
|
||||||
|
see [Configuration format](#configuration-format) for more information.
|
||||||
|
|
||||||
|
#### `--extend-exclude`
|
||||||
|
|
||||||
|
Like `--exclude`, but adds additional files and directories on top of the default values
|
||||||
|
instead of overriding them.
|
||||||
|
|
||||||
|
#### `--force-exclude`
|
||||||
|
|
||||||
|
Like `--exclude`, but files and directories matching this regex will be excluded even
|
||||||
|
when they are passed explicitly as arguments. This is useful when invoking Black
|
||||||
|
programmatically on changed files, such as in a pre-commit hook or editor plugin.
|
||||||
|
|
||||||
|
#### `--stdin-filename`
|
||||||
|
|
||||||
|
The name of the file when passing it through stdin. Useful to make sure Black will
|
||||||
|
respect the `--force-exclude` option on some editors that rely on using stdin.
|
||||||
|
|
||||||
|
#### `--include`
|
||||||
|
|
||||||
|
A regular expression that matches files and directories that should be included on
|
||||||
|
recursive searches. An empty value means all files are included regardless of the name.
|
||||||
|
Use forward slashes for directories on all platforms (Windows, too). Overrides all
|
||||||
|
exclusions, including from `.gitignore` and command line options.
|
||||||
|
|
||||||
|
#### `-W`, `--workers`
|
||||||
|
|
||||||
|
When _Black_ formats multiple files, it may use a process pool to speed up formatting.
|
||||||
|
This option controls the number of parallel workers. This can also be specified via the
|
||||||
|
`BLACK_NUM_WORKERS` environment variable. Defaults to the number of CPUs in the system.
|
||||||
|
|
||||||
|
#### `-q`, `--quiet`
|
||||||
|
|
||||||
|
Stop emitting all non-critical output. Error messages will still be emitted (which can
|
||||||
|
silenced by `2>/dev/null`).
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black src/ -q
|
||||||
|
error: cannot format src/black_primer/cli.py: Cannot parse: 5:6: mport asyncio
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `-v`, `--verbose`
|
||||||
|
|
||||||
|
Emit messages about files that were not changed or were ignored due to exclusion
|
||||||
|
patterns. If _Black_ is using a configuration file, a message detailing which one it is
|
||||||
|
using will be emitted.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black src/ -v
|
||||||
|
Using configuration from /tmp/pyproject.toml.
|
||||||
|
src/blib2to3 ignored: matches the --extend-exclude regular expression
|
||||||
|
src/_black_version.py wasn't modified on disk since last run.
|
||||||
|
src/black/__main__.py wasn't modified on disk since last run.
|
||||||
|
error: cannot format src/black_primer/cli.py: Cannot parse: 5:6: mport asyncio
|
||||||
|
reformatted src/black_primer/lib.py
|
||||||
|
reformatted src/blackd/__init__.py
|
||||||
|
reformatted src/black/__init__.py
|
||||||
|
Oh no! 💥 💔 💥
|
||||||
|
3 files reformatted, 2 files left unchanged, 1 file failed to reformat
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `--version`
|
||||||
|
|
||||||
|
You can check the version of _Black_ you have installed using the `--version` flag.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black --version
|
||||||
|
black, 25.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `--config`
|
||||||
|
|
||||||
|
Read configuration options from a configuration file. See
|
||||||
|
[below](#configuration-via-a-file) for more details on the configuration file.
|
||||||
|
|
||||||
|
### Environment variable options
|
||||||
|
|
||||||
|
_Black_ supports the following configuration via environment variables.
|
||||||
|
|
||||||
|
#### `BLACK_CACHE_DIR`
|
||||||
|
|
||||||
|
The directory where _Black_ should store its cache.
|
||||||
|
|
||||||
|
#### `BLACK_NUM_WORKERS`
|
||||||
|
|
||||||
|
The number of parallel workers _Black_ should use. The command line option `-W` /
|
||||||
|
`--workers` takes precedence over this environment variable.
|
||||||
|
|
||||||
|
### Code input alternatives
|
||||||
|
|
||||||
|
_Black_ supports formatting code via stdin, with the result being printed to stdout.
|
||||||
|
Just let _Black_ know with `-` as the path.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ echo "print ( 'hello, world' )" | black -
|
||||||
|
print("hello, world")
|
||||||
|
reformatted -
|
||||||
|
All done! ✨ 🍰 ✨
|
||||||
|
1 file reformatted.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tip:** if you need _Black_ to treat stdin input as a file passed directly via the CLI,
|
||||||
|
use `--stdin-filename`. Useful to make sure _Black_ will respect the `--force-exclude`
|
||||||
|
option on some editors that rely on using stdin.
|
||||||
|
|
||||||
|
You can also pass code as a string using the `--code` option.
|
||||||
|
|
||||||
|
### Writeback and reporting
|
||||||
|
|
||||||
|
By default _Black_ reformats the files given and/or found in place. Sometimes you need
|
||||||
|
_Black_ to just tell you what it _would_ do without actually rewriting the Python files.
|
||||||
|
|
||||||
|
There's two variations to this mode that are independently enabled by their respective
|
||||||
|
flags:
|
||||||
|
|
||||||
|
- `--check` (exit with code 1 if any file would be reformatted)
|
||||||
|
- `--diff` (print a diff instead of reformatting files)
|
||||||
|
|
||||||
|
Both variations can be enabled at once.
|
||||||
|
|
||||||
### Output verbosity
|
### Output verbosity
|
||||||
|
|
||||||
_Black_ in general tries to produce the right amount of output, balancing between
|
_Black_ in general tries to produce the right amount of output, balancing between
|
||||||
@ -141,53 +435,7 @@ Oh no! 💥 💔 💥
|
|||||||
3 files reformatted, 2 files left unchanged, 1 file failed to reformat.
|
3 files reformatted, 2 files left unchanged, 1 file failed to reformat.
|
||||||
```
|
```
|
||||||
|
|
||||||
Passing `-v` / `--verbose` will cause _Black_ to also emit messages about files that
|
The `--quiet` and `--verbose` flags control output verbosity.
|
||||||
were not changed or were ignored due to exclusion patterns. If _Black_ is using a
|
|
||||||
configuration file, a blue message detailing which one it is using will be emitted.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black src/ -v
|
|
||||||
Using configuration from /tmp/pyproject.toml.
|
|
||||||
src/blib2to3 ignored: matches the --extend-exclude regular expression
|
|
||||||
src/_black_version.py wasn't modified on disk since last run.
|
|
||||||
src/black/__main__.py wasn't modified on disk since last run.
|
|
||||||
error: cannot format src/black_primer/cli.py: Cannot parse: 5:6: mport asyncio
|
|
||||||
reformatted src/black_primer/lib.py
|
|
||||||
reformatted src/blackd/__init__.py
|
|
||||||
reformatted src/black/__init__.py
|
|
||||||
Oh no! 💥 💔 💥
|
|
||||||
3 files reformatted, 2 files left unchanged, 1 file failed to reformat
|
|
||||||
```
|
|
||||||
|
|
||||||
Passing `-q` / `--quiet` will cause _Black_ to stop emitting all non-critial output.
|
|
||||||
Error messages will still be emitted (which can silenced by `2>/dev/null`).
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black src/ -q
|
|
||||||
error: cannot format src/black_primer/cli.py: Cannot parse: 5:6: mport asyncio
|
|
||||||
```
|
|
||||||
|
|
||||||
### Versions
|
|
||||||
|
|
||||||
You can check the version of _Black_ you have installed using the `--version` flag.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black --version
|
|
||||||
black, version 21.5b0
|
|
||||||
```
|
|
||||||
|
|
||||||
An option to require a specific version to be running is also provided.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black --required-version 21.5b2 -c "format = 'this'"
|
|
||||||
format = "this"
|
|
||||||
$ black --required-version 31.5b2 -c "still = 'beta?!'"
|
|
||||||
Oh no! 💥 💔 💥 The required version does not match the running version!
|
|
||||||
```
|
|
||||||
|
|
||||||
This is useful for example when running _Black_ in multiple environments that haven't
|
|
||||||
necessarily installed the correct version. This option can be set in a configuration
|
|
||||||
file for consistent results across environments.
|
|
||||||
|
|
||||||
## Configuration via a file
|
## Configuration via a file
|
||||||
|
|
||||||
@ -204,16 +452,18 @@ code in compliance with many other _Black_ formatted projects.
|
|||||||
|
|
||||||
[PEP 518](https://www.python.org/dev/peps/pep-0518/) defines `pyproject.toml` as a
|
[PEP 518](https://www.python.org/dev/peps/pep-0518/) defines `pyproject.toml` as a
|
||||||
configuration file to store build system requirements for Python projects. With the help
|
configuration file to store build system requirements for Python projects. With the help
|
||||||
of tools like [Poetry](https://python-poetry.org/) or
|
of tools like [Poetry](https://python-poetry.org/),
|
||||||
[Flit](https://flit.readthedocs.io/en/latest/) it can fully replace the need for
|
[Flit](https://flit.readthedocs.io/en/latest/), or
|
||||||
`setup.py` and `setup.cfg` files.
|
[Hatch](https://hatch.pypa.io/latest/) it can fully replace the need for `setup.py` and
|
||||||
|
`setup.cfg` files.
|
||||||
|
|
||||||
### Where _Black_ looks for the file
|
### Where _Black_ looks for the file
|
||||||
|
|
||||||
By default _Black_ looks for `pyproject.toml` starting from the common base directory of
|
By default _Black_ looks for `pyproject.toml` containing a `[tool.black]` section
|
||||||
all files and directories passed on the command line. If it's not there, it looks in
|
starting from the common base directory of all files and directories passed on the
|
||||||
parent directories. It stops looking when it finds the file, or a `.git` directory, or a
|
command line. If it's not there, it looks in parent directories. It stops looking when
|
||||||
`.hg` directory, or the root of the file system, whichever comes first.
|
it finds the file, or a `.git` directory, or a `.hg` directory, or the root of the file
|
||||||
|
system, whichever comes first.
|
||||||
|
|
||||||
If you're formatting standard input, _Black_ will look for configuration starting from
|
If you're formatting standard input, _Black_ will look for configuration starting from
|
||||||
the current working directory.
|
the current working directory.
|
||||||
@ -228,15 +478,15 @@ operating system, this configuration file should be stored as:
|
|||||||
`XDG_CONFIG_HOME` environment variable is not set)
|
`XDG_CONFIG_HOME` environment variable is not set)
|
||||||
|
|
||||||
Note that these are paths to the TOML file itself (meaning that they shouldn't be named
|
Note that these are paths to the TOML file itself (meaning that they shouldn't be named
|
||||||
as `pyproject.toml`), not directories where you store the configuration. Here, `~`
|
as `pyproject.toml`), not directories where you store the configuration (i.e.,
|
||||||
refers to the path to your home directory. On Windows, this will be something like
|
`black`/`.black` is the file to create and add your configuration options to, in the
|
||||||
`C:\\Users\UserName`.
|
`~/.config/` directory). Here, `~` refers to the path to your home directory. On
|
||||||
|
Windows, this will be something like `C:\\Users\UserName`.
|
||||||
|
|
||||||
You can also explicitly specify the path to a particular file that you want with
|
You can also explicitly specify the path to a particular file that you want with
|
||||||
`--config`. In this situation _Black_ will not look for any other file.
|
`--config`. In this situation _Black_ will not look for any other file.
|
||||||
|
|
||||||
If you're running with `--verbose`, you will see a blue message if a file was found and
|
If you're running with `--verbose`, you will see a message if a file was found and used.
|
||||||
used.
|
|
||||||
|
|
||||||
Please note `blackd` will not use `pyproject.toml` configuration.
|
Please note `blackd` will not use `pyproject.toml` configuration.
|
||||||
|
|
||||||
@ -259,10 +509,14 @@ expressions by Black. Use `[ ]` to denote a significant space character.
|
|||||||
line-length = 88
|
line-length = 88
|
||||||
target-version = ['py37']
|
target-version = ['py37']
|
||||||
include = '\.pyi?$'
|
include = '\.pyi?$'
|
||||||
|
# 'extend-exclude' excludes files or directories in addition to the defaults
|
||||||
extend-exclude = '''
|
extend-exclude = '''
|
||||||
# A regex preceded with ^/ will apply only to files and directories
|
# A regex preceded with ^/ will apply only to files and directories
|
||||||
# in the root of the project.
|
# in the root of the project.
|
||||||
^/foo.py # exclude a file named foo.py in the root of the project (in addition to the defaults)
|
(
|
||||||
|
^/foo.py # exclude a file named foo.py in the root of the project
|
||||||
|
| .*_pb2.py # exclude autogenerated Protocol Buffer files anywhere in the project
|
||||||
|
)
|
||||||
'''
|
'''
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -280,9 +534,6 @@ file hierarchy.
|
|||||||
|
|
||||||
## Next steps
|
## Next steps
|
||||||
|
|
||||||
You've probably noted that not all of the options you can pass to _Black_ have been
|
|
||||||
covered. Don't worry, the rest will be covered in a later section.
|
|
||||||
|
|
||||||
A good next step would be configuring auto-discovery so `black .` is all you need
|
A good next step would be configuring auto-discovery so `black .` is all you need
|
||||||
instead of laborously listing every file or directory. You can get started by heading
|
instead of laborously listing every file or directory. You can get started by heading
|
||||||
over to [File collection and discovery](./file_collection_and_discovery.md).
|
over to [File collection and discovery](./file_collection_and_discovery.md).
|
||||||
|
@ -7,29 +7,20 @@
|
|||||||
import venv
|
import venv
|
||||||
import zipfile
|
import zipfile
|
||||||
from argparse import ArgumentParser, Namespace
|
from argparse import ArgumentParser, Namespace
|
||||||
|
from collections.abc import Generator
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from functools import lru_cache, partial
|
from functools import lru_cache, partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import ( # type: ignore # typing can't see Literal
|
from typing import NamedTuple, Optional, Union, cast
|
||||||
Generator,
|
|
||||||
List,
|
|
||||||
Literal,
|
|
||||||
NamedTuple,
|
|
||||||
Optional,
|
|
||||||
Tuple,
|
|
||||||
Union,
|
|
||||||
cast,
|
|
||||||
)
|
|
||||||
from urllib.request import urlopen, urlretrieve
|
from urllib.request import urlopen, urlretrieve
|
||||||
|
|
||||||
PYPI_INSTANCE = "https://pypi.org/pypi"
|
PYPI_INSTANCE = "https://pypi.org/pypi"
|
||||||
PYPI_TOP_PACKAGES = (
|
PYPI_TOP_PACKAGES = (
|
||||||
"https://hugovk.github.io/top-pypi-packages/top-pypi-packages-{days}-days.json"
|
"https://hugovk.github.io/top-pypi-packages/top-pypi-packages.min.json"
|
||||||
)
|
)
|
||||||
INTERNAL_BLACK_REPO = f"{tempfile.gettempdir()}/__black"
|
INTERNAL_BLACK_REPO = f"{tempfile.gettempdir()}/__black"
|
||||||
|
|
||||||
ArchiveKind = Union[tarfile.TarFile, zipfile.ZipFile]
|
ArchiveKind = Union[tarfile.TarFile, zipfile.ZipFile]
|
||||||
Days = Union[Literal[30], Literal[365]]
|
|
||||||
|
|
||||||
subprocess.run = partial(subprocess.run, check=True) # type: ignore
|
subprocess.run = partial(subprocess.run, check=True) # type: ignore
|
||||||
# https://github.com/python/mypy/issues/1484
|
# https://github.com/python/mypy/issues/1484
|
||||||
@ -64,8 +55,8 @@ def get_pypi_download_url(package: str, version: Optional[str]) -> str:
|
|||||||
return cast(str, source["url"])
|
return cast(str, source["url"])
|
||||||
|
|
||||||
|
|
||||||
def get_top_packages(days: Days) -> List[str]:
|
def get_top_packages() -> list[str]:
|
||||||
with urlopen(PYPI_TOP_PACKAGES.format(days=days)) as page:
|
with urlopen(PYPI_TOP_PACKAGES) as page:
|
||||||
result = json.load(page)
|
result = json.load(page)
|
||||||
|
|
||||||
return [package["project"] for package in result["rows"]]
|
return [package["project"] for package in result["rows"]]
|
||||||
@ -128,13 +119,12 @@ def get_package(
|
|||||||
|
|
||||||
def download_and_extract_top_packages(
|
def download_and_extract_top_packages(
|
||||||
directory: Path,
|
directory: Path,
|
||||||
days: Days = 365,
|
|
||||||
workers: int = 8,
|
workers: int = 8,
|
||||||
limit: slice = DEFAULT_SLICE,
|
limit: slice = DEFAULT_SLICE,
|
||||||
) -> Generator[Path, None, None]:
|
) -> Generator[Path, None, None]:
|
||||||
with ThreadPoolExecutor(max_workers=workers) as executor:
|
with ThreadPoolExecutor(max_workers=workers) as executor:
|
||||||
bound_downloader = partial(get_package, version=None, directory=directory)
|
bound_downloader = partial(get_package, version=None, directory=directory)
|
||||||
for package in executor.map(bound_downloader, get_top_packages(days)[limit]):
|
for package in executor.map(bound_downloader, get_top_packages()[limit]):
|
||||||
if package is not None:
|
if package is not None:
|
||||||
yield package
|
yield package
|
||||||
|
|
||||||
@ -161,7 +151,7 @@ def git_switch_branch(
|
|||||||
subprocess.run(args, cwd=repo)
|
subprocess.run(args, cwd=repo)
|
||||||
|
|
||||||
|
|
||||||
def init_repos(options: Namespace) -> Tuple[Path, ...]:
|
def init_repos(options: Namespace) -> tuple[Path, ...]:
|
||||||
options.output.mkdir(exist_ok=True)
|
options.output.mkdir(exist_ok=True)
|
||||||
|
|
||||||
if options.top_packages:
|
if options.top_packages:
|
||||||
@ -217,7 +207,7 @@ def format_repo_with_version(
|
|||||||
git_switch_branch(black_version.version, repo=black_repo)
|
git_switch_branch(black_version.version, repo=black_repo)
|
||||||
git_switch_branch(current_branch, repo=repo, new=True, from_branch=from_branch)
|
git_switch_branch(current_branch, repo=repo, new=True, from_branch=from_branch)
|
||||||
|
|
||||||
format_cmd: List[Union[Path, str]] = [
|
format_cmd: list[Union[Path, str]] = [
|
||||||
black_runner(black_version.version, black_repo),
|
black_runner(black_version.version, black_repo),
|
||||||
(black_repo / "black.py").resolve(),
|
(black_repo / "black.py").resolve(),
|
||||||
".",
|
".",
|
||||||
@ -233,7 +223,7 @@ def format_repo_with_version(
|
|||||||
return current_branch
|
return current_branch
|
||||||
|
|
||||||
|
|
||||||
def format_repos(repos: Tuple[Path, ...], options: Namespace) -> None:
|
def format_repos(repos: tuple[Path, ...], options: Namespace) -> None:
|
||||||
black_versions = tuple(
|
black_versions = tuple(
|
||||||
BlackVersion(*version.split(":")) for version in options.versions
|
BlackVersion(*version.split(":")) for version in options.versions
|
||||||
)
|
)
|
||||||
@ -254,11 +244,9 @@ def format_repos(repos: Tuple[Path, ...], options: Namespace) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
parser = ArgumentParser(
|
parser = ArgumentParser(description="""Black Gallery is a script that
|
||||||
description="""Black Gallery is a script that
|
|
||||||
automates the process of applying different Black versions to a selected
|
automates the process of applying different Black versions to a selected
|
||||||
PyPI package and seeing the results between versions."""
|
PyPI package and seeing the results between versions.""")
|
||||||
)
|
|
||||||
|
|
||||||
group = parser.add_mutually_exclusive_group(required=True)
|
group = parser.add_mutually_exclusive_group(required=True)
|
||||||
group.add_argument("-p", "--pypi-package", help="PyPI package to download.")
|
group.add_argument("-p", "--pypi-package", help="PyPI package to download.")
|
||||||
|
39
mypy.ini
39
mypy.ini
@ -1,39 +0,0 @@
|
|||||||
[mypy]
|
|
||||||
# Specify the target platform details in config, so your developers are
|
|
||||||
# free to run mypy on Windows, Linux, or macOS and get consistent
|
|
||||||
# results.
|
|
||||||
python_version=3.6
|
|
||||||
platform=linux
|
|
||||||
|
|
||||||
show_column_numbers=True
|
|
||||||
|
|
||||||
# show error messages from unrelated files
|
|
||||||
follow_imports=normal
|
|
||||||
|
|
||||||
# suppress errors about unsatisfied imports
|
|
||||||
ignore_missing_imports=True
|
|
||||||
|
|
||||||
# be strict
|
|
||||||
disallow_untyped_calls=True
|
|
||||||
warn_return_any=True
|
|
||||||
strict_optional=True
|
|
||||||
warn_no_return=True
|
|
||||||
warn_redundant_casts=True
|
|
||||||
warn_unused_ignores=True
|
|
||||||
# Until we're not supporting 3.6 primer needs this
|
|
||||||
disallow_any_generics=False
|
|
||||||
|
|
||||||
# The following are off by default. Flip them on if you feel
|
|
||||||
# adventurous.
|
|
||||||
disallow_untyped_defs=True
|
|
||||||
check_untyped_defs=True
|
|
||||||
|
|
||||||
# No incremental mode
|
|
||||||
cache_dir=/dev/null
|
|
||||||
|
|
||||||
[mypy-aiohttp.*]
|
|
||||||
follow_imports=skip
|
|
||||||
[mypy-black]
|
|
||||||
# The following is because of `patch_click()`. Remove when
|
|
||||||
# we drop Python 3.6 support.
|
|
||||||
warn_unused_ignores=False
|
|
@ -15,9 +15,13 @@
|
|||||||
" 1.2:
|
" 1.2:
|
||||||
" - use autoload script
|
" - use autoload script
|
||||||
|
|
||||||
|
if exists("g:load_black")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
if v:version < 700 || !has('python3')
|
if v:version < 700 || !has('python3')
|
||||||
func! __BLACK_MISSING()
|
func! __BLACK_MISSING()
|
||||||
echo "The black.vim plugin requires vim7.0+ with Python 3.6 support."
|
echo "The black.vim plugin requires vim7.0+ with Python 3.9 support."
|
||||||
endfunc
|
endfunc
|
||||||
command! Black :call __BLACK_MISSING()
|
command! Black :call __BLACK_MISSING()
|
||||||
command! BlackUpgrade :call __BLACK_MISSING()
|
command! BlackUpgrade :call __BLACK_MISSING()
|
||||||
@ -25,10 +29,6 @@ if v:version < 700 || !has('python3')
|
|||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if exists("g:load_black")
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:load_black = "py1.0"
|
let g:load_black = "py1.0"
|
||||||
if !exists("g:black_virtualenv")
|
if !exists("g:black_virtualenv")
|
||||||
if has("nvim")
|
if has("nvim")
|
||||||
@ -43,18 +43,43 @@ endif
|
|||||||
if !exists("g:black_linelength")
|
if !exists("g:black_linelength")
|
||||||
let g:black_linelength = 88
|
let g:black_linelength = 88
|
||||||
endif
|
endif
|
||||||
if !exists("g:black_string_normalization")
|
if !exists("g:black_skip_string_normalization")
|
||||||
if exists("g:black_skip_string_normalization")
|
if exists("g:black_string_normalization")
|
||||||
let g:black_string_normalization = !g:black_skip_string_normalization
|
let g:black_skip_string_normalization = !g:black_string_normalization
|
||||||
else
|
else
|
||||||
let g:black_string_normalization = 1
|
let g:black_skip_string_normalization = 0
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
if !exists("g:black_skip_magic_trailing_comma")
|
||||||
|
if exists("g:black_magic_trailing_comma")
|
||||||
|
let g:black_skip_magic_trailing_comma = !g:black_magic_trailing_comma
|
||||||
|
else
|
||||||
|
let g:black_skip_magic_trailing_comma = 0
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
if !exists("g:black_quiet")
|
if !exists("g:black_quiet")
|
||||||
let g:black_quiet = 0
|
let g:black_quiet = 0
|
||||||
endif
|
endif
|
||||||
|
if !exists("g:black_target_version")
|
||||||
|
let g:black_target_version = ""
|
||||||
|
endif
|
||||||
|
if !exists("g:black_use_virtualenv")
|
||||||
|
let g:black_use_virtualenv = 1
|
||||||
|
endif
|
||||||
|
if !exists("g:black_preview")
|
||||||
|
let g:black_preview = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
function BlackComplete(ArgLead, CmdLine, CursorPos)
|
||||||
|
return [
|
||||||
|
\ 'target_version=py39',
|
||||||
|
\ 'target_version=py310',
|
||||||
|
\ 'target_version=py311',
|
||||||
|
\ 'target_version=py312',
|
||||||
|
\ 'target_version=py313',
|
||||||
|
\ ]
|
||||||
|
endfunction
|
||||||
|
|
||||||
command! Black :call black#Black()
|
command! -nargs=* -complete=customlist,BlackComplete Black :call black#Black(<f-args>)
|
||||||
command! BlackUpgrade :call black#BlackUpgrade()
|
command! BlackUpgrade :call black#BlackUpgrade()
|
||||||
command! BlackVersion :call black#BlackVersion()
|
command! BlackVersion :call black#BlackVersion()
|
||||||
|
232
pyproject.toml
232
pyproject.toml
@ -7,28 +7,238 @@
|
|||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 88
|
line-length = 88
|
||||||
target-version = ['py36', 'py37', 'py38']
|
target-version = ['py39']
|
||||||
include = '\.pyi?$'
|
include = '\.pyi?$'
|
||||||
extend-exclude = '''
|
extend-exclude = '''
|
||||||
/(
|
/(
|
||||||
# The following are specific to Black, you probably don't want those.
|
# The following are specific to Black, you probably don't want those.
|
||||||
| blib2to3
|
tests/data/
|
||||||
| tests/data
|
| profiling/
|
||||||
| profiling
|
| scripts/generate_schema.py # Uses match syntax
|
||||||
)/
|
)
|
||||||
'''
|
'''
|
||||||
|
# We use the unstable style for formatting Black itself. If you
|
||||||
|
# want bug-free formatting, you should keep this off. If you want
|
||||||
|
# stable formatting across releases, you should also keep `preview = true`
|
||||||
|
# (which is implied by this flag) off.
|
||||||
|
unstable = true
|
||||||
|
|
||||||
|
# Build system information and other project-specific configuration below.
|
||||||
# Build system information below.
|
|
||||||
# NOTE: You don't need this in your own Black configuration.
|
# NOTE: You don't need this in your own Black configuration.
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools>=41.0", "setuptools-scm", "wheel"]
|
requires = ["hatchling>=1.20.0", "hatch-vcs", "hatch-fancy-pypi-readme"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "black"
|
||||||
|
description = "The uncompromising code formatter."
|
||||||
|
license = "MIT"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
authors = [
|
||||||
|
{ name = "Łukasz Langa", email = "lukasz@langa.pl" },
|
||||||
|
]
|
||||||
|
keywords = [
|
||||||
|
"automation",
|
||||||
|
"autopep8",
|
||||||
|
"formatter",
|
||||||
|
"gofmt",
|
||||||
|
"pyfmt",
|
||||||
|
"rustfmt",
|
||||||
|
"yapf",
|
||||||
|
]
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 5 - Production/Stable",
|
||||||
|
"Environment :: Console",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 3 :: Only",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
"Topic :: Software Development :: Quality Assurance",
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"click>=8.0.0",
|
||||||
|
"mypy_extensions>=0.4.3",
|
||||||
|
"packaging>=22.0",
|
||||||
|
"pathspec>=0.9.0",
|
||||||
|
"platformdirs>=2",
|
||||||
|
"pytokens>=0.1.10",
|
||||||
|
"tomli>=1.1.0; python_version < '3.11'",
|
||||||
|
"typing_extensions>=4.0.1; python_version < '3.11'",
|
||||||
|
]
|
||||||
|
dynamic = ["readme", "version"]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
colorama = ["colorama>=0.4.3"]
|
||||||
|
uvloop = ["uvloop>=0.15.2"]
|
||||||
|
d = ["aiohttp>=3.10"]
|
||||||
|
jupyter = [
|
||||||
|
"ipython>=7.8.0",
|
||||||
|
"tokenize-rt>=3.2.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
black = "black:patched_main"
|
||||||
|
blackd = "blackd:patched_main [d]"
|
||||||
|
|
||||||
|
[project.entry-points."validate_pyproject.tool_schema"]
|
||||||
|
black = "black.schema:get_schema"
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Documentation = "https://black.readthedocs.io/"
|
||||||
|
Changelog = "https://github.com/psf/black/blob/main/CHANGES.md"
|
||||||
|
Repository = "https://github.com/psf/black"
|
||||||
|
Issues = "https://github.com/psf/black/issues"
|
||||||
|
|
||||||
|
[tool.hatch.metadata.hooks.fancy-pypi-readme]
|
||||||
|
content-type = "text/markdown"
|
||||||
|
fragments = [
|
||||||
|
{ path = "README.md" },
|
||||||
|
{ path = "CHANGES.md" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.hatch.version]
|
||||||
|
source = "vcs"
|
||||||
|
|
||||||
|
[tool.hatch.build.hooks.vcs]
|
||||||
|
version-file = "src/_black_version.py"
|
||||||
|
template = '''
|
||||||
|
version = "{version}"
|
||||||
|
'''
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.sdist]
|
||||||
|
exclude = ["/profiling"]
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel]
|
||||||
|
only-include = ["src"]
|
||||||
|
sources = ["src"]
|
||||||
|
# Note that we change the behaviour of this flag below
|
||||||
|
macos-max-compat = true
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel.hooks.mypyc]
|
||||||
|
enable-by-default = false
|
||||||
|
dependencies = [
|
||||||
|
"hatch-mypyc>=0.16.0",
|
||||||
|
"mypy>=1.12",
|
||||||
|
"click>=8.1.7",
|
||||||
|
]
|
||||||
|
require-runtime-dependencies = true
|
||||||
|
exclude = [
|
||||||
|
# There's no good reason for blackd to be compiled.
|
||||||
|
"/src/blackd",
|
||||||
|
# Not performance sensitive, so save bytes + compilation time:
|
||||||
|
"/src/blib2to3/__init__.py",
|
||||||
|
"/src/blib2to3/pgen2/__init__.py",
|
||||||
|
"/src/black/output.py",
|
||||||
|
"/src/black/concurrency.py",
|
||||||
|
"/src/black/files.py",
|
||||||
|
"/src/black/report.py",
|
||||||
|
# Breaks the test suite when compiled (and is also useless):
|
||||||
|
"/src/black/debug.py",
|
||||||
|
# Compiled modules can't be run directly and that's a problem here:
|
||||||
|
"/src/black/__main__.py",
|
||||||
|
]
|
||||||
|
mypy-args = ["--ignore-missing-imports"]
|
||||||
|
options = { debug_level = "0" }
|
||||||
|
|
||||||
|
[tool.cibuildwheel]
|
||||||
|
build-verbosity = 1
|
||||||
|
|
||||||
|
# So these are the environments we target:
|
||||||
|
# - Python: CPython 3.9+ only
|
||||||
|
# - Architecture (64-bit only): amd64 / x86_64, universal2, and arm64
|
||||||
|
# - OS: Linux (no musl), Windows, and macOS
|
||||||
|
build = "cp3*"
|
||||||
|
skip = ["*-manylinux_i686", "*-musllinux_*", "*-win32", "pp*"]
|
||||||
|
|
||||||
|
# This is the bare minimum needed to run the test suite. Pulling in the full
|
||||||
|
# test_requirements.txt would download a bunch of other packages not necessary
|
||||||
|
# here and would slow down the testing step a fair bit.
|
||||||
|
test-requires = ["pytest>=6.1.1"]
|
||||||
|
test-command = 'pytest {project} -k "not incompatible_with_mypyc"'
|
||||||
|
test-extras = ["d"," jupyter"]
|
||||||
|
# Skip trying to test arm64 builds on Intel Macs. (so cross-compilation doesn't
|
||||||
|
# straight up crash)
|
||||||
|
test-skip = ["*-macosx_arm64", "*-macosx_universal2:arm64"]
|
||||||
|
|
||||||
|
[tool.cibuildwheel.environment]
|
||||||
|
HATCH_BUILD_HOOKS_ENABLE = "1"
|
||||||
|
MYPYC_OPT_LEVEL = "3"
|
||||||
|
MYPYC_DEBUG_LEVEL = "0"
|
||||||
|
|
||||||
|
[tool.cibuildwheel.linux]
|
||||||
|
manylinux-x86_64-image = "manylinux_2_28"
|
||||||
|
before-build = [
|
||||||
|
"yum install -y clang gcc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.cibuildwheel.linux.environment]
|
||||||
|
HATCH_BUILD_HOOKS_ENABLE = "1"
|
||||||
|
MYPYC_OPT_LEVEL = "3"
|
||||||
|
MYPYC_DEBUG_LEVEL = "0"
|
||||||
|
|
||||||
|
# Black needs Clang to compile successfully on Linux.
|
||||||
|
CC = "clang"
|
||||||
|
|
||||||
|
[tool.isort]
|
||||||
|
atomic = true
|
||||||
|
profile = "black"
|
||||||
|
line_length = 88
|
||||||
|
skip_gitignore = true
|
||||||
|
skip_glob = ["tests/data", "profiling"]
|
||||||
|
known_first_party = ["black", "blib2to3", "blackd", "_black_version"]
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
# Option below requires `tests/optional.py`
|
# Option below requires `tests/optional.py`
|
||||||
|
addopts = "--strict-config --strict-markers"
|
||||||
optional-tests = [
|
optional-tests = [
|
||||||
"no_python2: run when `python2` extra NOT installed",
|
|
||||||
"no_blackd: run when `d` extra NOT installed",
|
"no_blackd: run when `d` extra NOT installed",
|
||||||
]
|
"no_jupyter: run when `jupyter` extra NOT installed",
|
||||||
|
]
|
||||||
|
markers = [
|
||||||
|
"incompatible_with_mypyc: run when testing mypyc compiled black"
|
||||||
|
]
|
||||||
|
xfail_strict = true
|
||||||
|
filterwarnings = ["error"]
|
||||||
|
[tool.coverage.report]
|
||||||
|
omit = [
|
||||||
|
"src/blib2to3/*",
|
||||||
|
"tests/data/*",
|
||||||
|
"*/site-packages/*",
|
||||||
|
".tox/*"
|
||||||
|
]
|
||||||
|
[tool.coverage.run]
|
||||||
|
relative_files = true
|
||||||
|
branch = true
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
# Specify the target platform details in config, so your developers are
|
||||||
|
# free to run mypy on Windows, Linux, or macOS and get consistent
|
||||||
|
# results.
|
||||||
|
python_version = "3.9"
|
||||||
|
mypy_path = "src"
|
||||||
|
strict = true
|
||||||
|
strict_bytes = true
|
||||||
|
local_partial_types = true
|
||||||
|
# Unreachable blocks have been an issue when compiling mypyc, let's try to avoid 'em in the first place.
|
||||||
|
warn_unreachable = true
|
||||||
|
implicit_reexport = true
|
||||||
|
show_error_codes = true
|
||||||
|
show_column_numbers = true
|
||||||
|
|
||||||
|
[[tool.mypy.overrides]]
|
||||||
|
module = ["pathspec.*", "IPython.*", "colorama.*", "tokenize_rt.*", "uvloop.*", "_black_version.*"]
|
||||||
|
ignore_missing_imports = true
|
||||||
|
|
||||||
|
# CI only checks src/, but in case users are running LSP or similar we explicitly ignore
|
||||||
|
# errors in test data files.
|
||||||
|
[[tool.mypy.overrides]]
|
||||||
|
module = ["tests.data.*"]
|
||||||
|
ignore_errors = true
|
||||||
|
0
scripts/__init__.py
Normal file
0
scripts/__init__.py
Normal file
54
scripts/check_pre_commit_rev_in_example.py
Normal file
54
scripts/check_pre_commit_rev_in_example.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"""
|
||||||
|
Check that the rev value in the example pre-commit configuration matches
|
||||||
|
the latest version of Black. This saves us from forgetting to update that
|
||||||
|
during the release process.
|
||||||
|
|
||||||
|
Why can't we just use `rev: stable` and call it a day? Well pre-commit
|
||||||
|
won't auto update the hook as you may expect (and for good reasons, some
|
||||||
|
technical and some pragmatic). Encouraging bad practice is also just
|
||||||
|
not ideal. xref: https://github.com/psf/black/issues/420
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import commonmark
|
||||||
|
import yaml
|
||||||
|
from bs4 import BeautifulSoup # type: ignore[import-untyped]
|
||||||
|
|
||||||
|
|
||||||
|
def main(changes: str, source_version_control: str) -> None:
|
||||||
|
changes_html = commonmark.commonmark(changes)
|
||||||
|
changes_soup = BeautifulSoup(changes_html, "html.parser")
|
||||||
|
headers = changes_soup.find_all("h2")
|
||||||
|
latest_tag, *_ = [
|
||||||
|
header.string for header in headers if header.string != "Unreleased"
|
||||||
|
]
|
||||||
|
|
||||||
|
source_version_control_html = commonmark.commonmark(source_version_control)
|
||||||
|
source_version_control_soup = BeautifulSoup(
|
||||||
|
source_version_control_html, "html.parser"
|
||||||
|
)
|
||||||
|
pre_commit_repos = yaml.safe_load(
|
||||||
|
source_version_control_soup.find(class_="language-yaml").string
|
||||||
|
)["repos"]
|
||||||
|
|
||||||
|
for repo in pre_commit_repos:
|
||||||
|
pre_commit_rev = repo["rev"]
|
||||||
|
if not pre_commit_rev == latest_tag:
|
||||||
|
print(
|
||||||
|
"Please set the rev in ``source_version_control.md`` to be the latest "
|
||||||
|
f"one.\nExpected {latest_tag}, got {pre_commit_rev}.\n"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
with open("CHANGES.md", encoding="utf-8") as fd:
|
||||||
|
changes = fd.read()
|
||||||
|
with open(
|
||||||
|
os.path.join("docs", "integrations", "source_version_control.md"),
|
||||||
|
encoding="utf-8",
|
||||||
|
) as fd:
|
||||||
|
source_version_control = fd.read()
|
||||||
|
main(changes, source_version_control)
|
48
scripts/check_version_in_basics_example.py
Normal file
48
scripts/check_version_in_basics_example.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
"""
|
||||||
|
Check that the rev value in the example from ``the_basics.md`` matches
|
||||||
|
the latest version of Black. This saves us from forgetting to update that
|
||||||
|
during the release process.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import commonmark
|
||||||
|
from bs4 import BeautifulSoup # type: ignore[import-untyped]
|
||||||
|
|
||||||
|
|
||||||
|
def main(changes: str, the_basics: str) -> None:
|
||||||
|
changes_html = commonmark.commonmark(changes)
|
||||||
|
changes_soup = BeautifulSoup(changes_html, "html.parser")
|
||||||
|
headers = changes_soup.find_all("h2")
|
||||||
|
tags = [header.string for header in headers if header.string != "Unreleased"]
|
||||||
|
latest_tag = tags[0]
|
||||||
|
|
||||||
|
the_basics_html = commonmark.commonmark(the_basics)
|
||||||
|
the_basics_soup = BeautifulSoup(the_basics_html, "html.parser")
|
||||||
|
version_examples = [
|
||||||
|
code_block.string
|
||||||
|
for code_block in the_basics_soup.find_all(class_="language-console")
|
||||||
|
if "$ black --version" in code_block.string
|
||||||
|
]
|
||||||
|
|
||||||
|
for tag in tags:
|
||||||
|
for version_example in version_examples:
|
||||||
|
if tag in version_example and tag != latest_tag:
|
||||||
|
print(
|
||||||
|
"Please set the version in the ``black --version`` "
|
||||||
|
"examples from ``the_basics.md`` to be the latest one.\n"
|
||||||
|
f"Expected {latest_tag}, got {tag}.\n"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
with open("CHANGES.md", encoding="utf-8") as fd:
|
||||||
|
changes = fd.read()
|
||||||
|
with open(
|
||||||
|
os.path.join("docs", "usage_and_configuration", "the_basics.md"),
|
||||||
|
encoding="utf-8",
|
||||||
|
) as fd:
|
||||||
|
the_basics = fd.read()
|
||||||
|
main(changes, the_basics)
|
231
scripts/diff_shades_gha_helper.py
Normal file
231
scripts/diff_shades_gha_helper.py
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
"""Helper script for psf/black's diff-shades Github Actions integration.
|
||||||
|
|
||||||
|
diff-shades is a tool for analyzing what happens when you run Black on
|
||||||
|
OSS code capturing it for comparisons or other usage. It's used here to
|
||||||
|
help measure the impact of a change *before* landing it (in particular
|
||||||
|
posting a comment on completion for PRs).
|
||||||
|
|
||||||
|
This script exists as a more maintainable alternative to using inline
|
||||||
|
Javascript in the workflow YAML files. The revision configuration and
|
||||||
|
resolving, caching, and PR comment logic is contained here.
|
||||||
|
|
||||||
|
For more information, please see the developer docs:
|
||||||
|
|
||||||
|
https://black.readthedocs.io/en/latest/contributing/gauging_changes.html#diff-shades
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
import pprint
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import zipfile
|
||||||
|
from base64 import b64encode
|
||||||
|
from io import BytesIO
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Final, Literal
|
||||||
|
|
||||||
|
import click
|
||||||
|
import urllib3
|
||||||
|
from packaging.version import Version
|
||||||
|
|
||||||
|
COMMENT_FILE: Final = ".pr-comment.json"
|
||||||
|
DIFF_STEP_NAME: Final = "Generate HTML diff report"
|
||||||
|
DOCS_URL: Final = (
|
||||||
|
"https://black.readthedocs.io/en/latest/"
|
||||||
|
"contributing/gauging_changes.html#diff-shades"
|
||||||
|
)
|
||||||
|
USER_AGENT: Final = f"psf/black diff-shades workflow via urllib3/{urllib3.__version__}"
|
||||||
|
SHA_LENGTH: Final = 10
|
||||||
|
GH_API_TOKEN: Final = os.getenv("GITHUB_TOKEN")
|
||||||
|
REPO: Final = os.getenv("GITHUB_REPOSITORY", default="psf/black")
|
||||||
|
http = urllib3.PoolManager()
|
||||||
|
|
||||||
|
|
||||||
|
def set_output(name: str, value: str) -> None:
|
||||||
|
if len(value) < 200:
|
||||||
|
print(f"[INFO]: setting '{name}' to '{value}'")
|
||||||
|
else:
|
||||||
|
print(f"[INFO]: setting '{name}' to [{len(value)} chars]")
|
||||||
|
|
||||||
|
if "GITHUB_OUTPUT" in os.environ:
|
||||||
|
if "\n" in value:
|
||||||
|
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
|
||||||
|
delimiter = b64encode(os.urandom(16)).decode()
|
||||||
|
value = f"{delimiter}\n{value}\n{delimiter}"
|
||||||
|
command = f"{name}<<{value}"
|
||||||
|
else:
|
||||||
|
command = f"{name}={value}"
|
||||||
|
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
|
||||||
|
print(command, file=f)
|
||||||
|
|
||||||
|
|
||||||
|
def http_get(url: str, *, is_json: bool = True, **kwargs: Any) -> Any:
|
||||||
|
headers = kwargs.get("headers") or {}
|
||||||
|
headers["User-Agent"] = USER_AGENT
|
||||||
|
if "github" in url:
|
||||||
|
if GH_API_TOKEN:
|
||||||
|
headers["Authorization"] = f"token {GH_API_TOKEN}"
|
||||||
|
headers["Accept"] = "application/vnd.github.v3+json"
|
||||||
|
kwargs["headers"] = headers
|
||||||
|
|
||||||
|
r = http.request("GET", url, **kwargs)
|
||||||
|
if is_json:
|
||||||
|
data = json.loads(r.data.decode("utf-8"))
|
||||||
|
else:
|
||||||
|
data = r.data
|
||||||
|
print(f"[INFO]: issued GET request for {r.geturl()}")
|
||||||
|
if not (200 <= r.status < 300):
|
||||||
|
pprint.pprint(dict(r.info()))
|
||||||
|
pprint.pprint(data)
|
||||||
|
raise RuntimeError(f"unexpected status code: {r.status}")
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_main_revision() -> str:
|
||||||
|
data = http_get(
|
||||||
|
f"https://api.github.com/repos/{REPO}/commits",
|
||||||
|
fields={"per_page": "1", "sha": "main"},
|
||||||
|
)
|
||||||
|
assert isinstance(data[0]["sha"], str)
|
||||||
|
return data[0]["sha"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_pr_revision(pr: int) -> str:
|
||||||
|
data = http_get(f"https://api.github.com/repos/{REPO}/pulls/{pr}")
|
||||||
|
assert isinstance(data["head"]["sha"], str)
|
||||||
|
return data["head"]["sha"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_pypi_version() -> Version:
|
||||||
|
data = http_get("https://pypi.org/pypi/black/json")
|
||||||
|
versions = [Version(v) for v in data["releases"]]
|
||||||
|
sorted_versions = sorted(versions, reverse=True)
|
||||||
|
return sorted_versions[0]
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def main() -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@main.command("config", help="Acquire run configuration and metadata.")
|
||||||
|
@click.argument("event", type=click.Choice(["push", "pull_request"]))
|
||||||
|
def config(event: Literal["push", "pull_request"]) -> None:
|
||||||
|
import diff_shades # type: ignore[import-not-found]
|
||||||
|
|
||||||
|
if event == "push":
|
||||||
|
jobs = [{"mode": "preview-changes", "force-flag": "--force-preview-style"}]
|
||||||
|
# Push on main, let's use PyPI Black as the baseline.
|
||||||
|
baseline_name = str(get_pypi_version())
|
||||||
|
baseline_cmd = f"git checkout {baseline_name}"
|
||||||
|
target_rev = os.getenv("GITHUB_SHA")
|
||||||
|
assert target_rev is not None
|
||||||
|
target_name = "main-" + target_rev[:SHA_LENGTH]
|
||||||
|
target_cmd = f"git checkout {target_rev}"
|
||||||
|
|
||||||
|
elif event == "pull_request":
|
||||||
|
jobs = [
|
||||||
|
{"mode": "preview-changes", "force-flag": "--force-preview-style"},
|
||||||
|
{"mode": "assert-no-changes", "force-flag": "--force-stable-style"},
|
||||||
|
]
|
||||||
|
# PR, let's use main as the baseline.
|
||||||
|
baseline_rev = get_main_revision()
|
||||||
|
baseline_name = "main-" + baseline_rev[:SHA_LENGTH]
|
||||||
|
baseline_cmd = f"git checkout {baseline_rev}"
|
||||||
|
pr_ref = os.getenv("GITHUB_REF")
|
||||||
|
assert pr_ref is not None
|
||||||
|
pr_num = int(pr_ref[10:-6])
|
||||||
|
pr_rev = get_pr_revision(pr_num)
|
||||||
|
target_name = f"pr-{pr_num}-{pr_rev[:SHA_LENGTH]}"
|
||||||
|
target_cmd = f"gh pr checkout {pr_num} && git merge origin/main"
|
||||||
|
|
||||||
|
env = f"{platform.system()}-{platform.python_version()}-{diff_shades.__version__}"
|
||||||
|
for entry in jobs:
|
||||||
|
entry["baseline-analysis"] = f"{entry['mode']}-{baseline_name}.json"
|
||||||
|
entry["baseline-setup-cmd"] = baseline_cmd
|
||||||
|
entry["target-analysis"] = f"{entry['mode']}-{target_name}.json"
|
||||||
|
entry["target-setup-cmd"] = target_cmd
|
||||||
|
entry["baseline-cache-key"] = f"{env}-{baseline_name}-{entry['mode']}"
|
||||||
|
if event == "pull_request":
|
||||||
|
# These are only needed for the PR comment.
|
||||||
|
entry["baseline-sha"] = baseline_rev
|
||||||
|
entry["target-sha"] = pr_rev
|
||||||
|
|
||||||
|
set_output("matrix", json.dumps(jobs, indent=None))
|
||||||
|
pprint.pprint(jobs)
|
||||||
|
|
||||||
|
|
||||||
|
@main.command("comment-body", help="Generate the body for a summary PR comment.")
|
||||||
|
@click.argument("baseline", type=click.Path(exists=True, path_type=Path))
|
||||||
|
@click.argument("target", type=click.Path(exists=True, path_type=Path))
|
||||||
|
@click.argument("baseline-sha")
|
||||||
|
@click.argument("target-sha")
|
||||||
|
@click.argument("pr-num", type=int)
|
||||||
|
def comment_body(
|
||||||
|
baseline: Path, target: Path, baseline_sha: str, target_sha: str, pr_num: int
|
||||||
|
) -> None:
|
||||||
|
# fmt: off
|
||||||
|
cmd = [
|
||||||
|
sys.executable, "-m", "diff_shades", "--no-color",
|
||||||
|
"compare", str(baseline), str(target), "--quiet", "--check"
|
||||||
|
]
|
||||||
|
# fmt: on
|
||||||
|
proc = subprocess.run(cmd, stdout=subprocess.PIPE, encoding="utf-8")
|
||||||
|
if not proc.returncode:
|
||||||
|
body = (
|
||||||
|
f"**diff-shades** reports zero changes comparing this PR ({target_sha}) to"
|
||||||
|
f" main ({baseline_sha}).\n\n---\n\n"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
body = (
|
||||||
|
f"**diff-shades** results comparing this PR ({target_sha}) to main"
|
||||||
|
f" ({baseline_sha}). The full diff is [available in the logs]"
|
||||||
|
f'($job-diff-url) under the "{DIFF_STEP_NAME}" step.'
|
||||||
|
)
|
||||||
|
body += "\n```text\n" + proc.stdout.strip() + "\n```\n"
|
||||||
|
body += (
|
||||||
|
f"[**What is this?**]({DOCS_URL}) | [Workflow run]($workflow-run-url) |"
|
||||||
|
" [diff-shades documentation](https://github.com/ichard26/diff-shades#readme)"
|
||||||
|
)
|
||||||
|
print(f"[INFO]: writing comment details to {COMMENT_FILE}")
|
||||||
|
with open(COMMENT_FILE, "w", encoding="utf-8") as f:
|
||||||
|
json.dump({"body": body, "pr-number": pr_num}, f)
|
||||||
|
|
||||||
|
|
||||||
|
@main.command("comment-details", help="Get PR comment resources from a workflow run.")
|
||||||
|
@click.argument("run-id")
|
||||||
|
def comment_details(run_id: str) -> None:
|
||||||
|
data = http_get(f"https://api.github.com/repos/{REPO}/actions/runs/{run_id}")
|
||||||
|
if data["event"] != "pull_request" or data["conclusion"] == "cancelled":
|
||||||
|
set_output("needs-comment", "false")
|
||||||
|
return
|
||||||
|
|
||||||
|
set_output("needs-comment", "true")
|
||||||
|
jobs = http_get(data["jobs_url"])["jobs"]
|
||||||
|
job = next(j for j in jobs if j["name"] == "analysis / preview-changes")
|
||||||
|
diff_step = next(s for s in job["steps"] if s["name"] == DIFF_STEP_NAME)
|
||||||
|
diff_url = job["html_url"] + f"#step:{diff_step['number']}:1"
|
||||||
|
|
||||||
|
artifacts = http_get(data["artifacts_url"])["artifacts"]
|
||||||
|
comment_artifact = next(a for a in artifacts if a["name"] == COMMENT_FILE)
|
||||||
|
comment_url = comment_artifact["archive_download_url"]
|
||||||
|
comment_zip = BytesIO(http_get(comment_url, is_json=False))
|
||||||
|
with zipfile.ZipFile(comment_zip) as zfile:
|
||||||
|
with zfile.open(COMMENT_FILE) as rf:
|
||||||
|
comment_data = json.loads(rf.read().decode("utf-8"))
|
||||||
|
|
||||||
|
set_output("pr-number", str(comment_data["pr-number"]))
|
||||||
|
body = comment_data["body"]
|
||||||
|
# It's more convenient to fill in these fields after the first workflow is done
|
||||||
|
# since this command can access the workflows API (doing it in the main workflow
|
||||||
|
# while it's still in progress seems impossible).
|
||||||
|
body = body.replace("$workflow-run-url", data["html_url"])
|
||||||
|
body = body.replace("$job-diff-url", diff_url)
|
||||||
|
set_output("comment-body", body)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -5,13 +5,11 @@
|
|||||||
a coverage-guided fuzzer I'm working on.
|
a coverage-guided fuzzer I'm working on.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
import hypothesmith
|
import hypothesmith
|
||||||
from hypothesis import HealthCheck, given, settings, strategies as st
|
from hypothesis import HealthCheck, given, settings
|
||||||
|
from hypothesis import strategies as st
|
||||||
|
|
||||||
import black
|
import black
|
||||||
from blib2to3.pgen2.tokenize import TokenError
|
|
||||||
|
|
||||||
|
|
||||||
# This test uses the Hypothesis and Hypothesmith libraries to generate random
|
# This test uses the Hypothesis and Hypothesmith libraries to generate random
|
||||||
@ -20,7 +18,7 @@
|
|||||||
max_examples=1000, # roughly 1k tests/minute, or half that under coverage
|
max_examples=1000, # roughly 1k tests/minute, or half that under coverage
|
||||||
derandomize=True, # deterministic mode to avoid CI flakiness
|
derandomize=True, # deterministic mode to avoid CI flakiness
|
||||||
deadline=None, # ignore Hypothesis' health checks; we already know that
|
deadline=None, # ignore Hypothesis' health checks; we already know that
|
||||||
suppress_health_check=HealthCheck.all(), # this is slow and filter-heavy.
|
suppress_health_check=list(HealthCheck), # this is slow and filter-heavy.
|
||||||
)
|
)
|
||||||
@given(
|
@given(
|
||||||
# Note that while Hypothesmith might generate code unlike that written by
|
# Note that while Hypothesmith might generate code unlike that written by
|
||||||
@ -32,7 +30,9 @@
|
|||||||
black.FileMode,
|
black.FileMode,
|
||||||
line_length=st.just(88) | st.integers(0, 200),
|
line_length=st.just(88) | st.integers(0, 200),
|
||||||
string_normalization=st.booleans(),
|
string_normalization=st.booleans(),
|
||||||
|
preview=st.booleans(),
|
||||||
is_pyi=st.booleans(),
|
is_pyi=st.booleans(),
|
||||||
|
magic_trailing_comma=st.booleans(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_idempotent_any_syntatically_valid_python(
|
def test_idempotent_any_syntatically_valid_python(
|
||||||
@ -42,23 +42,7 @@ def test_idempotent_any_syntatically_valid_python(
|
|||||||
compile(src_contents, "<string>", "exec") # else the bug is in hypothesmith
|
compile(src_contents, "<string>", "exec") # else the bug is in hypothesmith
|
||||||
|
|
||||||
# Then format the code...
|
# Then format the code...
|
||||||
try:
|
dst_contents = black.format_str(src_contents, mode=mode)
|
||||||
dst_contents = black.format_str(src_contents, mode=mode)
|
|
||||||
except black.InvalidInput:
|
|
||||||
# This is a bug - if it's valid Python code, as above, Black should be
|
|
||||||
# able to cope with it. See issues #970, #1012, #1358, and #1557.
|
|
||||||
# TODO: remove this try-except block when issues are resolved.
|
|
||||||
return
|
|
||||||
except TokenError as e:
|
|
||||||
if ( # Special-case logic for backslashes followed by newlines or end-of-input
|
|
||||||
e.args[0] == "EOF in multi-line statement"
|
|
||||||
and re.search(r"\\($|\r?\n)", src_contents) is not None
|
|
||||||
):
|
|
||||||
# This is a bug - if it's valid Python code, as above, Black should be
|
|
||||||
# able to cope with it. See issue #1012.
|
|
||||||
# TODO: remove this block when the issue is resolved.
|
|
||||||
return
|
|
||||||
raise
|
|
||||||
|
|
||||||
# And check that we got equivalent and stable output.
|
# And check that we got equivalent and stable output.
|
||||||
black.assert_equivalent(src_contents, dst_contents)
|
black.assert_equivalent(src_contents, dst_contents)
|
||||||
@ -76,10 +60,14 @@ def test_idempotent_any_syntatically_valid_python(
|
|||||||
# (if you want only bounded fuzzing, just use `pytest fuzz.py`)
|
# (if you want only bounded fuzzing, just use `pytest fuzz.py`)
|
||||||
try:
|
try:
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import atheris
|
import atheris
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
test = test_idempotent_any_syntatically_valid_python
|
test = test_idempotent_any_syntatically_valid_python
|
||||||
atheris.Setup(sys.argv, test.hypothesis.fuzz_one_input)
|
atheris.Setup(
|
||||||
|
sys.argv,
|
||||||
|
test.hypothesis.fuzz_one_input, # type: ignore[attr-defined]
|
||||||
|
)
|
||||||
atheris.Fuzz()
|
atheris.Fuzz()
|
74
scripts/generate_schema.py
Executable file
74
scripts/generate_schema.py
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
import json
|
||||||
|
from typing import IO, Any
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
import black
|
||||||
|
|
||||||
|
|
||||||
|
def generate_schema_from_click(
|
||||||
|
cmd: click.Command,
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
result: dict[str, dict[str, Any]] = {}
|
||||||
|
for param in cmd.params:
|
||||||
|
if not isinstance(param, click.Option) or param.is_eager:
|
||||||
|
continue
|
||||||
|
|
||||||
|
assert param.name
|
||||||
|
name = param.name.replace("_", "-")
|
||||||
|
|
||||||
|
result[name] = {}
|
||||||
|
|
||||||
|
match param.type:
|
||||||
|
case click.types.IntParamType():
|
||||||
|
result[name]["type"] = "integer"
|
||||||
|
case click.types.StringParamType() | click.types.Path():
|
||||||
|
result[name]["type"] = "string"
|
||||||
|
case click.types.Choice(choices=choices):
|
||||||
|
result[name]["enum"] = choices
|
||||||
|
case click.types.BoolParamType():
|
||||||
|
result[name]["type"] = "boolean"
|
||||||
|
case _:
|
||||||
|
msg = f"{param.type!r} not a known type for {param}"
|
||||||
|
raise TypeError(msg)
|
||||||
|
|
||||||
|
if param.multiple:
|
||||||
|
result[name] = {"type": "array", "items": result[name]}
|
||||||
|
|
||||||
|
result[name]["description"] = param.help
|
||||||
|
|
||||||
|
if param.default is not None and not param.multiple:
|
||||||
|
result[name]["default"] = param.default
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@click.command(context_settings={"help_option_names": ["-h", "--help"]})
|
||||||
|
@click.option("--schemastore", is_flag=True, help="SchemaStore format")
|
||||||
|
@click.option("--outfile", type=click.File(mode="w"), help="Write to file")
|
||||||
|
def main(schemastore: bool, outfile: IO[str]) -> None:
|
||||||
|
properties = generate_schema_from_click(black.main)
|
||||||
|
del properties["line-ranges"]
|
||||||
|
|
||||||
|
schema: dict[str, Any] = {
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": (
|
||||||
|
"https://github.com/psf/black/blob/main/src/black/resources/black.schema.json"
|
||||||
|
),
|
||||||
|
"$comment": "tool.black table in pyproject.toml",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": properties,
|
||||||
|
}
|
||||||
|
|
||||||
|
if schemastore:
|
||||||
|
schema["$id"] = "https://json.schemastore.org/partial-black.json"
|
||||||
|
# The precise list of unstable features may change frequently, so don't
|
||||||
|
# bother putting it in SchemaStore
|
||||||
|
schema["properties"]["enable-unstable-feature"]["items"] = {"type": "string"}
|
||||||
|
|
||||||
|
print(json.dumps(schema, indent=2), file=outfile)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
66
scripts/make_width_table.py
Normal file
66
scripts/make_width_table.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
"""Generates a width table for Unicode characters.
|
||||||
|
|
||||||
|
This script generates a width table for Unicode characters that are not
|
||||||
|
narrow (width 1). The table is written to src/black/_width_table.py (note
|
||||||
|
that although this file is generated, it is checked into Git) and is used
|
||||||
|
by the char_width() function in src/black/strings.py.
|
||||||
|
|
||||||
|
You should run this script when you upgrade wcwidth, which is expected to
|
||||||
|
happen when a new Unicode version is released. The generated table contains
|
||||||
|
the version of wcwidth and Unicode that it was generated for.
|
||||||
|
|
||||||
|
In order to run this script, you need to install the latest version of wcwidth.
|
||||||
|
You can do this by running:
|
||||||
|
|
||||||
|
pip install -U wcwidth
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from collections.abc import Iterable
|
||||||
|
from os.path import basename, dirname, join
|
||||||
|
|
||||||
|
import wcwidth # type: ignore[import-not-found]
|
||||||
|
|
||||||
|
|
||||||
|
def make_width_table() -> Iterable[tuple[int, int, int]]:
|
||||||
|
start_codepoint = -1
|
||||||
|
end_codepoint = -1
|
||||||
|
range_width = -2
|
||||||
|
for codepoint in range(0, sys.maxunicode + 1):
|
||||||
|
width = wcwidth.wcwidth(chr(codepoint))
|
||||||
|
if width <= 1:
|
||||||
|
# Ignore narrow characters along with zero-width characters so that
|
||||||
|
# they are treated as single-width. Note that treating zero-width
|
||||||
|
# characters as single-width is consistent with the heuristics built
|
||||||
|
# on top of str.isascii() in the str_width() function in strings.py.
|
||||||
|
continue
|
||||||
|
if start_codepoint < 0:
|
||||||
|
start_codepoint = codepoint
|
||||||
|
range_width = width
|
||||||
|
elif width != range_width or codepoint != end_codepoint + 1:
|
||||||
|
yield (start_codepoint, end_codepoint, range_width)
|
||||||
|
start_codepoint = codepoint
|
||||||
|
range_width = width
|
||||||
|
end_codepoint = codepoint
|
||||||
|
if start_codepoint >= 0:
|
||||||
|
yield (start_codepoint, end_codepoint, range_width)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
table_path = join(dirname(__file__), "..", "src", "black", "_width_table.py")
|
||||||
|
with open(table_path, "w") as f:
|
||||||
|
f.write(f"""# Generated by {basename(__file__)}
|
||||||
|
# wcwidth {wcwidth.__version__}
|
||||||
|
# Unicode {wcwidth.list_versions()[-1]}
|
||||||
|
from typing import Final
|
||||||
|
|
||||||
|
WIDTH_TABLE: Final[list[tuple[int, int, int]]] = [
|
||||||
|
""")
|
||||||
|
for triple in make_width_table():
|
||||||
|
f.write(f" {triple!r},\n")
|
||||||
|
f.write("]\n")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user