Compare commits
898 Commits
bugfix/ext
...
disinherit
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a438076473 | ||
![]() |
d841542b9c | ||
![]() |
3bc943ae51 | ||
![]() |
548aa21b18 | ||
![]() |
c9775df0a4 | ||
![]() |
6f11efe576 | ||
![]() |
fef0f47d65 | ||
![]() |
20575ca96a | ||
![]() |
13121b4c28 | ||
![]() |
ef8214682c | ||
![]() |
aca7dd6c2b | ||
![]() |
c6d715c188 | ||
![]() |
b148a43f08 | ||
![]() |
74901a3d0d | ||
![]() |
10d5f14c85 | ||
![]() |
c0389ab3d0 | ||
![]() |
2fdd72094a | ||
![]() |
7659912dc4 | ||
![]() |
ff4cccbf6c | ||
![]() |
5074e72be8 | ||
![]() |
3d7674225f | ||
![]() |
873871bc62 | ||
![]() |
35d0dc8bb5 | ||
![]() |
331e3cd4e1 | ||
![]() |
100134a2b1 | ||
![]() |
39ffef8363 | ||
![]() |
f0672bbaf8 | ||
![]() |
4fa0c1d11c | ||
![]() |
9e845635ce | ||
![]() |
184a75ec54 | ||
![]() |
dbd425f0f8 | ||
![]() |
3161784e9a | ||
![]() |
a72a3fb2e0 | ||
![]() |
e253184886 | ||
![]() |
d276a5f8e4 | ||
![]() |
3ed219578b | ||
![]() |
0040236cc6 | ||
![]() |
0629c8e5fa | ||
![]() |
6f19eb5e67 | ||
![]() |
b7e416046f | ||
![]() |
b2cc36109f | ||
![]() |
1262dcfb9f | ||
![]() |
c3dc7a8349 | ||
![]() |
84d2c8a693 | ||
![]() |
37b1bc9c26 | ||
![]() |
3489cc0a9b | ||
![]() |
9a25e21da8 | ||
![]() |
d156e2ee91 | ||
![]() |
891a63cae6 | ||
![]() |
886ea7c490 | ||
![]() |
fcf9c639ee | ||
![]() |
4e63d92bc9 | ||
![]() |
17a67b9a56 | ||
![]() |
904eefc930 | ||
![]() |
add8022490 | ||
![]() |
645faad379 | ||
![]() |
d0866e4d02 | ||
![]() |
1095958cac | ||
![]() |
911e9edf07 | ||
![]() |
b9048dbee9 | ||
![]() |
55f71e41d5 | ||
![]() |
07ee8e99ca | ||
![]() |
307a8f8565 | ||
![]() |
1ca7da4831 | ||
![]() |
b9a16a599a | ||
![]() |
590adf57d2 | ||
![]() |
d45c228401 | ||
![]() |
d0cb5efa3b | ||
![]() |
5f4b736006 | ||
![]() |
c7d1746064 | ||
![]() |
a1889440d7 | ||
![]() |
f521c31657 | ||
![]() |
d4e714bb2e | ||
![]() |
ff38ff25cb | ||
![]() |
6e95417c98 | ||
![]() |
4727a9b976 | ||
![]() |
44c69cadf4 | ||
![]() |
1034b23320 | ||
![]() |
ef9049feac | ||
![]() |
f6006445da | ||
![]() |
2c87f59d36 | ||
![]() |
229ee7cad9 | ||
![]() |
85e2fb0c4d | ||
![]() |
88a604e7f4 | ||
![]() |
33859d3d5f | ||
![]() |
68ce49a57b | ||
![]() |
92b7f63365 | ||
![]() |
a1930e36e7 | ||
![]() |
897f812a70 | ||
![]() |
b7f41638fd | ||
![]() |
e804671fc0 | ||
![]() |
c0b458e38a | ||
![]() |
deef4177f7 | ||
![]() |
a1c840b3e8 | ||
![]() |
57e9e77475 | ||
![]() |
d260fa59c9 | ||
![]() |
0da69a45e3 | ||
![]() |
153b79c2ed | ||
![]() |
ffae0db115 | ||
![]() |
37c8ebcafd | ||
![]() |
03fc502da5 | ||
![]() |
b73884d541 | ||
![]() |
43f337d993 | ||
![]() |
a8188a9f14 | ||
![]() |
c19638bb0d | ||
![]() |
ccb9969b64 | ||
![]() |
fa93b5219c | ||
![]() |
42a0cf9b96 | ||
![]() |
4b67153613 | ||
![]() |
c65c944853 | ||
![]() |
ea6608edde | ||
![]() |
07499f2355 | ||
![]() |
781c4823e6 | ||
![]() |
71a609b2f4 | ||
![]() |
74595de359 | ||
![]() |
9d70f6e6c7 | ||
![]() |
7365d138fb | ||
![]() |
b94030cc5d | ||
![]() |
4414161787 | ||
![]() |
881a0d4462 | ||
![]() |
8d83af732a | ||
![]() |
a5a2918202 | ||
![]() |
8dc3a09104 | ||
![]() |
8f6f77ac9f | ||
![]() |
d0bd8f74cf | ||
![]() |
9d00e7d15d | ||
![]() |
cc333b600c | ||
![]() |
006969a8cd | ||
![]() |
d2618cd640 | ||
![]() |
807b87068a | ||
![]() |
6879c35d1c | ||
![]() |
f1b8bc97f0 | ||
![]() |
6fefb92413 | ||
![]() |
03a2feef88 | ||
![]() |
416615f30b | ||
![]() |
b62c4276c9 | ||
![]() |
b9861f7bbb | ||
![]() |
856fe5941a | ||
![]() |
0f7f600d1f | ||
![]() |
9283a94ee4 | ||
![]() |
726dee9e2d | ||
![]() |
b5a5af8c05 | ||
![]() |
289d6df911 | ||
![]() |
6158e4d8aa | ||
![]() |
8c3c8a4e4d | ||
![]() |
954e241174 | ||
![]() |
ae3a1618a2 | ||
![]() |
0d96b0b311 | ||
![]() |
f96f8a99e8 | ||
![]() |
94cff84df1 | ||
![]() |
582ee111f6 | ||
![]() |
c55de3f5e0 | ||
![]() |
0bdd4c10cf | ||
![]() |
521cc41db0 | ||
![]() |
c0eb2cf9e6 | ||
![]() |
9f0bb4301f | ||
![]() |
288e728144 | ||
![]() |
47011f594f | ||
![]() |
a00f692f20 | ||
![]() |
68bffd4689 | ||
![]() |
5acb20f145 | ||
![]() |
8a1b817978 | ||
![]() |
86e346e906 | ||
![]() |
a5ef522f98 | ||
![]() |
800ac7b53d | ||
![]() |
691e8c69c4 | ||
![]() |
ea970c8ab8 | ||
![]() |
c05827e794 | ||
![]() |
910b13000f | ||
![]() |
9474fdf910 | ||
![]() |
2cdac9392f | ||
![]() |
6775c10e82 | ||
![]() |
ea5d5517ce | ||
![]() |
8780c718ea | ||
![]() |
9687491568 | ||
![]() |
9c56b97aa9 | ||
![]() |
df10e711f7 | ||
![]() |
6fdb5dfa0a | ||
![]() |
ada174afbd | ||
![]() |
eace2ebb08 | ||
![]() |
441c0a4fee | ||
![]() |
0a7b0c68cf | ||
![]() |
6a44a146af | ||
![]() |
033cb86fd6 | ||
![]() |
5175189412 | ||
![]() |
86378502f9 | ||
![]() |
2530c7828b | ||
![]() |
ab2f842424 | ||
![]() |
b9f48da560 | ||
![]() |
e21c1c5770 | ||
![]() |
310b6b9466 | ||
![]() |
a869cfd95d | ||
![]() |
ddab6c4ac3 | ||
![]() |
25cff6be14 | ||
![]() |
5fe1281b14 | ||
![]() |
43cf60814d | ||
![]() |
582f165871 | ||
![]() |
bf76f1e774 | ||
![]() |
9cdb862856 | ||
![]() |
2e8d165120 | ||
![]() |
6984ee291a | ||
![]() |
10d506d61b | ||
![]() |
4549312c5e | ||
![]() |
80761bdc9d | ||
![]() |
4eb853856a | ||
![]() |
790929c832 | ||
![]() |
769378c959 | ||
![]() |
a18e2f98b3 | ||
![]() |
8f3bdf29dc | ||
![]() |
a28bb90b93 | ||
![]() |
5c9b591439 | ||
![]() |
778325db42 | ||
![]() |
f65bb62de4 | ||
![]() |
e4881d5465 | ||
![]() |
31cccdf52b | ||
![]() |
2c1523debe | ||
![]() |
c07881c843 | ||
![]() |
cb807594b8 | ||
![]() |
0227c0a98a | ||
![]() |
20a1cdd95e | ||
![]() |
2a779c1234 | ||
![]() |
3f6109404d | ||
![]() |
f83d47442d | ||
![]() |
08aafe180b | ||
![]() |
9cbbe64cf7 | ||
![]() |
2b006bb6ec | ||
![]() |
5509392151 | ||
![]() |
2001be99b3 | ||
![]() |
dd4409b62c | ||
![]() |
ca265ea0c2 | ||
![]() |
7a92579480 | ||
![]() |
190dfd0269 | ||
![]() |
b549548f69 | ||
![]() |
79268cedd2 | ||
![]() |
2004171b7e | ||
![]() |
06312ddf18 | ||
![]() |
3a0db729c7 | ||
![]() |
9759331f43 | ||
![]() |
ceca97518a | ||
![]() |
1929d5e3de | ||
![]() |
238e9c3613 | ||
![]() |
d43e7cb5cd | ||
![]() |
51a037d52a | ||
![]() |
c91f8c2f14 | ||
![]() |
04ad42e5ee | ||
![]() |
d02c71e443 | ||
![]() |
ca6e178890 | ||
![]() |
b145085fff | ||
![]() |
3a4b96e61c | ||
![]() |
36d87a4783 | ||
![]() |
6d2645f73b | ||
![]() |
44f7363fbe | ||
![]() |
9d936a2a75 | ||
![]() |
18438c395d | ||
![]() |
28a30bcea6 | ||
![]() |
536c7709c2 | ||
![]() |
e28738a01e | ||
![]() |
5f8c706128 | ||
![]() |
558695793f | ||
![]() |
b43a27674b | ||
![]() |
3d961b9a1f | ||
![]() |
d100ac8923 | ||
![]() |
e8fa8c5f01 | ||
![]() |
be6bb413df | ||
![]() |
d23c302ca2 | ||
![]() |
ed0c1cea91 | ||
![]() |
ffc42e287d | ||
![]() |
ba0d182e10 | ||
![]() |
8d8104de2c | ||
![]() |
7975e0afbc | ||
![]() |
4a43522763 | ||
![]() |
30343d65ba | ||
![]() |
38c1639c9c | ||
![]() |
be5033c869 | ||
![]() |
eb67497020 | ||
![]() |
371268a9aa | ||
![]() |
344e8d142a | ||
![]() |
161fbfadf4 | ||
![]() |
3304312b26 | ||
![]() |
3279ee7068 | ||
![]() |
8f3f838763 | ||
![]() |
09864d00c5 | ||
![]() |
0f7fa27327 | ||
![]() |
a27139c081 | ||
![]() |
4d4338db16 | ||
![]() |
6d64ffdd1a | ||
![]() |
e9ea9e2316 | ||
![]() |
2a5509ea90 | ||
![]() |
b9d027f0cc | ||
![]() |
6d54dc2a44 | ||
![]() |
6cd9cbf578 | ||
![]() |
72e81796d1 | ||
![]() |
f116e6762a | ||
![]() |
c74bbc6723 | ||
![]() |
492a603d5e | ||
![]() |
dab68687bd | ||
![]() |
1a32cea114 | ||
![]() |
aaec76652b | ||
![]() |
f748911ea0 | ||
![]() |
e60e74694f | ||
![]() |
2ef026b8c6 | ||
![]() |
a6c2569b18 | ||
![]() |
5483b5ff99 | ||
![]() |
2b78a7099d | ||
![]() |
34cdc6f52b | ||
![]() |
3aafdb06c9 | ||
![]() |
4a22c1c699 | ||
![]() |
f021479ef0 | ||
![]() |
3f374fb62f | ||
![]() |
949be42f32 | ||
![]() |
e5abd5abc1 | ||
![]() |
4473d5d811 | ||
![]() |
c3e61664cf | ||
![]() |
c3217775c3 | ||
![]() |
58a7e11db9 | ||
![]() |
ac570bb5c4 | ||
![]() |
b2c806f6fc | ||
![]() |
bd613b3124 | ||
![]() |
f1b85bc653 | ||
![]() |
e1fab4dd51 | ||
![]() |
a924079f66 | ||
![]() |
c5aff1d412 | ||
![]() |
6c9602ee64 | ||
![]() |
64327bfef0 | ||
![]() |
05c3cb7cc9 | ||
![]() |
c87b251639 | ||
![]() |
f2332a17d3 | ||
![]() |
c7f24a132e | ||
![]() |
96a7af1dd2 | ||
![]() |
db1caa9e92 | ||
![]() |
237d26460d | ||
![]() |
1020b65297 | ||
![]() |
dceb4c9d65 | ||
![]() |
50570ea334 | ||
![]() |
7e836b925d | ||
![]() |
cec3da61d2 | ||
![]() |
7ed53cf083 | ||
![]() |
bdc3ab5b54 | ||
![]() |
5a985e33ea | ||
![]() |
9817593c1c | ||
![]() |
1cc78dac38 | ||
![]() |
e2c5fe4aa3 | ||
![]() |
1bf87dbb5d | ||
![]() |
ffe527b141 | ||
![]() |
642c5b876b | ||
![]() |
8b7bd6dc74 | ||
![]() |
2f97dc7aa6 | ||
![]() |
958d542f81 | ||
![]() |
b1aae1c2ed | ||
![]() |
690f9d69fe | ||
![]() |
a78c16a609 | ||
![]() |
7bb2d3cca3 | ||
![]() |
7216050dd3 | ||
![]() |
2f26e422d6 | ||
![]() |
3477d578a3 | ||
![]() |
aa8e1ba606 | ||
![]() |
08e007e9a6 | ||
![]() |
d6fb65ebc6 | ||
![]() |
2b5be919dd | ||
![]() |
cc2dff48a8 | ||
![]() |
22922bf74c | ||
![]() |
8a02463d7d | ||
![]() |
c6465bd9bd | ||
![]() |
9025caed6e | ||
![]() |
7056a4bffd | ||
![]() |
d2aa8466eb | ||
![]() |
6e4684fbca | ||
![]() |
fcbf617d38 | ||
![]() |
1f8b55a021 | ||
![]() |
b5f8ed07fb | ||
![]() |
65bd9b9ac5 | ||
![]() |
6250d84b41 | ||
![]() |
99056e03bd | ||
![]() |
1db849ee5f | ||
![]() |
2f82b213df | ||
![]() |
2a5f0158bc | ||
![]() |
21a1f7dd97 | ||
![]() |
4b5ed94af4 | ||
![]() |
06788019a4 | ||
![]() |
cab8f795a7 | ||
![]() |
2db38bfa38 | ||
![]() |
ea029442e6 | ||
![]() |
43e38d0d12 | ||
![]() |
2522c8b754 | ||
![]() |
f64cb29aea | ||
![]() |
80e30222e1 | ||
![]() |
55356e9edb | ||
![]() |
eec09f791d | ||
![]() |
9032179b34 | ||
![]() |
45b40115fb | ||
![]() |
e030833129 | ||
![]() |
e055dc0e64 | ||
![]() |
c45729cba1 | ||
![]() |
b02b2f0f00 | ||
![]() |
3ded50cc8c | ||
![]() |
a7280cd5bb | ||
![]() |
2837b47ea5 | ||
![]() |
ea2c61c683 | ||
![]() |
217b34825a | ||
![]() |
17d90f4cbc | ||
![]() |
7a5bd8cac4 | ||
![]() |
333da47dc7 | ||
![]() |
8b68b4ae72 | ||
![]() |
40a3fdefa8 | ||
![]() |
a61474f2c1 | ||
![]() |
b95a75779b | ||
![]() |
0ff6a1bd1c | ||
![]() |
f9cfc2f57e | ||
![]() |
f4fb20e27e | ||
![]() |
3ff5d49102 | ||
![]() |
238d4f72f5 | ||
![]() |
c5bc469eeb | ||
![]() |
b01e7dca9d | ||
![]() |
c62906f781 | ||
![]() |
94bac8d6dd | ||
![]() |
cd9c9b47e8 | ||
![]() |
8560295529 | ||
![]() |
fd248ad0b8 | ||
![]() |
0578ccc0e6 | ||
![]() |
fcc2ab8b4b | ||
![]() |
76511ac039 | ||
![]() |
e4547982b3 | ||
![]() |
80722fbaa3 | ||
![]() |
c2fa444344 | ||
![]() |
088ece1219 | ||
![]() |
fcdd275564 | ||
![]() |
b6d6a1ab2c | ||
![]() |
7efcb5ae73 | ||
![]() |
06e6389258 | ||
![]() |
b7f0f7879d | ||
![]() |
f7cfbe2702 | ||
![]() |
1466f8d602 | ||
![]() |
9fdb36585f | ||
![]() |
1f0a9fdc11 | ||
![]() |
0baba62900 | ||
![]() |
4a0e34eda8 | ||
![]() |
88f2f59d92 | ||
![]() |
c1d11975f5 | ||
![]() |
cca56291c6 | ||
![]() |
ef155c16f0 | ||
![]() |
0952d314bd | ||
![]() |
f29ac34558 | ||
![]() |
47628521b9 | ||
![]() |
62da76cb5d | ||
![]() |
65c914fff7 | ||
![]() |
dd7b2deb47 | ||
![]() |
7d72aeb4fe | ||
![]() |
43d97afd8b | ||
![]() |
39f13853ba | ||
![]() |
d65b9c559a | ||
![]() |
bde5720a81 | ||
![]() |
2371ec7497 | ||
![]() |
aa3b6e598f | ||
![]() |
8035eeb36d | ||
![]() |
57383a2294 | ||
![]() |
9517dab409 | ||
![]() |
84fa4e6c4c | ||
![]() |
f33507961d | ||
![]() |
46010ef1e1 | ||
![]() |
f9d9d43b63 | ||
![]() |
db8f115013 | ||
![]() |
09b5476049 | ||
![]() |
14c4896ec2 | ||
![]() |
b5ef5c2eb5 | ||
![]() |
675afd884d | ||
![]() |
0f5482dc9a | ||
![]() |
069e5f874c | ||
![]() |
cad01a03cb | ||
![]() |
f10f8ed013 | ||
![]() |
d991ec90e3 | ||
![]() |
8353d1539f | ||
![]() |
bf3d18bf06 | ||
![]() |
0e69710f41 | ||
![]() |
ec62150ed7 | ||
![]() |
d37dc37504 | ||
![]() |
38d37897d4 | ||
![]() |
606eef43bd | ||
![]() |
02a30f8d95 | ||
![]() |
7e054cb7fc | ||
![]() |
d29cb87ecc | ||
![]() |
f8c0d9728d | ||
![]() |
f5bff16745 | ||
![]() |
2d1cb6d64a | ||
![]() |
c6e35da2c7 | ||
![]() |
f1cd327186 | ||
![]() |
391ad8cec4 | ||
![]() |
2c668f4bfd | ||
![]() |
52fdae83f0 | ||
![]() |
0ea81affd1 | ||
![]() |
ddc6e233c7 | ||
![]() |
7ee4499f2b | ||
![]() |
641adae961 | ||
![]() |
aed77efb9a | ||
![]() |
ab6499ce1e | ||
![]() |
412bec45aa | ||
![]() |
c3dcd94ebc | ||
![]() |
cb8f642297 | ||
![]() |
92f19c8491 | ||
![]() |
f3f8b31be5 | ||
![]() |
63cadf04ea | ||
![]() |
541e75350f | ||
![]() |
8806e74419 | ||
![]() |
381f8161b1 | ||
![]() |
884123b7ce | ||
![]() |
35aa875762 | ||
![]() |
9b0e79fcab | ||
![]() |
8ba0faa9ee | ||
![]() |
d464185bba | ||
![]() |
7f4d71252b | ||
![]() |
7950311767 | ||
![]() |
194f9a9ca9 | ||
![]() |
a72021fd63 | ||
![]() |
d910b3725b | ||
![]() |
99f209019e | ||
![]() |
c11a4e0ad3 | ||
![]() |
4a429ec315 | ||
![]() |
eadccfe332 | ||
![]() |
dfab5b5ceb | ||
![]() |
862029215c | ||
![]() |
559c3de213 | ||
![]() |
e3bf7358d7 | ||
![]() |
b58ec9e2b9 | ||
![]() |
95b5d54129 | ||
![]() |
bcce9c3e9c | ||
![]() |
4c05fe569c | ||
![]() |
e550665df7 | ||
![]() |
d92d34b162 | ||
![]() |
f27be808a4 | ||
![]() |
855d3519b6 | ||
![]() |
37f232e319 | ||
![]() |
ac1c29eac0 | ||
![]() |
56072172f5 | ||
![]() |
64d957dece | ||
![]() |
3edc85ec21 | ||
![]() |
d8006a9495 | ||
![]() |
a2cfc07412 | ||
![]() |
1295ea5d40 | ||
![]() |
4664b3cd1e | ||
![]() |
dc7e0e3ef6 | ||
![]() |
9aa615aa98 | ||
![]() |
85b6bf99a4 | ||
![]() |
78ec3d5662 | ||
![]() |
a7b5f2ef39 | ||
![]() |
f71701f39d | ||
![]() |
54008a2342 | ||
![]() |
1670c325c6 | ||
![]() |
534a994b4c | ||
![]() |
359efca201 | ||
![]() |
65809140f3 | ||
![]() |
3f1622f9e7 | ||
![]() |
8332a59194 | ||
![]() |
05abea3a3a | ||
![]() |
e7fc9ea243 | ||
![]() |
eea3ea7675 | ||
![]() |
895ac2626d | ||
![]() |
94dc86e163 | ||
![]() |
729b1c9fa6 | ||
![]() |
82b7fe649f | ||
![]() |
76417d6ac6 | ||
![]() |
fe995542ab | ||
![]() |
8f5209063d | ||
![]() |
241a8f6be6 | ||
![]() |
a8a0a6916a | ||
![]() |
8d10dce651 | ||
![]() |
a2938c9348 | ||
![]() |
8017f4b55b | ||
![]() |
588d2e295f | ||
![]() |
c10b84f08d | ||
![]() |
99044bedd7 | ||
![]() |
3afe6f1adc | ||
![]() |
fcd9038225 | ||
![]() |
9d82024f1a | ||
![]() |
bcefe6a73e | ||
![]() |
87562042df | ||
![]() |
10d10b612a | ||
![]() |
69dd742dc9 | ||
![]() |
18efd817b1 | ||
![]() |
65a5369d6a | ||
![]() |
f66ec00fa9 | ||
![]() |
f63fb2f521 | ||
![]() |
dfa00f5a8d | ||
![]() |
6602780657 | ||
![]() |
8420c610fa | ||
![]() |
b139cab687 | ||
![]() |
99fcc57607 | ||
![]() |
5a394d37b7 | ||
![]() |
472074cb7c | ||
![]() |
45c8d7f457 | ||
![]() |
dce1f01f1a | ||
![]() |
03cc83bc67 | ||
![]() |
f452741e3d | ||
![]() |
99b68e646d | ||
![]() |
f78c8265f4 | ||
![]() |
5d3efbba14 | ||
![]() |
7423f52cd3 | ||
![]() |
43d93f7773 | ||
![]() |
f8dec3e87f | ||
![]() |
ef06b9db5b | ||
![]() |
c64c9649be | ||
![]() |
2c6b52f137 | ||
![]() |
33422acef0 | ||
![]() |
428f635142 | ||
![]() |
c6c74e98ff | ||
![]() |
d9b438ec76 | ||
![]() |
c6ee30497c | ||
![]() |
1270ae1526 | ||
![]() |
d15fead30c | ||
![]() |
23aaaf2d28 | ||
![]() |
56f9c76394 | ||
![]() |
49cda811fc | ||
![]() |
a97312535a | ||
![]() |
a0180ef741 | ||
![]() |
d640a573a8 | ||
![]() |
b3679406d0 | ||
![]() |
587488882a | ||
![]() |
a17844a367 | ||
![]() |
093a37750c | ||
![]() |
173cc7e973 | ||
![]() |
451e3ff50b | ||
![]() |
523c4c2b63 | ||
![]() |
35e5a916bc | ||
![]() |
1374577659 | ||
![]() |
4c017403db | ||
![]() |
fdfda72371 | ||
![]() |
efa1dba9e4 | ||
![]() |
2a7ae2a700 | ||
![]() |
a1b4e1bccd | ||
![]() |
066ec31604 | ||
![]() |
bb1888dbd4 | ||
![]() |
bc17b6cefb | ||
![]() |
46a0cd8e55 | ||
![]() |
b2ceb23165 | ||
![]() |
2fad966139 | ||
![]() |
0b01c8c950 | ||
![]() |
613d0b7e8e | ||
![]() |
21c29ee375 | ||
![]() |
e236339e5a | ||
![]() |
7a03525c35 | ||
![]() |
17ca86a309 | ||
![]() |
ce71a38703 | ||
![]() |
12c23f2724 | ||
![]() |
b8ae0fbbf4 | ||
![]() |
6b5c86e0be | ||
![]() |
1ed1b49c9b | ||
![]() |
4265d5e111 | ||
![]() |
8c0fb91d4e | ||
![]() |
567532b9e5 | ||
![]() |
47d59e571e | ||
![]() |
93ff19c9b7 | ||
![]() |
2167cbf72c | ||
![]() |
7a5e527cab | ||
![]() |
a25868594c | ||
![]() |
dd5263694b | ||
![]() |
5fca1c9aff | ||
![]() |
1d7393c281 | ||
![]() |
f0bc551718 | ||
![]() |
46b9a09843 | ||
![]() |
c0898565b9 | ||
![]() |
3018e7f63d | ||
![]() |
dfa1a42420 | ||
![]() |
2c8ab85e6a | ||
![]() |
b2505aed5c | ||
![]() |
7847d4332e | ||
![]() |
70bcbba5eb | ||
![]() |
0182603609 | ||
![]() |
bf1b846f26 | ||
![]() |
d06fd26c9a | ||
![]() |
5d2c9636ff | ||
![]() |
63e4406514 | ||
![]() |
d56380fc07 | ||
![]() |
f89cc96b0c | ||
![]() |
cf952d41d8 | ||
![]() |
5f737c5a71 | ||
![]() |
a845b1f984 | ||
![]() |
b8d059e8f4 | ||
![]() |
1006c77374 | ||
![]() |
38d4fd7711 | ||
![]() |
643ce586de | ||
![]() |
5b3b0130f2 | ||
![]() |
55c77d659e | ||
![]() |
fe1c105161 | ||
![]() |
09f2b6f5f5 | ||
![]() |
73fe21ba41 | ||
![]() |
81fb87cedf | ||
![]() |
7de39c44b1 | ||
![]() |
c902e27e52 | ||
![]() |
65b991a4c5 | ||
![]() |
65520311a6 | ||
![]() |
def79731d0 | ||
![]() |
0fd3c9f451 | ||
![]() |
c5883fffd7 | ||
![]() |
4bf964e6b3 | ||
![]() |
bcc0fda4e2 | ||
![]() |
69987fd323 | ||
![]() |
9a16234ed4 | ||
![]() |
bd198312c9 | ||
![]() |
7f9af8d4a0 | ||
![]() |
793a7bc6a9 | ||
![]() |
376afd631c | ||
![]() |
e287c6ac4b | ||
![]() |
e864744b60 | ||
![]() |
5b3af53b10 | ||
![]() |
44c22a54c9 | ||
![]() |
f97f37550a | ||
![]() |
0e4ee3d352 | ||
![]() |
05fc800db9 | ||
![]() |
2387c116ad | ||
![]() |
6411cbd803 | ||
![]() |
8ea366b33f | ||
![]() |
9a2fbf373c | ||
![]() |
9e1fef8813 | ||
![]() |
f8a6e3ad90 | ||
![]() |
0706919b09 | ||
![]() |
b9b93ce272 | ||
![]() |
87cb9760ce | ||
![]() |
d472e28bfe | ||
![]() |
dbc81549db | ||
![]() |
dc00c4fdae | ||
![]() |
f1b9da16c8 | ||
![]() |
93ce943301 | ||
![]() |
632b36ab5d | ||
![]() |
94c76c5823 | ||
![]() |
45b4cedb7e | ||
![]() |
6d0a8f78b2 | ||
![]() |
409cf185ce | ||
![]() |
602984460d | ||
![]() |
62b1d52a1e | ||
![]() |
790bd175e0 | ||
![]() |
2f057d729d | ||
![]() |
a124185090 | ||
![]() |
c5235bbe86 | ||
![]() |
e715901cb2 | ||
![]() |
1db914f567 | ||
![]() |
688dae7058 | ||
![]() |
ddb460ec8d | ||
![]() |
703e5fe44a | ||
![]() |
c601bdf7bf | ||
![]() |
778dddc523 | ||
![]() |
acc19ad34f | ||
![]() |
f4826e1b33 | ||
![]() |
05ff7e657c | ||
![]() |
839a14c0ba | ||
![]() |
9aafbec121 | ||
![]() |
20071e0c04 | ||
![]() |
51bb2f23a3 | ||
![]() |
2060d51bd0 | ||
![]() |
e5af0ccc09 | ||
![]() |
284859e742 | ||
![]() |
37e77f7a15 | ||
![]() |
d2432e1ba4 | ||
![]() |
5809ba0e3f | ||
![]() |
95e294b2e8 | ||
![]() |
cdaac58488 | ||
![]() |
13389f7eb8 | ||
![]() |
4964633614 | ||
![]() |
381bedf369 | ||
![]() |
6811651a0f | ||
![]() |
22aada0e20 | ||
![]() |
4a71020cd2 | ||
![]() |
294e6f80a0 | ||
![]() |
cc2d0eade6 | ||
![]() |
f00e411287 | ||
![]() |
da0a6280ac | ||
![]() |
6ee6844473 | ||
![]() |
69822b0d82 | ||
![]() |
93eecae0c3 | ||
![]() |
61f5d85525 | ||
![]() |
a90e86de75 | ||
![]() |
7247a493ab | ||
![]() |
cd8ec60ae9 | ||
![]() |
fe597dfb0c | ||
![]() |
c721aab006 | ||
![]() |
6a08e9ed08 | ||
![]() |
7637efb363 | ||
![]() |
b31f1b0353 | ||
![]() |
497682260f | ||
![]() |
e47beceb8a | ||
![]() |
067976f4b8 | ||
![]() |
1263b5c444 | ||
![]() |
90f0a8eacc | ||
![]() |
61a7420c94 | ||
![]() |
39a1f1462b | ||
![]() |
6de5d8e68c | ||
![]() |
b0f2523350 | ||
![]() |
bc8cc39871 | ||
![]() |
b36a8f4f2e | ||
![]() |
0a952f8b7b | ||
![]() |
26a0384171 | ||
![]() |
d18cccf7c5 | ||
![]() |
fbe6b4b486 | ||
![]() |
5fe08a5647 | ||
![]() |
ac2fc4f271 | ||
![]() |
93430496e2 | ||
![]() |
901b31a7aa | ||
![]() |
0cec2d3110 | ||
![]() |
40e4884e8b | ||
![]() |
f18425a51f | ||
![]() |
472893c5c4 | ||
![]() |
289bbf74f6 | ||
![]() |
a0182c069f | ||
![]() |
4ecb6ecaff | ||
![]() |
d5193f73d8 | ||
![]() |
1aab5bb9f2 | ||
![]() |
8dda4ff60b | ||
![]() |
0811f81a09 | ||
![]() |
af74680405 | ||
![]() |
d1715c5fdf | ||
![]() |
b245f1ece1 | ||
![]() |
e10c47c53d | ||
![]() |
0697d20fd4 | ||
![]() |
fd4f905ce5 | ||
![]() |
d36c7b20d2 | ||
![]() |
2948248d7a | ||
![]() |
850c54c3b1 | ||
![]() |
90fb16033e | ||
![]() |
13a68d547d | ||
![]() |
857ae5a74b | ||
![]() |
b3124bff7c | ||
![]() |
5c4137baf1 | ||
![]() |
a9dcd4c01e | ||
![]() |
2cd7322b11 | ||
![]() |
f9e9ecd0c1 | ||
![]() |
d756034161 | ||
![]() |
2460c4fc28 | ||
![]() |
6e39efbb9a | ||
![]() |
277e35c3b0 | ||
![]() |
bf1b2a828c | ||
![]() |
2913f8b42b | ||
![]() |
57f4c922e9 | ||
![]() |
8d82fecce9 | ||
![]() |
96126cbf17 | ||
![]() |
6ecb57e91f | ||
![]() |
a75af62fe3 | ||
![]() |
e4e02dbeae | ||
![]() |
3efa4ee26f | ||
![]() |
f4c3d98064 | ||
![]() |
a4cec82841 | ||
![]() |
3812edd0db | ||
![]() |
3ea9c8529a | ||
![]() |
ed28797f83 | ||
![]() |
eadb6ae774 | ||
![]() |
a5d35c3077 | ||
![]() |
3d811617e6 | ||
![]() |
03224e52d2 | ||
![]() |
4ebe57cd64 | ||
![]() |
343cd04a54 | ||
![]() |
ed45385b7b | ||
![]() |
8a3b596042 | ||
![]() |
1792327874 | ||
![]() |
d0dedda9a9 | ||
![]() |
368dde437a | ||
![]() |
022a2d2eaf | ||
![]() |
5f8511311c | ||
![]() |
2d2c591633 | ||
![]() |
d49c992b23 | ||
![]() |
f1392bbd49 | ||
![]() |
c14dc2f56a | ||
![]() |
0f54a63dfd | ||
![]() |
f11778bb02 | ||
![]() |
3437926cde | ||
![]() |
d25375da55 | ||
![]() |
0b302034df | ||
![]() |
b9f69a8dfa | ||
![]() |
c3e9aeeed0 | ||
![]() |
277234c044 | ||
![]() |
0077a25639 | ||
![]() |
6a3e20023e | ||
![]() |
f92987b11f | ||
![]() |
61f198e8af | ||
![]() |
4d90d663a3 | ||
![]() |
7a7e9eb04f | ||
![]() |
3ea4b53bf6 | ||
![]() |
ad0d908d8d | ||
![]() |
9a793fe01b | ||
![]() |
6dd3c78924 | ||
![]() |
5b080d63fb | ||
![]() |
ea8e3c27a4 | ||
![]() |
30ffd6d33e | ||
![]() |
c1aec72f60 | ||
![]() |
cfd0dc6d89 | ||
![]() |
60b3d32072 | ||
![]() |
5142ebdd57 | ||
![]() |
6b782e6d7e | ||
![]() |
168bced888 | ||
![]() |
489de38890 | ||
![]() |
2a20520cc8 | ||
![]() |
ae6213b193 | ||
![]() |
bb1cd430c0 | ||
![]() |
36877abd02 | ||
![]() |
62db008e42 | ||
![]() |
b10d75b1c6 | ||
![]() |
078767946c | ||
![]() |
9ca7165ef0 | ||
![]() |
d1d668a9d5 | ||
![]() |
284c3a3fd8 | ||
![]() |
ec89c47aee | ||
![]() |
49114ffff7 | ||
![]() |
05fd39477e |
4
.github/workflows/audit.yaml
vendored
4
.github/workflows/audit.yaml
vendored
@@ -19,8 +19,8 @@ jobs:
|
|||||||
package-audits:
|
package-audits:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # @v2
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # @v2
|
||||||
with:
|
with:
|
||||||
python-version: ${{inputs.python_version}}
|
python-version: ${{inputs.python_version}}
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
|
24
.github/workflows/bootstrap.yml
vendored
24
.github/workflows/bootstrap.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
make patch unzip which xz python3 python3-devel tree \
|
make patch unzip which xz python3 python3-devel tree \
|
||||||
cmake bison bison-devel libstdc++-static
|
cmake bison bison-devel libstdc++-static
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup non-root user
|
- name: Setup non-root user
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
make patch unzip xz-utils python3 python3-dev tree \
|
make patch unzip xz-utils python3 python3-dev tree \
|
||||||
cmake bison
|
cmake bison
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup non-root user
|
- name: Setup non-root user
|
||||||
@@ -99,7 +99,7 @@ jobs:
|
|||||||
bzip2 curl file g++ gcc gfortran git gnupg2 gzip \
|
bzip2 curl file g++ gcc gfortran git gnupg2 gzip \
|
||||||
make patch unzip xz-utils python3 python3-dev tree
|
make patch unzip xz-utils python3 python3-dev tree
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup non-root user
|
- name: Setup non-root user
|
||||||
@@ -133,7 +133,7 @@ jobs:
|
|||||||
make patch unzip which xz python3 python3-devel tree \
|
make patch unzip which xz python3 python3-devel tree \
|
||||||
cmake bison
|
cmake bison
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup repo
|
- name: Setup repo
|
||||||
@@ -158,7 +158,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
brew install cmake bison@2.7 tree
|
brew install cmake bison@2.7 tree
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
- name: Bootstrap clingo
|
- name: Bootstrap clingo
|
||||||
run: |
|
run: |
|
||||||
source share/spack/setup-env.sh
|
source share/spack/setup-env.sh
|
||||||
@@ -179,7 +179,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
brew install tree
|
brew install tree
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
- name: Bootstrap clingo
|
- name: Bootstrap clingo
|
||||||
run: |
|
run: |
|
||||||
set -ex
|
set -ex
|
||||||
@@ -204,7 +204,7 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup repo
|
- name: Setup repo
|
||||||
@@ -214,7 +214,7 @@ jobs:
|
|||||||
- name: Bootstrap clingo
|
- name: Bootstrap clingo
|
||||||
run: |
|
run: |
|
||||||
set -ex
|
set -ex
|
||||||
for ver in '2.7' '3.6' '3.7' '3.8' '3.9' '3.10' ; do
|
for ver in '3.6' '3.7' '3.8' '3.9' '3.10' ; do
|
||||||
not_found=1
|
not_found=1
|
||||||
ver_dir="$(find $RUNNER_TOOL_CACHE/Python -wholename "*/${ver}.*/*/bin" | grep . || true)"
|
ver_dir="$(find $RUNNER_TOOL_CACHE/Python -wholename "*/${ver}.*/*/bin" | grep . || true)"
|
||||||
echo "Testing $ver_dir"
|
echo "Testing $ver_dir"
|
||||||
@@ -247,7 +247,7 @@ jobs:
|
|||||||
bzip2 curl file g++ gcc patchelf gfortran git gzip \
|
bzip2 curl file g++ gcc patchelf gfortran git gzip \
|
||||||
make patch unzip xz-utils python3 python3-dev tree
|
make patch unzip xz-utils python3 python3-dev tree
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup non-root user
|
- name: Setup non-root user
|
||||||
@@ -283,7 +283,7 @@ jobs:
|
|||||||
make patch unzip xz-utils python3 python3-dev tree \
|
make patch unzip xz-utils python3 python3-dev tree \
|
||||||
gawk
|
gawk
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup non-root user
|
- name: Setup non-root user
|
||||||
@@ -316,7 +316,7 @@ jobs:
|
|||||||
# Remove GnuPG since we want to bootstrap it
|
# Remove GnuPG since we want to bootstrap it
|
||||||
sudo rm -rf /usr/local/bin/gpg
|
sudo rm -rf /usr/local/bin/gpg
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
- name: Bootstrap GnuPG
|
- name: Bootstrap GnuPG
|
||||||
run: |
|
run: |
|
||||||
source share/spack/setup-env.sh
|
source share/spack/setup-env.sh
|
||||||
@@ -333,7 +333,7 @@ jobs:
|
|||||||
# Remove GnuPG since we want to bootstrap it
|
# Remove GnuPG since we want to bootstrap it
|
||||||
sudo rm -rf /usr/local/bin/gpg
|
sudo rm -rf /usr/local/bin/gpg
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
- name: Bootstrap GnuPG
|
- name: Bootstrap GnuPG
|
||||||
run: |
|
run: |
|
||||||
source share/spack/setup-env.sh
|
source share/spack/setup-env.sh
|
||||||
|
6
.github/workflows/build-containers.yml
vendored
6
.github/workflows/build-containers.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
|||||||
if: github.repository == 'spack/spack'
|
if: github.repository == 'spack/spack'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
|
|
||||||
- name: Set Container Tag Normal (Nightly)
|
- name: Set Container Tag Normal (Nightly)
|
||||||
run: |
|
run: |
|
||||||
@@ -80,7 +80,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload Dockerfile
|
- name: Upload Dockerfile
|
||||||
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb
|
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce
|
||||||
with:
|
with:
|
||||||
name: dockerfiles
|
name: dockerfiles
|
||||||
path: dockerfiles
|
path: dockerfiles
|
||||||
@@ -106,7 +106,7 @@ jobs:
|
|||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build & Deploy ${{ matrix.dockerfile[0] }}
|
- name: Build & Deploy ${{ matrix.dockerfile[0] }}
|
||||||
uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 # @v2
|
uses: docker/build-push-action@37abcedcc1da61a57767b7588cb9d03eb57e28b3 # @v2
|
||||||
with:
|
with:
|
||||||
context: dockerfiles/${{ matrix.dockerfile[0] }}
|
context: dockerfiles/${{ matrix.dockerfile[0] }}
|
||||||
platforms: ${{ matrix.dockerfile[1] }}
|
platforms: ${{ matrix.dockerfile[1] }}
|
||||||
|
10
.github/workflows/ci.yaml
vendored
10
.github/workflows/ci.yaml
vendored
@@ -20,12 +20,6 @@ jobs:
|
|||||||
uses: ./.github/workflows/valid-style.yml
|
uses: ./.github/workflows/valid-style.yml
|
||||||
with:
|
with:
|
||||||
with_coverage: ${{ needs.changes.outputs.core }}
|
with_coverage: ${{ needs.changes.outputs.core }}
|
||||||
audit-ancient-python:
|
|
||||||
uses: ./.github/workflows/audit.yaml
|
|
||||||
needs: [ changes ]
|
|
||||||
with:
|
|
||||||
with_coverage: ${{ needs.changes.outputs.core }}
|
|
||||||
python_version: 2.7
|
|
||||||
all-prechecks:
|
all-prechecks:
|
||||||
needs: [ prechecks ]
|
needs: [ prechecks ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -41,7 +35,7 @@ jobs:
|
|||||||
core: ${{ steps.filter.outputs.core }}
|
core: ${{ steps.filter.outputs.core }}
|
||||||
packages: ${{ steps.filter.outputs.packages }}
|
packages: ${{ steps.filter.outputs.packages }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
if: ${{ github.event_name == 'push' }}
|
if: ${{ github.event_name == 'push' }}
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
@@ -85,7 +79,7 @@ jobs:
|
|||||||
needs: [ prechecks ]
|
needs: [ prechecks ]
|
||||||
uses: ./.github/workflows/windows_python.yml
|
uses: ./.github/workflows/windows_python.yml
|
||||||
all:
|
all:
|
||||||
needs: [ windows, unit-tests, bootstrap, audit-ancient-python ]
|
needs: [ windows, unit-tests, bootstrap ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Success
|
- name: Success
|
||||||
|
8
.github/workflows/setup_git.ps1
vendored
8
.github/workflows/setup_git.ps1
vendored
@@ -1,15 +1,9 @@
|
|||||||
# (c) 2021 Lawrence Livermore National Laboratory
|
# (c) 2022 Lawrence Livermore National Laboratory
|
||||||
|
|
||||||
Set-Location spack
|
|
||||||
|
|
||||||
git config --global user.email "spack@example.com"
|
git config --global user.email "spack@example.com"
|
||||||
git config --global user.name "Test User"
|
git config --global user.name "Test User"
|
||||||
git config --global core.longpaths true
|
git config --global core.longpaths true
|
||||||
|
|
||||||
# See https://github.com/git/git/security/advisories/GHSA-3wp6-j8xr-qw85 (CVE-2022-39253)
|
|
||||||
# This is needed to let some fixture in our unit-test suite run
|
|
||||||
git config --global protocol.file.allow always
|
|
||||||
|
|
||||||
if ($(git branch --show-current) -ne "develop")
|
if ($(git branch --show-current) -ne "develop")
|
||||||
{
|
{
|
||||||
git branch develop origin/develop
|
git branch develop origin/develop
|
||||||
|
4
.github/workflows/setup_git.sh
vendored
4
.github/workflows/setup_git.sh
vendored
@@ -2,10 +2,6 @@
|
|||||||
git config --global user.email "spack@example.com"
|
git config --global user.email "spack@example.com"
|
||||||
git config --global user.name "Test User"
|
git config --global user.name "Test User"
|
||||||
|
|
||||||
# See https://github.com/git/git/security/advisories/GHSA-3wp6-j8xr-qw85 (CVE-2022-39253)
|
|
||||||
# This is needed to let some fixture in our unit-test suite run
|
|
||||||
git config --global protocol.file.allow always
|
|
||||||
|
|
||||||
# create a local pr base branch
|
# create a local pr base branch
|
||||||
if [[ -n $GITHUB_BASE_REF ]]; then
|
if [[ -n $GITHUB_BASE_REF ]]; then
|
||||||
git fetch origin "${GITHUB_BASE_REF}:${GITHUB_BASE_REF}"
|
git fetch origin "${GITHUB_BASE_REF}:${GITHUB_BASE_REF}"
|
||||||
|
64
.github/workflows/unit_tests.yaml
vendored
64
.github/workflows/unit_tests.yaml
vendored
@@ -11,39 +11,46 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
# Run unit tests with different configurations on linux
|
# Run unit tests with different configurations on linux
|
||||||
ubuntu:
|
ubuntu:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ['2.7', '3.6', '3.7', '3.8', '3.9', '3.10', '3.11']
|
os: [ubuntu-latest]
|
||||||
|
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
|
||||||
concretizer: ['clingo']
|
concretizer: ['clingo']
|
||||||
on_develop:
|
on_develop:
|
||||||
- ${{ github.ref == 'refs/heads/develop' }}
|
- ${{ github.ref == 'refs/heads/develop' }}
|
||||||
include:
|
include:
|
||||||
- python-version: 2.7
|
- python-version: '3.11'
|
||||||
|
os: ubuntu-latest
|
||||||
concretizer: original
|
concretizer: original
|
||||||
on_develop: ${{ github.ref == 'refs/heads/develop' }}
|
on_develop: ${{ github.ref == 'refs/heads/develop' }}
|
||||||
- python-version: '3.11'
|
- python-version: '3.6'
|
||||||
concretizer: original
|
os: ubuntu-20.04
|
||||||
|
concretizer: clingo
|
||||||
on_develop: ${{ github.ref == 'refs/heads/develop' }}
|
on_develop: ${{ github.ref == 'refs/heads/develop' }}
|
||||||
exclude:
|
exclude:
|
||||||
- python-version: '3.7'
|
- python-version: '3.7'
|
||||||
|
os: ubuntu-latest
|
||||||
concretizer: 'clingo'
|
concretizer: 'clingo'
|
||||||
on_develop: false
|
on_develop: false
|
||||||
- python-version: '3.8'
|
- python-version: '3.8'
|
||||||
|
os: ubuntu-latest
|
||||||
concretizer: 'clingo'
|
concretizer: 'clingo'
|
||||||
on_develop: false
|
on_develop: false
|
||||||
- python-version: '3.9'
|
- python-version: '3.9'
|
||||||
|
os: ubuntu-latest
|
||||||
concretizer: 'clingo'
|
concretizer: 'clingo'
|
||||||
on_develop: false
|
on_develop: false
|
||||||
- python-version: '3.10'
|
- python-version: '3.10'
|
||||||
|
os: ubuntu-latest
|
||||||
concretizer: 'clingo'
|
concretizer: 'clingo'
|
||||||
on_develop: false
|
on_develop: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # @v2
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # @v2
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
- name: Install System packages
|
- name: Install System packages
|
||||||
@@ -52,24 +59,11 @@ jobs:
|
|||||||
# Needed for unit tests
|
# Needed for unit tests
|
||||||
sudo apt-get -y install \
|
sudo apt-get -y install \
|
||||||
coreutils cvs gfortran graphviz gnupg2 mercurial ninja-build \
|
coreutils cvs gfortran graphviz gnupg2 mercurial ninja-build \
|
||||||
patchelf cmake bison libbison-dev kcov
|
cmake bison libbison-dev kcov
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
run: |
|
run: |
|
||||||
pip install --upgrade pip six setuptools pytest codecov[toml] pytest-xdist
|
pip install --upgrade pip six setuptools pytest codecov[toml] pytest-xdist pytest-cov
|
||||||
# Install pytest-cov only on recent Python, to avoid stalling on Python 2.7 due
|
pip install --upgrade flake8 "isort>=4.3.5" "mypy>=0.900" "click" "black"
|
||||||
# to bugs on an unmaintained version of the package when used with xdist.
|
|
||||||
if [[ ${{ matrix.python-version }} != "2.7" ]]; then
|
|
||||||
pip install --upgrade pytest-cov
|
|
||||||
fi
|
|
||||||
# ensure style checks are not skipped in unit tests for python >= 3.6
|
|
||||||
# note that true/false (i.e., 1/0) are opposite in conditions in python and bash
|
|
||||||
if python -c 'import sys; sys.exit(not sys.version_info >= (3, 6))'; then
|
|
||||||
pip install --upgrade flake8 "isort>=4.3.5" "mypy>=0.900" "click==8.0.4" "black<=21.12b0"
|
|
||||||
fi
|
|
||||||
- name: Pin pathlib for Python 2.7
|
|
||||||
if: ${{ matrix.python-version == 2.7 }}
|
|
||||||
run: |
|
|
||||||
pip install -U pathlib2==2.3.6 toml
|
|
||||||
- name: Setup git configuration
|
- name: Setup git configuration
|
||||||
run: |
|
run: |
|
||||||
# Need this for the git tests to succeed.
|
# Need this for the git tests to succeed.
|
||||||
@@ -82,6 +76,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
. share/spack/setup-env.sh
|
. share/spack/setup-env.sh
|
||||||
spack bootstrap disable spack-install
|
spack bootstrap disable spack-install
|
||||||
|
spack bootstrap now
|
||||||
spack -v solve zlib
|
spack -v solve zlib
|
||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
env:
|
env:
|
||||||
@@ -89,7 +84,7 @@ jobs:
|
|||||||
SPACK_TEST_SOLVER: ${{ matrix.concretizer }}
|
SPACK_TEST_SOLVER: ${{ matrix.concretizer }}
|
||||||
SPACK_TEST_PARALLEL: 2
|
SPACK_TEST_PARALLEL: 2
|
||||||
COVERAGE: true
|
COVERAGE: true
|
||||||
UNIT_TEST_COVERAGE: ${{ (matrix.python-version == '3.11') }}
|
UNIT_TEST_COVERAGE: ${{ matrix.python-version == '3.11' }}
|
||||||
run: |
|
run: |
|
||||||
share/spack/qa/run-unit-tests
|
share/spack/qa/run-unit-tests
|
||||||
- uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
|
- uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
|
||||||
@@ -99,10 +94,10 @@ jobs:
|
|||||||
shell:
|
shell:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # @v2
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # @v2
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.11'
|
||||||
- name: Install System packages
|
- name: Install System packages
|
||||||
@@ -138,7 +133,7 @@ jobs:
|
|||||||
dnf install -y \
|
dnf install -y \
|
||||||
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
|
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
|
||||||
make patch tcl unzip which xz
|
make patch tcl unzip which xz
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
- name: Setup repo and non-root user
|
- name: Setup repo and non-root user
|
||||||
run: |
|
run: |
|
||||||
git --version
|
git --version
|
||||||
@@ -150,25 +145,22 @@ jobs:
|
|||||||
shell: runuser -u spack-test -- bash {0}
|
shell: runuser -u spack-test -- bash {0}
|
||||||
run: |
|
run: |
|
||||||
source share/spack/setup-env.sh
|
source share/spack/setup-env.sh
|
||||||
spack -d solve zlib
|
spack -d bootstrap now --dev
|
||||||
spack unit-test -k 'not cvs and not svn and not hg' -x --verbose
|
spack unit-test -k 'not cvs and not svn and not hg' -x --verbose
|
||||||
# Test for the clingo based solver (using clingo-cffi)
|
# Test for the clingo based solver (using clingo-cffi)
|
||||||
clingo-cffi:
|
clingo-cffi:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # @v2
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # @v2
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.11'
|
||||||
- name: Install System packages
|
- name: Install System packages
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
# Needed for unit tests
|
sudo apt-get -y install coreutils cvs gfortran graphviz gnupg2 mercurial ninja-build kcov
|
||||||
sudo apt-get -y install \
|
|
||||||
coreutils cvs gfortran graphviz gnupg2 mercurial ninja-build \
|
|
||||||
patchelf kcov
|
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
run: |
|
run: |
|
||||||
pip install --upgrade pip six setuptools pytest codecov coverage[toml] pytest-cov clingo pytest-xdist
|
pip install --upgrade pip six setuptools pytest codecov coverage[toml] pytest-cov clingo pytest-xdist
|
||||||
@@ -193,10 +185,10 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.10"]
|
python-version: ["3.10"]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # @v2
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # @v2
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
|
14
.github/workflows/valid-style.yml
vendored
14
.github/workflows/valid-style.yml
vendored
@@ -18,8 +18,8 @@ jobs:
|
|||||||
validate:
|
validate:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # @v2
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # @v2
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.11'
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
@@ -28,23 +28,23 @@ jobs:
|
|||||||
pip install --upgrade pip
|
pip install --upgrade pip
|
||||||
pip install --upgrade vermin
|
pip install --upgrade vermin
|
||||||
- name: vermin (Spack's Core)
|
- name: vermin (Spack's Core)
|
||||||
run: vermin --backport argparse --violations --backport typing -t=2.7- -t=3.6- -vvv lib/spack/spack/ lib/spack/llnl/ bin/
|
run: vermin --backport importlib --backport argparse --violations --backport typing -t=3.6- -vvv lib/spack/spack/ lib/spack/llnl/ bin/
|
||||||
- name: vermin (Repositories)
|
- name: vermin (Repositories)
|
||||||
run: vermin --backport argparse --violations --backport typing -t=2.7- -t=3.6- -vvv var/spack/repos
|
run: vermin --backport importlib --backport argparse --violations --backport typing -t=3.6- -vvv var/spack/repos
|
||||||
# Run style checks on the files that have been changed
|
# Run style checks on the files that have been changed
|
||||||
style:
|
style:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # @v2
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # @v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # @v2
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # @v2
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.11'
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
run: |
|
run: |
|
||||||
python3 -m pip install --upgrade pip six setuptools types-six click==8.0.2 'black==21.12b0' mypy isort clingo flake8
|
python3 -m pip install --upgrade pip six setuptools types-six black mypy isort clingo flake8
|
||||||
- name: Setup git configuration
|
- name: Setup git configuration
|
||||||
run: |
|
run: |
|
||||||
# Need this for the git tests to succeed.
|
# Need this for the git tests to succeed.
|
||||||
|
175
.github/workflows/windows_python.yml
vendored
175
.github/workflows/windows_python.yml
vendored
@@ -10,15 +10,15 @@ concurrency:
|
|||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell:
|
shell:
|
||||||
powershell Invoke-Expression -Command ".\share\spack\qa\windows_test_setup.ps1"; {0}
|
powershell Invoke-Expression -Command "./share/spack/qa/windows_test_setup.ps1"; {0}
|
||||||
jobs:
|
jobs:
|
||||||
unit-tests:
|
unit-tests:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435
|
||||||
with:
|
with:
|
||||||
python-version: 3.9
|
python-version: 3.9
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
@@ -26,13 +26,11 @@ jobs:
|
|||||||
python -m pip install --upgrade pip six pywin32 setuptools codecov pytest-cov clingo
|
python -m pip install --upgrade pip six pywin32 setuptools codecov pytest-cov clingo
|
||||||
- name: Create local develop
|
- name: Create local develop
|
||||||
run: |
|
run: |
|
||||||
.\spack\.github\workflows\setup_git.ps1
|
./.github/workflows/setup_git.ps1
|
||||||
- name: Unit Test
|
- name: Unit Test
|
||||||
run: |
|
run: |
|
||||||
echo F|xcopy .\spack\share\spack\qa\configuration\windows_config.yaml $env:USERPROFILE\.spack\windows\config.yaml
|
|
||||||
cd spack
|
|
||||||
dir
|
|
||||||
spack unit-test -x --verbose --cov --cov-config=pyproject.toml --ignore=lib/spack/spack/test/cmd
|
spack unit-test -x --verbose --cov --cov-config=pyproject.toml --ignore=lib/spack/spack/test/cmd
|
||||||
|
./share/spack/qa/validate_last_exit.ps1
|
||||||
coverage combine -a
|
coverage combine -a
|
||||||
coverage xml
|
coverage xml
|
||||||
- uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
|
- uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
|
||||||
@@ -41,10 +39,10 @@ jobs:
|
|||||||
unit-tests-cmd:
|
unit-tests-cmd:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435
|
||||||
with:
|
with:
|
||||||
python-version: 3.9
|
python-version: 3.9
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
@@ -52,12 +50,11 @@ jobs:
|
|||||||
python -m pip install --upgrade pip six pywin32 setuptools codecov coverage pytest-cov clingo
|
python -m pip install --upgrade pip six pywin32 setuptools codecov coverage pytest-cov clingo
|
||||||
- name: Create local develop
|
- name: Create local develop
|
||||||
run: |
|
run: |
|
||||||
.\spack\.github\workflows\setup_git.ps1
|
./.github/workflows/setup_git.ps1
|
||||||
- name: Command Unit Test
|
- name: Command Unit Test
|
||||||
run: |
|
run: |
|
||||||
echo F|xcopy .\spack\share\spack\qa\configuration\windows_config.yaml $env:USERPROFILE\.spack\windows\config.yaml
|
|
||||||
cd spack
|
|
||||||
spack unit-test -x --verbose --cov --cov-config=pyproject.toml lib/spack/spack/test/cmd
|
spack unit-test -x --verbose --cov --cov-config=pyproject.toml lib/spack/spack/test/cmd
|
||||||
|
./share/spack/qa/validate_last_exit.ps1
|
||||||
coverage combine -a
|
coverage combine -a
|
||||||
coverage xml
|
coverage xml
|
||||||
- uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
|
- uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
|
||||||
@@ -66,10 +63,10 @@ jobs:
|
|||||||
build-abseil:
|
build-abseil:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984
|
- uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435
|
||||||
with:
|
with:
|
||||||
python-version: 3.9
|
python-version: 3.9
|
||||||
- name: Install Python packages
|
- name: Install Python packages
|
||||||
@@ -78,81 +75,81 @@ jobs:
|
|||||||
- name: Build Test
|
- name: Build Test
|
||||||
run: |
|
run: |
|
||||||
spack compiler find
|
spack compiler find
|
||||||
echo F|xcopy .\spack\share\spack\qa\configuration\windows_config.yaml $env:USERPROFILE\.spack\windows\config.yaml
|
|
||||||
spack external find cmake
|
spack external find cmake
|
||||||
spack external find ninja
|
spack external find ninja
|
||||||
spack -d install abseil-cpp
|
spack -d install abseil-cpp
|
||||||
make-installer:
|
# TODO: johnwparent - reduce the size of the installer operations
|
||||||
runs-on: windows-latest
|
# make-installer:
|
||||||
steps:
|
# runs-on: windows-latest
|
||||||
- name: Disable Windows Symlinks
|
# steps:
|
||||||
run: |
|
# - name: Disable Windows Symlinks
|
||||||
git config --global core.symlinks false
|
# run: |
|
||||||
shell:
|
# git config --global core.symlinks false
|
||||||
powershell
|
# shell:
|
||||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
# powershell
|
||||||
with:
|
# - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||||
fetch-depth: 0
|
# with:
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984
|
# fetch-depth: 0
|
||||||
with:
|
# - uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435
|
||||||
python-version: 3.9
|
# with:
|
||||||
- name: Install Python packages
|
# python-version: 3.9
|
||||||
run: |
|
# - name: Install Python packages
|
||||||
python -m pip install --upgrade pip six pywin32 setuptools
|
# run: |
|
||||||
- name: Add Light and Candle to Path
|
# python -m pip install --upgrade pip six pywin32 setuptools
|
||||||
run: |
|
# - name: Add Light and Candle to Path
|
||||||
$env:WIX >> $GITHUB_PATH
|
# run: |
|
||||||
- name: Run Installer
|
# $env:WIX >> $GITHUB_PATH
|
||||||
run: |
|
# - name: Run Installer
|
||||||
.\spack\share\spack\qa\setup_spack.ps1
|
# run: |
|
||||||
spack make-installer -s spack -g SILENT pkg
|
# ./share/spack/qa/setup_spack_installer.ps1
|
||||||
echo "installer_root=$((pwd).Path)" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
# spack make-installer -s . -g SILENT pkg
|
||||||
env:
|
# echo "installer_root=$((pwd).Path)" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
ProgressPreference: SilentlyContinue
|
# env:
|
||||||
- uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb
|
# ProgressPreference: SilentlyContinue
|
||||||
with:
|
# - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb
|
||||||
name: Windows Spack Installer Bundle
|
# with:
|
||||||
path: ${{ env.installer_root }}\pkg\Spack.exe
|
# name: Windows Spack Installer Bundle
|
||||||
- uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb
|
# path: ${{ env.installer_root }}\pkg\Spack.exe
|
||||||
with:
|
# - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb
|
||||||
name: Windows Spack Installer
|
# with:
|
||||||
path: ${{ env.installer_root}}\pkg\Spack.msi
|
# name: Windows Spack Installer
|
||||||
execute-installer:
|
# path: ${{ env.installer_root}}\pkg\Spack.msi
|
||||||
needs: make-installer
|
# execute-installer:
|
||||||
runs-on: windows-latest
|
# needs: make-installer
|
||||||
defaults:
|
# runs-on: windows-latest
|
||||||
run:
|
# defaults:
|
||||||
shell: pwsh
|
# run:
|
||||||
steps:
|
# shell: pwsh
|
||||||
- uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984
|
# steps:
|
||||||
with:
|
# - uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435
|
||||||
python-version: 3.9
|
# with:
|
||||||
- name: Install Python packages
|
# python-version: 3.9
|
||||||
run: |
|
# - name: Install Python packages
|
||||||
python -m pip install --upgrade pip six pywin32 setuptools
|
# run: |
|
||||||
- name: Setup installer directory
|
# python -m pip install --upgrade pip six pywin32 setuptools
|
||||||
run: |
|
# - name: Setup installer directory
|
||||||
mkdir -p spack_installer
|
# run: |
|
||||||
echo "spack_installer=$((pwd).Path)\spack_installer" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
# mkdir -p spack_installer
|
||||||
- uses: actions/download-artifact@v3
|
# echo "spack_installer=$((pwd).Path)\spack_installer" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
with:
|
# - uses: actions/download-artifact@v3
|
||||||
name: Windows Spack Installer Bundle
|
# with:
|
||||||
path: ${{ env.spack_installer }}
|
# name: Windows Spack Installer Bundle
|
||||||
- name: Execute Bundled Installer
|
# path: ${{ env.spack_installer }}
|
||||||
run: |
|
# - name: Execute Bundled Installer
|
||||||
$proc = Start-Process ${{ env.spack_installer }}\spack.exe "/install /quiet" -Passthru
|
# run: |
|
||||||
$handle = $proc.Handle # cache proc.Handle
|
# $proc = Start-Process ${{ env.spack_installer }}\spack.exe "/install /quiet" -Passthru
|
||||||
$proc.WaitForExit();
|
# $handle = $proc.Handle # cache proc.Handle
|
||||||
$LASTEXITCODE
|
# $proc.WaitForExit();
|
||||||
env:
|
# $LASTEXITCODE
|
||||||
ProgressPreference: SilentlyContinue
|
# env:
|
||||||
- uses: actions/download-artifact@v3
|
# ProgressPreference: SilentlyContinue
|
||||||
with:
|
# - uses: actions/download-artifact@v3
|
||||||
name: Windows Spack Installer
|
# with:
|
||||||
path: ${{ env.spack_installer }}
|
# name: Windows Spack Installer
|
||||||
- name: Execute MSI
|
# path: ${{ env.spack_installer }}
|
||||||
run: |
|
# - name: Execute MSI
|
||||||
$proc = Start-Process ${{ env.spack_installer }}\spack.msi "/quiet" -Passthru
|
# run: |
|
||||||
$handle = $proc.Handle # cache proc.Handle
|
# $proc = Start-Process ${{ env.spack_installer }}\spack.msi "/quiet" -Passthru
|
||||||
$proc.WaitForExit();
|
# $handle = $proc.Handle # cache proc.Handle
|
||||||
$LASTEXITCODE
|
# $proc.WaitForExit();
|
||||||
|
# $LASTEXITCODE
|
||||||
|
274
CHANGELOG.md
274
CHANGELOG.md
@@ -1,16 +1,284 @@
|
|||||||
|
# v0.19.0 (2022-11-11)
|
||||||
|
|
||||||
|
`v0.19.0` is a major feature release.
|
||||||
|
|
||||||
|
## Major features in this release
|
||||||
|
|
||||||
|
1. **Package requirements**
|
||||||
|
|
||||||
|
Spack's traditional [package preferences](
|
||||||
|
https://spack.readthedocs.io/en/latest/build_settings.html#package-preferences)
|
||||||
|
are soft, but we've added hard requriements to `packages.yaml` and `spack.yaml`
|
||||||
|
(#32528, #32369). Package requirements use the same syntax as specs:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
packages:
|
||||||
|
libfabric:
|
||||||
|
require: "@1.13.2"
|
||||||
|
mpich:
|
||||||
|
require:
|
||||||
|
- one_of: ["+cuda", "+rocm"]
|
||||||
|
```
|
||||||
|
|
||||||
|
More details in [the docs](
|
||||||
|
https://spack.readthedocs.io/en/latest/build_settings.html#package-requirements).
|
||||||
|
|
||||||
|
2. **Environment UI Improvements**
|
||||||
|
|
||||||
|
* Fewer surprising modifications to `spack.yaml` (#33711):
|
||||||
|
|
||||||
|
* `spack install` in an environment will no longer add to the `specs:` list; you'll
|
||||||
|
need to either use `spack add <spec>` or `spack install --add <spec>`.
|
||||||
|
|
||||||
|
* Similarly, `spack uninstall` will not remove from your environment's `specs:`
|
||||||
|
list; you'll need to use `spack remove` or `spack uninstall --remove`.
|
||||||
|
|
||||||
|
This will make it easier to manage an environment, as there is clear separation
|
||||||
|
between the stack to be installed (`spack.yaml`/`spack.lock`) and which parts of
|
||||||
|
it should be installed (`spack install` / `spack uninstall`).
|
||||||
|
|
||||||
|
* `concretizer:unify:true` is now the default mode for new environments (#31787)
|
||||||
|
|
||||||
|
We see more users creating `unify:true` environments now. Users who need
|
||||||
|
`unify:false` can add it to their environment to get the old behavior. This will
|
||||||
|
concretize every spec in the environment independently.
|
||||||
|
|
||||||
|
* Include environment configuration from URLs (#29026, [docs](
|
||||||
|
https://spack.readthedocs.io/en/latest/environments.html#included-configurations))
|
||||||
|
|
||||||
|
You can now include configuration in your environment directly from a URL:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
spack:
|
||||||
|
include:
|
||||||
|
- https://github.com/path/to/raw/config/compilers.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Multiple Build Systems**
|
||||||
|
|
||||||
|
An increasing number of packages in the ecosystem need the ability to support
|
||||||
|
multiple build systems (#30738, [docs](
|
||||||
|
https://spack.readthedocs.io/en/latest/packaging_guide.html#multiple-build-systems)),
|
||||||
|
either across versions, across platforms, or within the same version of the software.
|
||||||
|
This has been hard to support through multiple inheritance, as methods from different
|
||||||
|
build system superclasses would conflict. `package.py` files can now define separate
|
||||||
|
builder classes with installation logic for different build systems, e.g.:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ArpackNg(CMakePackage, AutotoolsPackage):
|
||||||
|
|
||||||
|
build_system(
|
||||||
|
conditional("cmake", when="@0.64:"),
|
||||||
|
conditional("autotools", when="@:0.63"),
|
||||||
|
default="cmake",
|
||||||
|
)
|
||||||
|
|
||||||
|
class CMakeBuilder(spack.build_systems.cmake.CMakeBuilder):
|
||||||
|
def cmake_args(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Autotoolsbuilder(spack.build_systems.autotools.AutotoolsBuilder):
|
||||||
|
def configure_args(self):
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Compiler and variant propagation**
|
||||||
|
|
||||||
|
Currently, compiler flags and variants are inconsistent: compiler flags set for a
|
||||||
|
package are inherited by its dependencies, while variants are not. We should have
|
||||||
|
these be consistent by allowing for inheritance to be enabled or disabled for both
|
||||||
|
variants and compiler flags.
|
||||||
|
|
||||||
|
Example syntax:
|
||||||
|
- `package ++variant`:
|
||||||
|
enabled variant that will be propagated to dependencies
|
||||||
|
- `package +variant`:
|
||||||
|
enabled variant that will NOT be propagated to dependencies
|
||||||
|
- `package ~~variant`:
|
||||||
|
disabled variant that will be propagated to dependencies
|
||||||
|
- `package ~variant`:
|
||||||
|
disabled variant that will NOT be propagated to dependencies
|
||||||
|
- `package cflags==-g`:
|
||||||
|
`cflags` will be propagated to dependencies
|
||||||
|
- `package cflags=-g`:
|
||||||
|
`cflags` will NOT be propagated to dependencies
|
||||||
|
|
||||||
|
Syntax for non-boolan variants is similar to compiler flags. More in the docs for
|
||||||
|
[variants](
|
||||||
|
https://spack.readthedocs.io/en/latest/basic_usage.html#variants) and [compiler flags](
|
||||||
|
https://spack.readthedocs.io/en/latest/basic_usage.html#compiler-flags).
|
||||||
|
|
||||||
|
6. **Enhancements to git version specifiers**
|
||||||
|
|
||||||
|
* `v0.18.0` added the ability to use git commits as versions. You can now use the
|
||||||
|
`git.` prefix to specify git tags or branches as versions. All of these are valid git
|
||||||
|
versions in `v0.19` (#31200):
|
||||||
|
|
||||||
|
```console
|
||||||
|
foo@abcdef1234abcdef1234abcdef1234abcdef1234 # raw commit
|
||||||
|
foo@git.abcdef1234abcdef1234abcdef1234abcdef1234 # commit with git prefix
|
||||||
|
foo@git.develop # the develop branch
|
||||||
|
foo@git.0.19 # use the 0.19 tag
|
||||||
|
```
|
||||||
|
|
||||||
|
* `v0.19` also gives you more control over how Spack interprets git versions, in case
|
||||||
|
Spack cannot detect the version from the git repository. You can suffix a git
|
||||||
|
version with `=<version>` to force Spack to concretize it as a particular version
|
||||||
|
(#30998, #31914, #32257):
|
||||||
|
|
||||||
|
```console
|
||||||
|
# use mybranch, but treat it as version 3.2 for version comparison
|
||||||
|
foo@git.mybranch=3.2
|
||||||
|
|
||||||
|
# use the given commit, but treat it as develop for version comparison
|
||||||
|
foo@git.abcdef1234abcdef1234abcdef1234abcdef1234=develop
|
||||||
|
```
|
||||||
|
|
||||||
|
More in [the docs](
|
||||||
|
https://spack.readthedocs.io/en/latest/basic_usage.html#version-specifier)
|
||||||
|
|
||||||
|
7. **Changes to Cray EX Support**
|
||||||
|
|
||||||
|
Cray machines have historically had their own "platform" within Spack, because we
|
||||||
|
needed to go through the module system to leverage compilers and MPI installations on
|
||||||
|
these machines. The Cray EX programming environment now provides standalone `craycc`
|
||||||
|
executables and proper `mpicc` wrappers, so Spack can treat EX machines like Linux
|
||||||
|
with extra packages (#29392).
|
||||||
|
|
||||||
|
We expect this to greatly reduce bugs, as external packages and compilers can now be
|
||||||
|
used by prefix instead of through modules. We will also no longer be subject to
|
||||||
|
reproducibility issues when modules change from Cray PE release to release and from
|
||||||
|
site to site. This also simplifies dealing with the underlying Linux OS on cray
|
||||||
|
systems, as Spack will properly model the machine's OS as either SuSE or RHEL.
|
||||||
|
|
||||||
|
8. **Improvements to tests and testing in CI**
|
||||||
|
|
||||||
|
* `spack ci generate --tests` will generate a `.gitlab-ci.yml` file that not only does
|
||||||
|
builds but also runs tests for built packages (#27877). Public GitHub pipelines now
|
||||||
|
also run tests in CI.
|
||||||
|
|
||||||
|
* `spack test run --explicit` will only run tests for packages that are explicitly
|
||||||
|
installed, instead of all packages.
|
||||||
|
|
||||||
|
9. **Experimental binding link model**
|
||||||
|
|
||||||
|
You can add a new option to `config.yaml` to make Spack embed absolute paths to
|
||||||
|
needed shared libraries in ELF executables and shared libraries on Linux (#31948, [docs](
|
||||||
|
https://spack.readthedocs.io/en/latest/config_yaml.html#shared-linking-bind)):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
config:
|
||||||
|
shared_linking:
|
||||||
|
type: rpath
|
||||||
|
bind: true
|
||||||
|
```
|
||||||
|
|
||||||
|
This can improve launch time at scale for parallel applications, and it can make
|
||||||
|
installations less susceptible to environment variables like `LD_LIBRARY_PATH`, even
|
||||||
|
especially when dealing with external libraries that use `RUNPATH`. You can think of
|
||||||
|
this as a faster, even higher-precedence version of `RPATH`.
|
||||||
|
|
||||||
|
## Other new features of note
|
||||||
|
|
||||||
|
* `spack spec` prints dependencies more legibly. Dependencies in the output now appear
|
||||||
|
at the *earliest* level of indentation possible (#33406)
|
||||||
|
* You can override `package.py` attributes like `url`, directly in `packages.yaml`
|
||||||
|
(#33275, [docs](
|
||||||
|
https://spack.readthedocs.io/en/latest/build_settings.html#assigning-package-attributes))
|
||||||
|
* There are a number of new architecture-related format strings you can use in Spack
|
||||||
|
configuration files to specify paths (#29810, [docs](
|
||||||
|
https://spack.readthedocs.io/en/latest/configuration.html#config-file-variables))
|
||||||
|
* Spack now supports bootstrapping Clingo on Windows (#33400)
|
||||||
|
* There is now support for an `RPATH`-like library model on Windows (#31930)
|
||||||
|
|
||||||
|
## Performance Improvements
|
||||||
|
|
||||||
|
* Major performance improvements for installation from binary caches (#27610, #33628,
|
||||||
|
#33636, #33608, #33590, #33496)
|
||||||
|
* Test suite can now be parallelized using `xdist` (used in GitHub Actions) (#32361)
|
||||||
|
* Reduce lock contention for parallel builds in environments (#31643)
|
||||||
|
|
||||||
|
## New binary caches and stacks
|
||||||
|
|
||||||
|
* We now build nearly all of E4S with `oneapi` in our buildcache (#31781, #31804,
|
||||||
|
#31804, #31803, #31840, #31991, #32117, #32107, #32239)
|
||||||
|
* Added 3 new machine learning-centric stacks to binary cache: `x86_64_v3`, CUDA, ROCm
|
||||||
|
(#31592, #33463)
|
||||||
|
|
||||||
|
## Removals and Deprecations
|
||||||
|
|
||||||
|
* Support for Python 3.5 is dropped (#31908). Only Python 2.7 and 3.6+ are officially
|
||||||
|
supported.
|
||||||
|
|
||||||
|
* This is the last Spack release that will support Python 2 (#32615). Spack `v0.19`
|
||||||
|
will emit a deprecation warning if you run it with Python 2, and Python 2 support will
|
||||||
|
soon be removed from the `develop` branch.
|
||||||
|
|
||||||
|
* `LD_LIBRARY_PATH` is no longer set by default by `spack load` or module loads.
|
||||||
|
|
||||||
|
Setting `LD_LIBRARY_PATH` in Spack environments/modules can cause binaries from
|
||||||
|
outside of Spack to crash, and Spack's own builds use `RPATH` and do not need
|
||||||
|
`LD_LIBRARY_PATH` set in order to run. If you still want the old behavior, you
|
||||||
|
can run these commands to configure Spack to set `LD_LIBRARY_PATH`:
|
||||||
|
|
||||||
|
```console
|
||||||
|
spack config add modules:prefix_inspections:lib64:[LD_LIBRARY_PATH]
|
||||||
|
spack config add modules:prefix_inspections:lib:[LD_LIBRARY_PATH]
|
||||||
|
```
|
||||||
|
|
||||||
|
* The `spack:concretization:[together|separately]` has been removed after being
|
||||||
|
deprecated in `v0.18`. Use `concretizer:unify:[true|false]`.
|
||||||
|
* `config:module_roots` is no longer supported after being deprecated in `v0.18`. Use
|
||||||
|
configuration in module sets instead (#28659, [docs](
|
||||||
|
https://spack.readthedocs.io/en/latest/module_file_support.html)).
|
||||||
|
* `spack activate` and `spack deactivate` are no longer supported, having been
|
||||||
|
deprecated in `v0.18`. Use an environment with a view instead of
|
||||||
|
activating/deactivating ([docs](
|
||||||
|
https://spack.readthedocs.io/en/latest/environments.html#configuration-in-spack-yaml)).
|
||||||
|
* The old YAML format for buildcaches is now deprecated (#33707). If you are using an
|
||||||
|
old buildcache with YAML metadata you will need to regenerate it with JSON metadata.
|
||||||
|
* `spack bootstrap trust` and `spack bootstrap untrust` are deprecated in favor of
|
||||||
|
`spack bootstrap enable` and `spack bootstrap disable` and will be removed in `v0.20`.
|
||||||
|
(#33600)
|
||||||
|
* The `graviton2` architecture has been renamed to `neoverse_n1`, and `graviton3`
|
||||||
|
is now `neoverse_v1`. Buildcaches using the old architecture names will need to be rebuilt.
|
||||||
|
* The terms `blacklist` and `whitelist` have been replaced with `include` and `exclude`
|
||||||
|
in all configuration files (#31569). You can use `spack config update` to
|
||||||
|
automatically fix your configuration files.
|
||||||
|
|
||||||
|
## Notable Bugfixes
|
||||||
|
|
||||||
|
* Permission setting on installation now handles effective uid properly (#19980)
|
||||||
|
* `buildable:true` for an MPI implementation now overrides `buildable:false` for `mpi` (#18269)
|
||||||
|
* Improved error messages when attempting to use an unconfigured compiler (#32084)
|
||||||
|
* Do not punish explicitly requested compiler mismatches in the solver (#30074)
|
||||||
|
* `spack stage`: add missing --fresh and --reuse (#31626)
|
||||||
|
* Fixes for adding build system executables like `cmake` to package scope (#31739)
|
||||||
|
* Bugfix for binary relocation with aliased strings produced by newer `binutils` (#32253)
|
||||||
|
|
||||||
|
## Spack community stats
|
||||||
|
|
||||||
|
* 6,751 total packages, 335 new since `v0.18.0`
|
||||||
|
* 141 new Python packages
|
||||||
|
* 89 new R packages
|
||||||
|
* 303 people contributed to this release
|
||||||
|
* 287 committers to packages
|
||||||
|
* 57 committers to core
|
||||||
|
|
||||||
|
|
||||||
# v0.18.1 (2022-07-19)
|
# v0.18.1 (2022-07-19)
|
||||||
|
|
||||||
### Spack Bugfixes
|
### Spack Bugfixes
|
||||||
* Fix several bugs related to bootstrapping (#30834,#31042,#31180)
|
* Fix several bugs related to bootstrapping (#30834,#31042,#31180)
|
||||||
* Fix a regression that was causing spec hashes to differ between
|
* Fix a regression that was causing spec hashes to differ between
|
||||||
Python 2 and Python 3 (#31092)
|
Python 2 and Python 3 (#31092)
|
||||||
* Fixed compiler flags for oneAPI and DPC++ (#30856)
|
* Fixed compiler flags for oneAPI and DPC++ (#30856)
|
||||||
* Fixed several issues related to concretization (#31142,#31153,#31170,#31226)
|
* Fixed several issues related to concretization (#31142,#31153,#31170,#31226)
|
||||||
* Improved support for Cray manifest file and `spack external find` (#31144,#31201,#31173,#31186)
|
* Improved support for Cray manifest file and `spack external find` (#31144,#31201,#31173,#31186)
|
||||||
* Assign a version to openSUSE Tumbleweed according to the GLIBC version
|
* Assign a version to openSUSE Tumbleweed according to the GLIBC version
|
||||||
in the system (#19895)
|
in the system (#19895)
|
||||||
* Improved Dockerfile generation for `spack containerize` (#29741,#31321)
|
* Improved Dockerfile generation for `spack containerize` (#29741,#31321)
|
||||||
* Fixed a few bugs related to concurrent execution of commands (#31509,#31493,#31477)
|
* Fixed a few bugs related to concurrent execution of commands (#31509,#31493,#31477)
|
||||||
|
|
||||||
### Package updates
|
### Package updates
|
||||||
* WarpX: add v22.06, fixed libs property (#30866,#31102)
|
* WarpX: add v22.06, fixed libs property (#30866,#31102)
|
||||||
|
@@ -10,8 +10,8 @@ For more on Spack's release structure, see
|
|||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
| develop | :white_check_mark: |
|
| develop | :white_check_mark: |
|
||||||
| 0.17.x | :white_check_mark: |
|
| 0.19.x | :white_check_mark: |
|
||||||
| 0.16.x | :white_check_mark: |
|
| 0.18.x | :white_check_mark: |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
@@ -10,6 +10,7 @@ def getpywin():
|
|||||||
try:
|
try:
|
||||||
import win32con # noqa: F401
|
import win32con # noqa: F401
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
print("pyWin32 not installed but is required...\nInstalling via pip:")
|
||||||
subprocess.check_call([sys.executable, "-m", "pip", "-q", "install", "--upgrade", "pip"])
|
subprocess.check_call([sys.executable, "-m", "pip", "-q", "install", "--upgrade", "pip"])
|
||||||
subprocess.check_call([sys.executable, "-m", "pip", "-q", "install", "pywin32"])
|
subprocess.check_call([sys.executable, "-m", "pip", "-q", "install", "pywin32"])
|
||||||
|
|
||||||
|
@@ -31,13 +31,11 @@ import os
|
|||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
min_python3 = (3, 5)
|
min_python3 = (3, 6)
|
||||||
|
|
||||||
if sys.version_info[:2] < (2, 7) or (
|
if sys.version_info[:2] < min_python3:
|
||||||
sys.version_info[:2] >= (3, 0) and sys.version_info[:2] < min_python3
|
|
||||||
):
|
|
||||||
v_info = sys.version_info[:3]
|
v_info = sys.version_info[:3]
|
||||||
msg = "Spack requires Python 2.7 or %d.%d or higher " % min_python3
|
msg = "Spack requires Python %d.%d or higher " % min_python3
|
||||||
msg += "You are running spack with Python %d.%d.%d." % v_info
|
msg += "You are running spack with Python %d.%d.%d." % v_info
|
||||||
sys.exit(msg)
|
sys.exit(msg)
|
||||||
|
|
||||||
|
@@ -52,7 +52,6 @@ if defined py_path (
|
|||||||
|
|
||||||
if defined py_exe (
|
if defined py_exe (
|
||||||
"%py_exe%" "%SPACK_ROOT%\bin\haspywin.py"
|
"%py_exe%" "%SPACK_ROOT%\bin\haspywin.py"
|
||||||
"%py_exe%" "%SPACK_ROOT%\bin\spack" external find python >NUL
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set "EDITOR=notepad"
|
set "EDITOR=notepad"
|
||||||
|
@@ -19,7 +19,7 @@ config:
|
|||||||
install_tree:
|
install_tree:
|
||||||
root: $spack/opt/spack
|
root: $spack/opt/spack
|
||||||
projections:
|
projections:
|
||||||
all: "${ARCHITECTURE}/${COMPILERNAME}-${COMPILERVER}/${PACKAGE}-${VERSION}-${HASH}"
|
all: "{architecture}/{compiler.name}-{compiler.version}/{name}-{version}-{hash}"
|
||||||
# install_tree can include an optional padded length (int or boolean)
|
# install_tree can include an optional padded length (int or boolean)
|
||||||
# default is False (do not pad)
|
# default is False (do not pad)
|
||||||
# if padded_length is True, Spack will pad as close to the system max path
|
# if padded_length is True, Spack will pad as close to the system max path
|
||||||
@@ -54,6 +54,11 @@ config:
|
|||||||
# are that it precludes its use as a system package and its ability to be
|
# are that it precludes its use as a system package and its ability to be
|
||||||
# pip installable.
|
# pip installable.
|
||||||
#
|
#
|
||||||
|
# In Spack environment files, chaining onto existing system Spack
|
||||||
|
# installations, the $env variable can be used to download, cache and build
|
||||||
|
# into user-writable paths that are relative to the currently active
|
||||||
|
# environment.
|
||||||
|
#
|
||||||
# In any case, if the username is not already in the path, Spack will append
|
# In any case, if the username is not already in the path, Spack will append
|
||||||
# the value of `$user` in an attempt to avoid potential conflicts between
|
# the value of `$user` in an attempt to avoid potential conflicts between
|
||||||
# users in shared temporary spaces.
|
# users in shared temporary spaces.
|
||||||
@@ -214,4 +219,8 @@ config:
|
|||||||
|
|
||||||
# Number of seconds a buildcache's index.json is cached locally before probing
|
# Number of seconds a buildcache's index.json is cached locally before probing
|
||||||
# for updates, within a single Spack invocation. Defaults to 10 minutes.
|
# for updates, within a single Spack invocation. Defaults to 10 minutes.
|
||||||
binary_index_ttl: 600
|
binary_index_ttl: 600
|
||||||
|
|
||||||
|
flags:
|
||||||
|
# Whether to keep -Werror flags active in package builds.
|
||||||
|
keep_werror: 'none'
|
||||||
|
21
etc/spack/defaults/windows/packages.yaml
Normal file
21
etc/spack/defaults/windows/packages.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# This file controls default concretization preferences for Spack.
|
||||||
|
#
|
||||||
|
# Settings here are versioned with Spack and are intended to provide
|
||||||
|
# sensible defaults out of the box. Spack maintainers should edit this
|
||||||
|
# file to keep it current.
|
||||||
|
#
|
||||||
|
# Users can override these settings by editing the following files.
|
||||||
|
#
|
||||||
|
# Per-spack-instance settings (overrides defaults):
|
||||||
|
# $SPACK_ROOT/etc/spack/packages.yaml
|
||||||
|
#
|
||||||
|
# Per-user settings (overrides default and site settings):
|
||||||
|
# ~/.spack/packages.yaml
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
packages:
|
||||||
|
all:
|
||||||
|
compiler:
|
||||||
|
- msvc
|
||||||
|
providers:
|
||||||
|
mpi: [msmpi]
|
@@ -1,162 +0,0 @@
|
|||||||
.. Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
|
|
||||||
Spack Project Developers. See the top-level COPYRIGHT file for details.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
||||||
|
|
||||||
.. _analyze:
|
|
||||||
|
|
||||||
=======
|
|
||||||
Analyze
|
|
||||||
=======
|
|
||||||
|
|
||||||
|
|
||||||
The analyze command is a front-end to various tools that let us analyze
|
|
||||||
package installations. Each analyzer is a module for a different kind
|
|
||||||
of analysis that can be done on a package installation, including (but not
|
|
||||||
limited to) binary, log, or text analysis. Thus, the analyze command group
|
|
||||||
allows you to take an existing package install, choose an analyzer,
|
|
||||||
and extract some output for the package using it.
|
|
||||||
|
|
||||||
|
|
||||||
-----------------
|
|
||||||
Analyzer Metadata
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
For all analyzers, we write to an ``analyzers`` folder in ``~/.spack``, or the
|
|
||||||
value that you specify in your spack config at ``config:analyzers_dir``.
|
|
||||||
For example, here we see the results of running an analysis on zlib:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ tree ~/.spack/analyzers/
|
|
||||||
└── linux-ubuntu20.04-skylake
|
|
||||||
└── gcc-9.3.0
|
|
||||||
└── zlib-1.2.11-sl7m27mzkbejtkrajigj3a3m37ygv4u2
|
|
||||||
├── environment_variables
|
|
||||||
│ └── spack-analyzer-environment-variables.json
|
|
||||||
├── install_files
|
|
||||||
│ └── spack-analyzer-install-files.json
|
|
||||||
└── libabigail
|
|
||||||
└── spack-analyzer-libabigail-libz.so.1.2.11.xml
|
|
||||||
|
|
||||||
|
|
||||||
This means that you can always find analyzer output in this folder, and it
|
|
||||||
is organized with the same logic as the package install it was run for.
|
|
||||||
If you want to customize this top level folder, simply provide the ``--path``
|
|
||||||
argument to ``spack analyze run``. The nested organization will be maintained
|
|
||||||
within your custom root.
|
|
||||||
|
|
||||||
-----------------
|
|
||||||
Listing Analyzers
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
If you aren't familiar with Spack's analyzers, you can quickly list those that
|
|
||||||
are available:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack analyze list-analyzers
|
|
||||||
install_files : install file listing read from install_manifest.json
|
|
||||||
environment_variables : environment variables parsed from spack-build-env.txt
|
|
||||||
config_args : config args loaded from spack-configure-args.txt
|
|
||||||
libabigail : Application Binary Interface (ABI) features for objects
|
|
||||||
|
|
||||||
|
|
||||||
In the above, the first three are fairly simple - parsing metadata files from
|
|
||||||
a package install directory to save
|
|
||||||
|
|
||||||
-------------------
|
|
||||||
Analyzing a Package
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
The analyze command, akin to install, will accept a package spec to perform
|
|
||||||
an analysis for. The package must be installed. Let's walk through an example
|
|
||||||
with zlib. We first ask to analyze it. However, since we have more than one
|
|
||||||
install, we are asked to disambiguate:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack analyze run zlib
|
|
||||||
==> Error: zlib matches multiple packages.
|
|
||||||
Matching packages:
|
|
||||||
fz2bs56 zlib@1.2.11%gcc@7.5.0 arch=linux-ubuntu18.04-skylake
|
|
||||||
sl7m27m zlib@1.2.11%gcc@9.3.0 arch=linux-ubuntu20.04-skylake
|
|
||||||
Use a more specific spec.
|
|
||||||
|
|
||||||
|
|
||||||
We can then specify the spec version that we want to analyze:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack analyze run zlib/fz2bs56
|
|
||||||
|
|
||||||
If you don't provide any specific analyzer names, by default all analyzers
|
|
||||||
(shown in the ``list-analyzers`` subcommand list) will be run. If an analyzer does not
|
|
||||||
have any result, it will be skipped. For example, here is a result running for
|
|
||||||
zlib:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ ls ~/.spack/analyzers/linux-ubuntu20.04-skylake/gcc-9.3.0/zlib-1.2.11-sl7m27mzkbejtkrajigj3a3m37ygv4u2/
|
|
||||||
spack-analyzer-environment-variables.json
|
|
||||||
spack-analyzer-install-files.json
|
|
||||||
spack-analyzer-libabigail-libz.so.1.2.11.xml
|
|
||||||
|
|
||||||
If you want to run a specific analyzer, ask for it with `--analyzer`. Here we run
|
|
||||||
spack analyze on libabigail (already installed) _using_ libabigail1
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack analyze run --analyzer abigail libabigail
|
|
||||||
|
|
||||||
|
|
||||||
.. _analyze_monitoring:
|
|
||||||
|
|
||||||
----------------------
|
|
||||||
Monitoring An Analysis
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
For any kind of analysis, you can
|
|
||||||
use a `spack monitor <https://github.com/spack/spack-monitor>`_ "Spackmon"
|
|
||||||
as a server to upload the same run metadata to. You can
|
|
||||||
follow the instructions in the `spack monitor documentation <https://spack-monitor.readthedocs.org>`_
|
|
||||||
to first create a server along with a username and token for yourself.
|
|
||||||
You can then use this guide to interact with the server.
|
|
||||||
|
|
||||||
You should first export our spack monitor token and username to the environment:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ export SPACKMON_TOKEN=50445263afd8f67e59bd79bff597836ee6c05438
|
|
||||||
$ export SPACKMON_USER=spacky
|
|
||||||
|
|
||||||
|
|
||||||
By default, the host for your server is expected to be at ``http://127.0.0.1``
|
|
||||||
with a prefix of ``ms1``, and if this is the case, you can simply add the
|
|
||||||
``--monitor`` flag to the install command:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack analyze run --monitor wget
|
|
||||||
|
|
||||||
If you need to customize the host or the prefix, you can do that as well:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack analyze run --monitor --monitor-prefix monitor --monitor-host https://monitor-service.io wget
|
|
||||||
|
|
||||||
If your server doesn't have authentication, you can skip it:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack analyze run --monitor --monitor-disable-auth wget
|
|
||||||
|
|
||||||
Regardless of your choice, when you run analyze on an installed package (whether
|
|
||||||
it was installed with ``--monitor`` or not, you'll see the results generating as they did
|
|
||||||
before, and a message that the monitor server was pinged:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack analyze --monitor wget
|
|
||||||
...
|
|
||||||
==> Sending result for wget bin/wget to monitor.
|
|
@@ -1114,21 +1114,21 @@ set of arbitrary versions, such as ``@1.0,1.5,1.7`` (``1.0``, ``1.5``,
|
|||||||
or ``1.7``). When you supply such a specifier to ``spack install``,
|
or ``1.7``). When you supply such a specifier to ``spack install``,
|
||||||
it constrains the set of versions that Spack will install.
|
it constrains the set of versions that Spack will install.
|
||||||
|
|
||||||
For packages with a ``git`` attribute, ``git`` references
|
For packages with a ``git`` attribute, ``git`` references
|
||||||
may be specified instead of a numerical version i.e. branches, tags
|
may be specified instead of a numerical version i.e. branches, tags
|
||||||
and commits. Spack will stage and build based off the ``git``
|
and commits. Spack will stage and build based off the ``git``
|
||||||
reference provided. Acceptable syntaxes for this are:
|
reference provided. Acceptable syntaxes for this are:
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
# branches and tags
|
# branches and tags
|
||||||
foo@git.develop # use the develop branch
|
foo@git.develop # use the develop branch
|
||||||
foo@git.0.19 # use the 0.19 tag
|
foo@git.0.19 # use the 0.19 tag
|
||||||
|
|
||||||
# commit hashes
|
# commit hashes
|
||||||
foo@abcdef1234abcdef1234abcdef1234abcdef1234 # 40 character hashes are automatically treated as git commits
|
foo@abcdef1234abcdef1234abcdef1234abcdef1234 # 40 character hashes are automatically treated as git commits
|
||||||
foo@git.abcdef1234abcdef1234abcdef1234abcdef1234
|
foo@git.abcdef1234abcdef1234abcdef1234abcdef1234
|
||||||
|
|
||||||
Spack versions from git reference either have an associated version supplied by the user,
|
Spack versions from git reference either have an associated version supplied by the user,
|
||||||
or infer a relationship to known versions from the structure of the git repository. If an
|
or infer a relationship to known versions from the structure of the git repository. If an
|
||||||
associated version is supplied by the user, Spack treats the git version as equivalent to that
|
associated version is supplied by the user, Spack treats the git version as equivalent to that
|
||||||
@@ -1244,8 +1244,8 @@ For example, for the ``stackstart`` variant:
|
|||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
mpileaks stackstart=4 # variant will be propagated to dependencies
|
mpileaks stackstart==4 # variant will be propagated to dependencies
|
||||||
mpileaks stackstart==4 # only mpileaks will have this variant value
|
mpileaks stackstart=4 # only mpileaks will have this variant value
|
||||||
|
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
Compiler Flags
|
Compiler Flags
|
||||||
@@ -1672,9 +1672,13 @@ own install prefix. However, certain packages are typically installed
|
|||||||
`Python <https://www.python.org>`_ packages are typically installed in the
|
`Python <https://www.python.org>`_ packages are typically installed in the
|
||||||
``$prefix/lib/python-2.7/site-packages`` directory.
|
``$prefix/lib/python-2.7/site-packages`` directory.
|
||||||
|
|
||||||
Spack has support for this type of installation as well. In Spack,
|
In Spack, installation prefixes are immutable, so this type of installation
|
||||||
a package that can live inside the prefix of another package is called
|
is not directly supported. However, it is possible to create views that
|
||||||
an *extension*. Suppose you have Python installed like so:
|
allow you to merge install prefixes of multiple packages into a single new prefix.
|
||||||
|
Views are a convenient way to get a more traditional filesystem structure.
|
||||||
|
Using *extensions*, you can ensure that Python packages always share the
|
||||||
|
same prefix in the view as Python itself. Suppose you have
|
||||||
|
Python installed like so:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
@@ -1712,8 +1716,6 @@ You can find extensions for your Python installation like this:
|
|||||||
py-ipython@2.3.1 py-pygments@2.0.1 py-setuptools@11.3.1
|
py-ipython@2.3.1 py-pygments@2.0.1 py-setuptools@11.3.1
|
||||||
py-matplotlib@1.4.2 py-pyparsing@2.0.3 py-six@1.9.0
|
py-matplotlib@1.4.2 py-pyparsing@2.0.3 py-six@1.9.0
|
||||||
|
|
||||||
==> None activated.
|
|
||||||
|
|
||||||
The extensions are a subset of what's returned by ``spack list``, and
|
The extensions are a subset of what's returned by ``spack list``, and
|
||||||
they are packages like any other. They are installed into their own
|
they are packages like any other. They are installed into their own
|
||||||
prefixes, and you can see this with ``spack find --paths``:
|
prefixes, and you can see this with ``spack find --paths``:
|
||||||
@@ -1741,32 +1743,72 @@ directly when you run ``python``:
|
|||||||
ImportError: No module named numpy
|
ImportError: No module named numpy
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Using Extensions
|
Using Extensions in Environments
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
There are four ways to get ``numpy`` working in Python. The first is
|
The recommended way of working with extensions such as ``py-numpy``
|
||||||
to use :ref:`shell-support`. You can simply ``load`` the extension,
|
above is through :ref:`Environments <environments>`. For example,
|
||||||
and it will be added to the ``PYTHONPATH`` in your current shell:
|
the following creates an environment in the current working directory
|
||||||
|
with a filesystem view in the ``./view`` directory:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ spack load python
|
$ spack env create --with-view view --dir .
|
||||||
$ spack load py-numpy
|
$ spack -e . add py-numpy
|
||||||
|
$ spack -e . concretize
|
||||||
|
$ spack -e . install
|
||||||
|
|
||||||
|
We recommend environments for two reasons. Firstly, environments
|
||||||
|
can be activated (requires :ref:`shell-support`):
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ spack env activate .
|
||||||
|
|
||||||
|
which sets all the right environment variables such as ``PATH`` and
|
||||||
|
``PYTHONPATH``. This ensures that
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ python
|
||||||
|
>>> import numpy
|
||||||
|
|
||||||
|
works. Secondly, even without shell support, the view ensures
|
||||||
|
that Python can locate its extensions:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ ./view/bin/python
|
||||||
|
>>> import numpy
|
||||||
|
|
||||||
|
See :ref:`environments` for a more in-depth description of Spack
|
||||||
|
environments and customizations to views.
|
||||||
|
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Using ``spack load``
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
A more traditional way of using Spack and extensions is ``spack load``
|
||||||
|
(requires :ref:`shell-support`). This will add the extension to ``PYTHONPATH``
|
||||||
|
in your current shell, and Python itself will be available in the ``PATH``:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ spack load py-numpy
|
||||||
|
$ python
|
||||||
|
>>> import numpy
|
||||||
|
|
||||||
Now ``import numpy`` will succeed for as long as you keep your current
|
|
||||||
session open.
|
|
||||||
The loaded packages can be checked using ``spack find --loaded``
|
The loaded packages can be checked using ``spack find --loaded``
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Loading Extensions via Modules
|
Loading Extensions via Modules
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Instead of using Spack's environment modification capabilities through
|
Apart from ``spack env activate`` and ``spack load``, you can load numpy
|
||||||
the ``spack load`` command, you can load numpy through your
|
through your environment modules (using ``environment-modules`` or
|
||||||
environment modules (using ``environment-modules`` or ``lmod``). This
|
``lmod``). This will also add the extension to the ``PYTHONPATH`` in
|
||||||
will also add the extension to the ``PYTHONPATH`` in your current
|
your current shell.
|
||||||
shell.
|
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
@@ -1776,130 +1818,6 @@ If you do not know the name of the specific numpy module you wish to
|
|||||||
load, you can use the ``spack module tcl|lmod loads`` command to get
|
load, you can use the ``spack module tcl|lmod loads`` command to get
|
||||||
the name of the module from the Spack spec.
|
the name of the module from the Spack spec.
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
Activating Extensions in a View
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Another way to use extensions is to create a view, which merges the
|
|
||||||
python installation along with the extensions into a single prefix.
|
|
||||||
See :ref:`configuring_environment_views` for a more in-depth description
|
|
||||||
of views.
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
Activating Extensions Globally
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
As an alternative to creating a merged prefix with Python and its extensions,
|
|
||||||
and prior to support for views, Spack has provided a means to install the
|
|
||||||
extension into the Spack installation prefix for the extendee. This has
|
|
||||||
typically been useful since extendable packages typically search their own
|
|
||||||
installation path for addons by default.
|
|
||||||
|
|
||||||
Global activations are performed with the ``spack activate`` command:
|
|
||||||
|
|
||||||
.. _cmd-spack-activate:
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^
|
|
||||||
``spack activate``
|
|
||||||
^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack activate py-numpy
|
|
||||||
==> Activated extension py-setuptools@11.3.1%gcc@4.4.7 arch=linux-debian7-x86_64-3c74eb69 for python@2.7.8%gcc@4.4.7.
|
|
||||||
==> Activated extension py-nose@1.3.4%gcc@4.4.7 arch=linux-debian7-x86_64-5f70f816 for python@2.7.8%gcc@4.4.7.
|
|
||||||
==> Activated extension py-numpy@1.9.1%gcc@4.4.7 arch=linux-debian7-x86_64-66733244 for python@2.7.8%gcc@4.4.7.
|
|
||||||
|
|
||||||
Several things have happened here. The user requested that
|
|
||||||
``py-numpy`` be activated in the ``python`` installation it was built
|
|
||||||
with. Spack knows that ``py-numpy`` depends on ``py-nose`` and
|
|
||||||
``py-setuptools``, so it activated those packages first. Finally,
|
|
||||||
once all dependencies were activated in the ``python`` installation,
|
|
||||||
``py-numpy`` was activated as well.
|
|
||||||
|
|
||||||
If we run ``spack extensions`` again, we now see the three new
|
|
||||||
packages listed as activated:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack extensions python
|
|
||||||
==> python@2.7.8%gcc@4.4.7 arch=linux-debian7-x86_64-703c7a96
|
|
||||||
==> 36 extensions:
|
|
||||||
geos py-ipython py-pexpect py-pyside py-sip
|
|
||||||
py-basemap py-libxml2 py-pil py-pytz py-six
|
|
||||||
py-biopython py-mako py-pmw py-rpy2 py-sympy
|
|
||||||
py-cython py-matplotlib py-pychecker py-scientificpython py-virtualenv
|
|
||||||
py-dateutil py-mpi4py py-pygments py-scikit-learn
|
|
||||||
py-epydoc py-mx py-pylint py-scipy
|
|
||||||
py-gnuplot py-nose py-pyparsing py-setuptools
|
|
||||||
py-h5py py-numpy py-pyqt py-shiboken
|
|
||||||
|
|
||||||
==> 12 installed:
|
|
||||||
-- linux-debian7-x86_64 / gcc@4.4.7 --------------------------------
|
|
||||||
py-dateutil@2.4.0 py-nose@1.3.4 py-pyside@1.2.2
|
|
||||||
py-dateutil@2.4.0 py-numpy@1.9.1 py-pytz@2014.10
|
|
||||||
py-ipython@2.3.1 py-pygments@2.0.1 py-setuptools@11.3.1
|
|
||||||
py-matplotlib@1.4.2 py-pyparsing@2.0.3 py-six@1.9.0
|
|
||||||
|
|
||||||
==> 3 currently activated:
|
|
||||||
-- linux-debian7-x86_64 / gcc@4.4.7 --------------------------------
|
|
||||||
py-nose@1.3.4 py-numpy@1.9.1 py-setuptools@11.3.1
|
|
||||||
|
|
||||||
Now, when a user runs python, ``numpy`` will be available for import
|
|
||||||
*without* the user having to explicitly load it. ``python@2.7.8`` now
|
|
||||||
acts like a system Python installation with ``numpy`` installed inside
|
|
||||||
of it.
|
|
||||||
|
|
||||||
Spack accomplishes this by symbolically linking the *entire* prefix of
|
|
||||||
the ``py-numpy`` package into the prefix of the ``python`` package. To the
|
|
||||||
python interpreter, it looks like ``numpy`` is installed in the
|
|
||||||
``site-packages`` directory.
|
|
||||||
|
|
||||||
The only limitation of global activation is that you can only have a *single*
|
|
||||||
version of an extension activated at a time. This is because multiple
|
|
||||||
versions of the same extension would conflict if symbolically linked
|
|
||||||
into the same prefix. Users who want a different version of a package
|
|
||||||
can still get it by using environment modules or views, but they will have to
|
|
||||||
explicitly load their preferred version.
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
``spack activate --force``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
If, for some reason, you want to activate a package *without* its
|
|
||||||
dependencies, you can use ``spack activate --force``:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack activate --force py-numpy
|
|
||||||
==> Activated extension py-numpy@1.9.1%gcc@4.4.7 arch=linux-debian7-x86_64-66733244 for python@2.7.8%gcc@4.4.7.
|
|
||||||
|
|
||||||
.. _cmd-spack-deactivate:
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
|
||||||
``spack deactivate``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
We've seen how activating an extension can be used to set up a default
|
|
||||||
version of a Python module. Obviously, you may want to change that at
|
|
||||||
some point. ``spack deactivate`` is the command for this. There are
|
|
||||||
several variants:
|
|
||||||
|
|
||||||
* ``spack deactivate <extension>`` will deactivate a single
|
|
||||||
extension. If another activated extension depends on this one,
|
|
||||||
Spack will warn you and exit with an error.
|
|
||||||
* ``spack deactivate --force <extension>`` deactivates an extension
|
|
||||||
regardless of packages that depend on it.
|
|
||||||
* ``spack deactivate --all <extension>`` deactivates an extension and
|
|
||||||
all of its dependencies. Use ``--force`` to disregard dependents.
|
|
||||||
* ``spack deactivate --all <extendee>`` deactivates *all* activated
|
|
||||||
extensions of a package. For example, to deactivate *all* python
|
|
||||||
extensions, use:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack deactivate --all python
|
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
Filesystem requirements
|
Filesystem requirements
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@@ -13,49 +13,51 @@ Some sites may encourage users to set up their own test environments
|
|||||||
before carrying out central installations, or some users may prefer to set
|
before carrying out central installations, or some users may prefer to set
|
||||||
up these environments on their own motivation. To reduce the load of
|
up these environments on their own motivation. To reduce the load of
|
||||||
recompiling otherwise identical package specs in different installations,
|
recompiling otherwise identical package specs in different installations,
|
||||||
installed packages can be put into build cache tarballs, uploaded to
|
installed packages can be put into build cache tarballs, pushed to
|
||||||
your Spack mirror and then downloaded and installed by others.
|
your Spack mirror and then downloaded and installed by others.
|
||||||
|
|
||||||
|
Whenever a mirror provides prebuilt packages, Spack will take these packages
|
||||||
|
into account during concretization and installation, making ``spack install``
|
||||||
|
signficantly faster.
|
||||||
|
|
||||||
--------------------------
|
|
||||||
Creating build cache files
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
A compressed tarball of an installed package is created. Tarballs are created
|
.. note::
|
||||||
for all of its link and run dependency packages as well. Compressed tarballs are
|
|
||||||
signed with gpg and signature and tarball and put in a ``.spack`` file. Optionally,
|
We use the terms "build cache" and "mirror" often interchangeably. Mirrors
|
||||||
the rpaths (and ids and deps on macOS) can be changed to paths relative to
|
are used during installation both for sources and prebuilt packages. Build
|
||||||
the Spack install tree before the tarball is created.
|
caches refer to mirrors that provide prebuilt packages.
|
||||||
|
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
Creating a build cache
|
||||||
|
----------------------
|
||||||
|
|
||||||
Build caches are created via:
|
Build caches are created via:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ spack buildcache create <spec>
|
$ spack buildcache create <path/url/mirror name> <spec>
|
||||||
|
|
||||||
|
This command takes the locally installed spec and its dependencies, and
|
||||||
|
creates tarballs of their install prefixes. It also generates metadata files,
|
||||||
|
signed with GPG. These tarballs and metadata files are then pushed to the
|
||||||
|
provided binary cache, which can be a local directory or a remote URL.
|
||||||
|
|
||||||
If you wanted to create a build cache in a local directory, you would provide
|
Here is an example where a build cache is created in a local directory named
|
||||||
the ``-d`` argument to target that directory, again also specifying the spec.
|
"spack-cache", to which we push the "ninja" spec:
|
||||||
Here is an example creating a local directory, "spack-cache" and creating
|
|
||||||
build cache files for the "ninja" spec:
|
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ mkdir -p ./spack-cache
|
$ spack buildcache create --allow-root ./spack-cache ninja
|
||||||
$ spack buildcache create -d ./spack-cache ninja
|
==> Pushing binary packages to file:///home/spackuser/spack/spack-cache/build_cache
|
||||||
==> Buildcache files will be output to file:///home/spackuser/spack/spack-cache/build_cache
|
|
||||||
gpgconf: socketdir is '/run/user/1000/gnupg'
|
|
||||||
gpg: using "E6DF6A8BD43208E4D6F392F23777740B7DBD643D" as default secret key for signing
|
|
||||||
|
|
||||||
Note that the targeted spec must already be installed. Once you have a build cache,
|
Not that ``ninja`` must be installed locally for this to work.
|
||||||
you can add it as a mirror, discussed next.
|
|
||||||
|
|
||||||
.. warning::
|
We're using the ``--allow-root`` flag to tell Spack that is OK when any of
|
||||||
|
the binaries we're pushing contain references to the local Spack install
|
||||||
|
directory.
|
||||||
|
|
||||||
Spack improved the format used for binary caches in v0.18. The entire v0.18 series
|
Once you have a build cache, you can add it as a mirror, discussed next.
|
||||||
will be able to verify and install binary caches both in the new and in the old format.
|
|
||||||
Support for using the old format is expected to end in v0.19, so we advise users to
|
|
||||||
recreate relevant buildcaches using Spack v0.18 or higher.
|
|
||||||
|
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
Finding or installing build cache files
|
Finding or installing build cache files
|
||||||
@@ -66,10 +68,10 @@ with:
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ spack mirror add <name> <url>
|
$ spack mirror add <name> <url or path>
|
||||||
|
|
||||||
|
|
||||||
Note that the url can be a web url _or_ a local filesystem location. In the previous
|
Both web URLs and local paths on the filesystem can be specified. In the previous
|
||||||
example, you might add the directory "spack-cache" and call it ``mymirror``:
|
example, you might add the directory "spack-cache" and call it ``mymirror``:
|
||||||
|
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ this new build cache as follows:
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ spack buildcache update-index -d spack-cache/
|
$ spack buildcache update-index ./spack-cache
|
||||||
|
|
||||||
Now you can use list:
|
Now you can use list:
|
||||||
|
|
||||||
@@ -105,46 +107,38 @@ Now you can use list:
|
|||||||
-- linux-ubuntu20.04-skylake / gcc@9.3.0 ------------------------
|
-- linux-ubuntu20.04-skylake / gcc@9.3.0 ------------------------
|
||||||
ninja@1.10.2
|
ninja@1.10.2
|
||||||
|
|
||||||
|
With ``mymirror`` configured and an index available, Spack will automatically
|
||||||
Great! So now let's say you have a different spack installation, or perhaps just
|
use it during concretization and installation. That means that you can expect
|
||||||
a different environment for the same one, and you want to install a package from
|
``spack install ninja`` to fetch prebuilt packages from the mirror. Let's
|
||||||
that build cache. Let's first uninstall the actual library "ninja" to see if we can
|
verify by re-installing ninja:
|
||||||
re-install it from the cache.
|
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ spack uninstall ninja
|
$ spack uninstall ninja
|
||||||
|
$ spack install ninja
|
||||||
|
==> Installing ninja-1.11.1-yxferyhmrjkosgta5ei6b4lqf6bxbscz
|
||||||
And now reinstall from the buildcache
|
==> Fetching file:///home/spackuser/spack/spack-cache/build_cache/linux-ubuntu20.04-skylake-gcc-9.3.0-ninja-1.10.2-yxferyhmrjkosgta5ei6b4lqf6bxbscz.spec.json.sig
|
||||||
|
gpg: Signature made Do 12 Jan 2023 16:01:04 CET
|
||||||
.. code-block:: console
|
gpg: using RSA key 61B82B2B2350E171BD17A1744E3A689061D57BF6
|
||||||
|
gpg: Good signature from "example (GPG created for Spack) <example@example.com>" [ultimate]
|
||||||
$ spack buildcache install ninja
|
==> Fetching file:///home/spackuser/spack/spack-cache/build_cache/linux-ubuntu20.04-skylake/gcc-9.3.0/ninja-1.10.2/linux-ubuntu20.04-skylake-gcc-9.3.0-ninja-1.10.2-yxferyhmrjkosgta5ei6b4lqf6bxbscz.spack
|
||||||
==> buildcache spec(s) matching ninja
|
==> Extracting ninja-1.10.2-yxferyhmrjkosgta5ei6b4lqf6bxbscz from binary cache
|
||||||
==> Fetching file:///home/spackuser/spack/spack-cache/build_cache/linux-ubuntu20.04-skylake/gcc-9.3.0/ninja-1.10.2/linux-ubuntu20.04-skylake-gcc-9.3.0-ninja-1.10.2-i4e5luour7jxdpc3bkiykd4imke3mkym.spack
|
==> ninja: Successfully installed ninja-1.11.1-yxferyhmrjkosgta5ei6b4lqf6bxbscz
|
||||||
####################################################################################################################################### 100.0%
|
Search: 0.00s. Fetch: 0.17s. Install: 0.12s. Total: 0.29s
|
||||||
==> Installing buildcache for spec ninja@1.10.2%gcc@9.3.0 arch=linux-ubuntu20.04-skylake
|
[+] /home/harmen/spack/opt/spack/linux-ubuntu20.04-skylake/gcc-9.3.0/ninja-1.11.1-yxferyhmrjkosgta5ei6b4lqf6bxbscz
|
||||||
gpgconf: socketdir is '/run/user/1000/gnupg'
|
|
||||||
gpg: Signature made Tue 23 Mar 2021 10:16:29 PM MDT
|
|
||||||
gpg: using RSA key E6DF6A8BD43208E4D6F392F23777740B7DBD643D
|
|
||||||
gpg: Good signature from "spackuser (GPG created for Spack) <spackuser@noreply.users.github.com>" [ultimate]
|
|
||||||
|
|
||||||
|
|
||||||
It worked! You've just completed a full example of creating a build cache with
|
It worked! You've just completed a full example of creating a build cache with
|
||||||
a spec of interest, adding it as a mirror, updating it's index, listing the contents,
|
a spec of interest, adding it as a mirror, updating its index, listing the contents,
|
||||||
and finally, installing from it.
|
and finally, installing from it.
|
||||||
|
|
||||||
|
By default Spack falls back to building from sources when the mirror is not available
|
||||||
Note that the above command is intended to install a particular package to a
|
or when the package is simply not already available. To force Spack to only install
|
||||||
build cache you have created, and not to install a package from a build cache.
|
prebuilt packages, you can use
|
||||||
For the latter, once a mirror is added, by default when you do ``spack install`` the ``--use-cache``
|
|
||||||
flag is set, and you will install a package from a build cache if it is available.
|
|
||||||
If you want to always use the cache, you can do:
|
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ spack install --cache-only <package>
|
$ spack install --use-buildcache only <package>
|
||||||
|
|
||||||
For example, to combine all of the commands above to add the E4S build cache
|
For example, to combine all of the commands above to add the E4S build cache
|
||||||
and then install from it exclusively, you would do:
|
and then install from it exclusively, you would do:
|
||||||
@@ -153,7 +147,7 @@ and then install from it exclusively, you would do:
|
|||||||
|
|
||||||
$ spack mirror add E4S https://cache.e4s.io
|
$ spack mirror add E4S https://cache.e4s.io
|
||||||
$ spack buildcache keys --install --trust
|
$ spack buildcache keys --install --trust
|
||||||
$ spack install --cache-only <package>
|
$ spack install --use-buildache only <package>
|
||||||
|
|
||||||
We use ``--install`` and ``--trust`` to say that we are installing keys to our
|
We use ``--install`` and ``--trust`` to say that we are installing keys to our
|
||||||
keyring, and trusting all downloaded keys.
|
keyring, and trusting all downloaded keys.
|
||||||
|
@@ -272,7 +272,7 @@ Selection of the target microarchitectures
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The options under the ``targets`` attribute control which targets are considered during a solve.
|
The options under the ``targets`` attribute control which targets are considered during a solve.
|
||||||
Currently the options in this section are only configurable from the ``concretization.yaml`` file
|
Currently the options in this section are only configurable from the ``concretizer.yaml`` file
|
||||||
and there are no corresponding command line arguments to enable them for a single solve.
|
and there are no corresponding command line arguments to enable them for a single solve.
|
||||||
|
|
||||||
The ``granularity`` option can take two possible values: ``microarchitectures`` and ``generic``.
|
The ``granularity`` option can take two possible values: ``microarchitectures`` and ``generic``.
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
.. _cachedcmakepackage:
|
.. _cachedcmakepackage:
|
||||||
|
|
||||||
------------------
|
-----------
|
||||||
CachedCMakePackage
|
CachedCMake
|
||||||
------------------
|
-----------
|
||||||
|
|
||||||
The CachedCMakePackage base class is used for CMake-based workflows
|
The CachedCMakePackage base class is used for CMake-based workflows
|
||||||
that create a CMake cache file prior to running ``cmake``. This is
|
that create a CMake cache file prior to running ``cmake``. This is
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
.. _cudapackage:
|
.. _cudapackage:
|
||||||
|
|
||||||
-----------
|
----
|
||||||
CudaPackage
|
Cuda
|
||||||
-----------
|
----
|
||||||
|
|
||||||
Different from other packages, ``CudaPackage`` does not represent a build system.
|
Different from other packages, ``CudaPackage`` does not represent a build system.
|
||||||
Instead its goal is to simplify and unify usage of ``CUDA`` in other packages by providing a `mixin-class <https://en.wikipedia.org/wiki/Mixin>`_.
|
Instead its goal is to simplify and unify usage of ``CUDA`` in other packages by providing a `mixin-class <https://en.wikipedia.org/wiki/Mixin>`_.
|
||||||
@@ -80,7 +80,7 @@ standard CUDA compiler flags.
|
|||||||
|
|
||||||
**cuda_flags**
|
**cuda_flags**
|
||||||
|
|
||||||
This built-in static method returns a list of command line flags
|
This built-in static method returns a list of command line flags
|
||||||
for the chosen ``cuda_arch`` value(s). The flags are intended to
|
for the chosen ``cuda_arch`` value(s). The flags are intended to
|
||||||
be passed to the CUDA compiler driver (i.e., ``nvcc``).
|
be passed to the CUDA compiler driver (i.e., ``nvcc``).
|
||||||
|
|
||||||
|
@@ -6,9 +6,9 @@
|
|||||||
.. _inteloneapipackage:
|
.. _inteloneapipackage:
|
||||||
|
|
||||||
|
|
||||||
====================
|
===========
|
||||||
IntelOneapiPackage
|
IntelOneapi
|
||||||
====================
|
===========
|
||||||
|
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
@@ -36,7 +36,7 @@ For more information on a specific package, do::
|
|||||||
|
|
||||||
Intel no longer releases new versions of Parallel Studio, which can be
|
Intel no longer releases new versions of Parallel Studio, which can be
|
||||||
used in Spack via the :ref:`intelpackage`. All of its components can
|
used in Spack via the :ref:`intelpackage`. All of its components can
|
||||||
now be found in oneAPI.
|
now be found in oneAPI.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
========
|
========
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
.. _intelpackage:
|
.. _intelpackage:
|
||||||
|
|
||||||
------------
|
-----
|
||||||
IntelPackage
|
Intel
|
||||||
------------
|
-----
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
.. _pythonpackage:
|
.. _pythonpackage:
|
||||||
|
|
||||||
-------------
|
------
|
||||||
PythonPackage
|
Python
|
||||||
-------------
|
------
|
||||||
|
|
||||||
Python packages and modules have their own special build system. This
|
Python packages and modules have their own special build system. This
|
||||||
documentation covers everything you'll need to know in order to write
|
documentation covers everything you'll need to know in order to write
|
||||||
@@ -724,10 +724,9 @@ extends vs. depends_on
|
|||||||
|
|
||||||
This is very similar to the naming dilemma above, with a slight twist.
|
This is very similar to the naming dilemma above, with a slight twist.
|
||||||
As mentioned in the :ref:`Packaging Guide <packaging_extensions>`,
|
As mentioned in the :ref:`Packaging Guide <packaging_extensions>`,
|
||||||
``extends`` and ``depends_on`` are very similar, but ``extends`` adds
|
``extends`` and ``depends_on`` are very similar, but ``extends`` ensures
|
||||||
the ability to *activate* the package. Activation involves symlinking
|
that the extension and extendee share the same prefix in views.
|
||||||
everything in the installation prefix of the package to the installation
|
This allows the user to import a Python module without
|
||||||
prefix of Python. This allows the user to import a Python module without
|
|
||||||
having to add that module to ``PYTHONPATH``.
|
having to add that module to ``PYTHONPATH``.
|
||||||
|
|
||||||
When deciding between ``extends`` and ``depends_on``, the best rule of
|
When deciding between ``extends`` and ``depends_on``, the best rule of
|
||||||
@@ -735,7 +734,7 @@ thumb is to check the installation prefix. If Python libraries are
|
|||||||
installed to ``<prefix>/lib/pythonX.Y/site-packages``, then you
|
installed to ``<prefix>/lib/pythonX.Y/site-packages``, then you
|
||||||
should use ``extends``. If Python libraries are installed elsewhere
|
should use ``extends``. If Python libraries are installed elsewhere
|
||||||
or the only files that get installed reside in ``<prefix>/bin``, then
|
or the only files that get installed reside in ``<prefix>/bin``, then
|
||||||
don't use ``extends``, as symlinking the package wouldn't be useful.
|
don't use ``extends``.
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
Alternatives to Spack
|
Alternatives to Spack
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
.. _rocmpackage:
|
.. _rocmpackage:
|
||||||
|
|
||||||
-----------
|
----
|
||||||
ROCmPackage
|
ROCm
|
||||||
-----------
|
----
|
||||||
|
|
||||||
The ``ROCmPackage`` is not a build system but a helper package. Like ``CudaPackage``,
|
The ``ROCmPackage`` is not a build system but a helper package. Like ``CudaPackage``,
|
||||||
it provides standard variants, dependencies, and conflicts to facilitate building
|
it provides standard variants, dependencies, and conflicts to facilitate building
|
||||||
@@ -25,7 +25,7 @@ This package provides the following variants:
|
|||||||
|
|
||||||
* **rocm**
|
* **rocm**
|
||||||
|
|
||||||
This variant is used to enable/disable building with ``rocm``.
|
This variant is used to enable/disable building with ``rocm``.
|
||||||
The default is disabled (or ``False``).
|
The default is disabled (or ``False``).
|
||||||
|
|
||||||
* **amdgpu_target**
|
* **amdgpu_target**
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
.. _rpackage:
|
.. _rpackage:
|
||||||
|
|
||||||
--------
|
--
|
||||||
RPackage
|
R
|
||||||
--------
|
--
|
||||||
|
|
||||||
Like Python, R has its own built-in build system.
|
Like Python, R has its own built-in build system.
|
||||||
|
|
||||||
@@ -193,10 +193,10 @@ Build system dependencies
|
|||||||
|
|
||||||
As an extension of the R ecosystem, your package will obviously depend
|
As an extension of the R ecosystem, your package will obviously depend
|
||||||
on R to build and run. Normally, we would use ``depends_on`` to express
|
on R to build and run. Normally, we would use ``depends_on`` to express
|
||||||
this, but for R packages, we use ``extends``. ``extends`` is similar to
|
this, but for R packages, we use ``extends``. This implies a special
|
||||||
``depends_on``, but adds an additional feature: the ability to "activate"
|
dependency on R, which is used to set environment variables such as
|
||||||
the package by symlinking it to the R installation directory. Since
|
``R_LIBS`` uniformly. Since every R package needs this, the ``RPackage``
|
||||||
every R package needs this, the ``RPackage`` base class contains:
|
base class contains:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@@ -5,15 +5,15 @@
|
|||||||
|
|
||||||
.. _sourceforgepackage:
|
.. _sourceforgepackage:
|
||||||
|
|
||||||
------------------
|
-----------
|
||||||
SourceforgePackage
|
Sourceforge
|
||||||
------------------
|
-----------
|
||||||
|
|
||||||
``SourceforgePackage`` is a
|
``SourceforgePackage`` is a
|
||||||
`mixin-class <https://en.wikipedia.org/wiki/Mixin>`_. It automatically
|
`mixin-class <https://en.wikipedia.org/wiki/Mixin>`_. It automatically
|
||||||
sets the URL based on a list of Sourceforge mirrors listed in
|
sets the URL based on a list of Sourceforge mirrors listed in
|
||||||
`sourceforge_mirror_path`, which defaults to a half dozen known mirrors.
|
`sourceforge_mirror_path`, which defaults to a half dozen known mirrors.
|
||||||
Refer to the package source
|
Refer to the package source
|
||||||
(`<https://github.com/spack/spack/blob/develop/lib/spack/spack/build_systems/sourceforge.py>`__) for the current list of mirrors used by Spack.
|
(`<https://github.com/spack/spack/blob/develop/lib/spack/spack/build_systems/sourceforge.py>`__) for the current list of mirrors used by Spack.
|
||||||
|
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ This package provides a method for populating mirror URLs.
|
|||||||
It is decorated with `property` so its results are treated as
|
It is decorated with `property` so its results are treated as
|
||||||
a package attribute.
|
a package attribute.
|
||||||
|
|
||||||
Refer to
|
Refer to
|
||||||
`<https://spack.readthedocs.io/en/latest/packaging_guide.html#mirrors-of-the-main-url>`__
|
`<https://spack.readthedocs.io/en/latest/packaging_guide.html#mirrors-of-the-main-url>`__
|
||||||
for information on how Spack uses the `urls` attribute during
|
for information on how Spack uses the `urls` attribute during
|
||||||
fetching.
|
fetching.
|
||||||
|
@@ -36,13 +36,7 @@
|
|||||||
if not os.path.exists(link_name):
|
if not os.path.exists(link_name):
|
||||||
os.symlink(os.path.abspath("../../.."), link_name, target_is_directory=True)
|
os.symlink(os.path.abspath("../../.."), link_name, target_is_directory=True)
|
||||||
sys.path.insert(0, os.path.abspath("_spack_root/lib/spack/external"))
|
sys.path.insert(0, os.path.abspath("_spack_root/lib/spack/external"))
|
||||||
sys.path.insert(0, os.path.abspath("_spack_root/lib/spack/external/pytest-fallback"))
|
sys.path.insert(0, os.path.abspath("_spack_root/lib/spack/external/_vendoring"))
|
||||||
|
|
||||||
if sys.version_info[0] < 3:
|
|
||||||
sys.path.insert(0, os.path.abspath("_spack_root/lib/spack/external/yaml/lib"))
|
|
||||||
else:
|
|
||||||
sys.path.insert(0, os.path.abspath("_spack_root/lib/spack/external/yaml/lib3"))
|
|
||||||
|
|
||||||
sys.path.append(os.path.abspath("_spack_root/lib/spack/"))
|
sys.path.append(os.path.abspath("_spack_root/lib/spack/"))
|
||||||
|
|
||||||
# Add the Spack bin directory to the path so that we can use its output in docs.
|
# Add the Spack bin directory to the path so that we can use its output in docs.
|
||||||
@@ -80,8 +74,16 @@
|
|||||||
"--force", # Overwrite existing files
|
"--force", # Overwrite existing files
|
||||||
"--no-toc", # Don't create a table of contents file
|
"--no-toc", # Don't create a table of contents file
|
||||||
"--output-dir=.", # Directory to place all output
|
"--output-dir=.", # Directory to place all output
|
||||||
|
"--module-first", # emit module docs before submodule docs
|
||||||
]
|
]
|
||||||
sphinx_apidoc(apidoc_args + ["_spack_root/lib/spack/spack"])
|
sphinx_apidoc(
|
||||||
|
apidoc_args
|
||||||
|
+ [
|
||||||
|
"_spack_root/lib/spack/spack",
|
||||||
|
"_spack_root/lib/spack/spack/test/*.py",
|
||||||
|
"_spack_root/lib/spack/spack/test/cmd/*.py",
|
||||||
|
]
|
||||||
|
)
|
||||||
sphinx_apidoc(apidoc_args + ["_spack_root/lib/spack/llnl"])
|
sphinx_apidoc(apidoc_args + ["_spack_root/lib/spack/llnl"])
|
||||||
|
|
||||||
# Enable todo items
|
# Enable todo items
|
||||||
@@ -160,8 +162,8 @@ def setup(sphinx):
|
|||||||
master_doc = "index"
|
master_doc = "index"
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u"Spack"
|
project = "Spack"
|
||||||
copyright = u"2013-2021, Lawrence Livermore National Laboratory."
|
copyright = "2013-2021, Lawrence Livermore National Laboratory."
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
@@ -206,12 +208,14 @@ def setup(sphinx):
|
|||||||
("py:class", "_frozen_importlib_external.SourceFileLoader"),
|
("py:class", "_frozen_importlib_external.SourceFileLoader"),
|
||||||
("py:class", "clingo.Control"),
|
("py:class", "clingo.Control"),
|
||||||
("py:class", "six.moves.urllib.parse.ParseResult"),
|
("py:class", "six.moves.urllib.parse.ParseResult"),
|
||||||
|
("py:class", "TextIO"),
|
||||||
# Spack classes that are private and we don't want to expose
|
# Spack classes that are private and we don't want to expose
|
||||||
("py:class", "spack.provider_index._IndexBase"),
|
("py:class", "spack.provider_index._IndexBase"),
|
||||||
("py:class", "spack.repo._PrependFileLoader"),
|
("py:class", "spack.repo._PrependFileLoader"),
|
||||||
("py:class", "spack.build_systems._checks.BaseBuilder"),
|
("py:class", "spack.build_systems._checks.BaseBuilder"),
|
||||||
# Spack classes that intersphinx is unable to resolve
|
# Spack classes that intersphinx is unable to resolve
|
||||||
("py:class", "spack.version.VersionBase"),
|
("py:class", "spack.version.VersionBase"),
|
||||||
|
("py:class", "spack.spec.DependencySpec"),
|
||||||
]
|
]
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||||
@@ -350,7 +354,7 @@ class SpackStyle(DefaultStyle):
|
|||||||
# 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, author, documentclass [howto/manual]).
|
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||||
latex_documents = [
|
latex_documents = [
|
||||||
("index", "Spack.tex", u"Spack Documentation", u"Todd Gamblin", "manual"),
|
("index", "Spack.tex", "Spack Documentation", "Todd Gamblin", "manual"),
|
||||||
]
|
]
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
@@ -378,7 +382,7 @@ class SpackStyle(DefaultStyle):
|
|||||||
|
|
||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [("index", "spack", u"Spack Documentation", [u"Todd Gamblin"], 1)]
|
man_pages = [("index", "spack", "Spack Documentation", ["Todd Gamblin"], 1)]
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
# man_show_urls = False
|
# man_show_urls = False
|
||||||
@@ -393,8 +397,8 @@ class SpackStyle(DefaultStyle):
|
|||||||
(
|
(
|
||||||
"index",
|
"index",
|
||||||
"Spack",
|
"Spack",
|
||||||
u"Spack Documentation",
|
"Spack Documentation",
|
||||||
u"Todd Gamblin",
|
"Todd Gamblin",
|
||||||
"Spack",
|
"Spack",
|
||||||
"One line description of project.",
|
"One line description of project.",
|
||||||
"Miscellaneous",
|
"Miscellaneous",
|
||||||
|
@@ -394,7 +394,7 @@ are indicated at the start of the path with ``~`` or ``~user``.
|
|||||||
Spack-specific variables
|
Spack-specific variables
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Spack understands several special variables. These are:
|
Spack understands over a dozen special variables. These are:
|
||||||
|
|
||||||
* ``$env``: name of the currently active :ref:`environment <environments>`
|
* ``$env``: name of the currently active :ref:`environment <environments>`
|
||||||
* ``$spack``: path to the prefix of this Spack installation
|
* ``$spack``: path to the prefix of this Spack installation
|
||||||
@@ -416,6 +416,8 @@ Spack understands several special variables. These are:
|
|||||||
ArchSpec. E.g. ``skylake`` or ``neoverse-n1``.
|
ArchSpec. E.g. ``skylake`` or ``neoverse-n1``.
|
||||||
* ``$target_family``. The target family for the current host, as
|
* ``$target_family``. The target family for the current host, as
|
||||||
detected by ArchSpec. E.g. ``x86_64`` or ``aarch64``.
|
detected by ArchSpec. E.g. ``x86_64`` or ``aarch64``.
|
||||||
|
* ``$date``: the current date in the format YYYY-MM-DD
|
||||||
|
|
||||||
|
|
||||||
Note that, as with shell variables, you can write these as ``$varname``
|
Note that, as with shell variables, you can write these as ``$varname``
|
||||||
or with braces to distinguish the variable from surrounding characters:
|
or with braces to distinguish the variable from surrounding characters:
|
||||||
|
@@ -253,27 +253,6 @@ to update them.
|
|||||||
multiple runs of ``spack style`` just to re-compute line numbers and
|
multiple runs of ``spack style`` just to re-compute line numbers and
|
||||||
makes it much easier to fix errors directly off of the CI output.
|
makes it much easier to fix errors directly off of the CI output.
|
||||||
|
|
||||||
.. warning::
|
|
||||||
|
|
||||||
Flake8 and ``pep8-naming`` require a number of dependencies in order
|
|
||||||
to run. If you installed ``py-flake8`` and ``py-pep8-naming``, the
|
|
||||||
easiest way to ensure the right packages are on your ``PYTHONPATH`` is
|
|
||||||
to run::
|
|
||||||
|
|
||||||
spack activate py-flake8
|
|
||||||
spack activate pep8-naming
|
|
||||||
|
|
||||||
so that all of the dependencies are symlinked to a central
|
|
||||||
location. If you see an error message like:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File: "/usr/bin/flake8", line 5, in <module>
|
|
||||||
from pkg_resources import load_entry_point
|
|
||||||
ImportError: No module named pkg_resources
|
|
||||||
|
|
||||||
that means Flake8 couldn't find setuptools in your ``PYTHONPATH``.
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
Documentation Tests
|
Documentation Tests
|
||||||
@@ -309,13 +288,9 @@ All of these can be installed with Spack, e.g.
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ spack activate py-sphinx
|
$ spack load py-sphinx py-sphinx-rtd-theme py-sphinxcontrib-programoutput
|
||||||
$ spack activate py-sphinx-rtd-theme
|
|
||||||
$ spack activate py-sphinxcontrib-programoutput
|
|
||||||
|
|
||||||
so that all of the dependencies are symlinked into that Python's
|
so that all of the dependencies are added to PYTHONPATH. If you see an error message
|
||||||
tree. Alternatively, you could arrange for their library
|
|
||||||
directories to be added to PYTHONPATH. If you see an error message
|
|
||||||
like:
|
like:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
@@ -175,14 +175,11 @@ Spec-related modules
|
|||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
:mod:`spack.spec`
|
:mod:`spack.spec`
|
||||||
Contains :class:`~spack.spec.Spec` and :class:`~spack.spec.SpecParser`.
|
Contains :class:`~spack.spec.Spec`. Also implements most of the logic for concretization
|
||||||
Also implements most of the logic for normalization and concretization
|
|
||||||
of specs.
|
of specs.
|
||||||
|
|
||||||
:mod:`spack.parse`
|
:mod:`spack.parser`
|
||||||
Contains some base classes for implementing simple recursive descent
|
Contains :class:`~spack.parser.SpecParser` and functions related to parsing specs.
|
||||||
parsers: :class:`~spack.parse.Parser` and :class:`~spack.parse.Lexer`.
|
|
||||||
Used by :class:`~spack.spec.SpecParser`.
|
|
||||||
|
|
||||||
:mod:`spack.concretize`
|
:mod:`spack.concretize`
|
||||||
Contains :class:`~spack.concretize.Concretizer` implementation,
|
Contains :class:`~spack.concretize.Concretizer` implementation,
|
||||||
@@ -235,7 +232,7 @@ Spack Subcommands
|
|||||||
Unit tests
|
Unit tests
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
:mod:`spack.test`
|
``spack.test``
|
||||||
Implements Spack's test suite. Add a module and put its name in
|
Implements Spack's test suite. Add a module and put its name in
|
||||||
the test suite in ``__init__.py`` to add more unit tests.
|
the test suite in ``__init__.py`` to add more unit tests.
|
||||||
|
|
||||||
|
@@ -233,8 +233,8 @@ packages will be listed as roots of the Environment.
|
|||||||
|
|
||||||
All of the Spack commands that act on the list of installed specs are
|
All of the Spack commands that act on the list of installed specs are
|
||||||
Environment-sensitive in this way, including ``install``,
|
Environment-sensitive in this way, including ``install``,
|
||||||
``uninstall``, ``activate``, ``deactivate``, ``find``, ``extensions``,
|
``uninstall``, ``find``, ``extensions``, and more. In the
|
||||||
and more. In the :ref:`environment-configuration` section we will discuss
|
:ref:`environment-configuration` section we will discuss
|
||||||
Environment-sensitive commands further.
|
Environment-sensitive commands further.
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
@@ -1070,19 +1070,23 @@ the include is conditional.
|
|||||||
Building a subset of the environment
|
Building a subset of the environment
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The generated ``Makefile``\s contain install targets for each spec. Given the hash
|
The generated ``Makefile``\s contain install targets for each spec, identified
|
||||||
of a particular spec, you can use the ``.install/<hash>`` target to install the
|
by ``<name>-<version>-<hash>``. This allows you to install only a subset of the
|
||||||
spec with its dependencies. There is also ``.install-deps/<hash>`` to *only* install
|
packages in the environment. When packages are unique in the environment, it's
|
||||||
|
enough to know the name and let tab-completion fill out the version and hash.
|
||||||
|
|
||||||
|
The following phony targets are available: ``install/<spec>`` to install the
|
||||||
|
spec with its dependencies, and ``install-deps/<spec>`` to *only* install
|
||||||
its dependencies. This can be useful when certain flags should only apply to
|
its dependencies. This can be useful when certain flags should only apply to
|
||||||
dependencies. Below we show a use case where a spec is installed with verbose
|
dependencies. Below we show a use case where a spec is installed with verbose
|
||||||
output (``spack install --verbose``) while its dependencies are installed silently:
|
output (``spack install --verbose``) while its dependencies are installed silently:
|
||||||
|
|
||||||
.. code:: console
|
.. code:: console
|
||||||
|
|
||||||
$ spack env depfile -o Makefile --make-target-prefix my_env
|
$ spack env depfile -o Makefile
|
||||||
|
|
||||||
# Install dependencies in parallel, only show a log on error.
|
# Install dependencies in parallel, only show a log on error.
|
||||||
$ make -j16 my_env/.install-deps/<hash> SPACK_INSTALL_FLAGS=--show-log-on-error
|
$ make -j16 install-deps/python-3.11.0-<hash> SPACK_INSTALL_FLAGS=--show-log-on-error
|
||||||
|
|
||||||
# Install the root spec with verbose output.
|
# Install the root spec with verbose output.
|
||||||
$ make -j16 my_env/.install/<hash> SPACK_INSTALL_FLAGS=--verbose
|
$ make -j16 install/python-3.11.0-<hash> SPACK_INSTALL_FLAGS=--verbose
|
@@ -21,8 +21,9 @@ be present on the machine where Spack is run:
|
|||||||
:header-rows: 1
|
:header-rows: 1
|
||||||
|
|
||||||
These requirements can be easily installed on most modern Linux systems;
|
These requirements can be easily installed on most modern Linux systems;
|
||||||
on macOS, XCode is required. Spack is designed to run on HPC
|
on macOS, the Command Line Tools package is required, and a full XCode suite
|
||||||
platforms like Cray. Not all packages should be expected
|
may be necessary for some packages such as Qt and apple-gl. Spack is designed
|
||||||
|
to run on HPC platforms like Cray. Not all packages should be expected
|
||||||
to work on all platforms.
|
to work on all platforms.
|
||||||
|
|
||||||
A build matrix showing which packages are working on which systems is shown below.
|
A build matrix showing which packages are working on which systems is shown below.
|
||||||
@@ -1704,9 +1705,11 @@ dependencies or incompatible build tools like autoconf. Here are several
|
|||||||
packages known to work on Windows:
|
packages known to work on Windows:
|
||||||
|
|
||||||
* abseil-cpp
|
* abseil-cpp
|
||||||
|
* bzip2
|
||||||
* clingo
|
* clingo
|
||||||
* cpuinfo
|
* cpuinfo
|
||||||
* cmake
|
* cmake
|
||||||
|
* hdf5
|
||||||
* glm
|
* glm
|
||||||
* nasm
|
* nasm
|
||||||
* netlib-lapack (requires Intel Fortran)
|
* netlib-lapack (requires Intel Fortran)
|
||||||
|
@@ -67,7 +67,6 @@ or refer to the full manual below.
|
|||||||
build_settings
|
build_settings
|
||||||
environments
|
environments
|
||||||
containers
|
containers
|
||||||
monitoring
|
|
||||||
mirrors
|
mirrors
|
||||||
module_file_support
|
module_file_support
|
||||||
repositories
|
repositories
|
||||||
@@ -78,12 +77,6 @@ or refer to the full manual below.
|
|||||||
extensions
|
extensions
|
||||||
pipelines
|
pipelines
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
:caption: Research
|
|
||||||
|
|
||||||
analyze
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
:caption: Contributing
|
:caption: Contributing
|
||||||
|
@@ -1,265 +0,0 @@
|
|||||||
.. Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
|
|
||||||
Spack Project Developers. See the top-level COPYRIGHT file for details.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
||||||
|
|
||||||
.. _monitoring:
|
|
||||||
|
|
||||||
==========
|
|
||||||
Monitoring
|
|
||||||
==========
|
|
||||||
|
|
||||||
You can use a `spack monitor <https://github.com/spack/spack-monitor>`_ "Spackmon"
|
|
||||||
server to store a database of your packages, builds, and associated metadata
|
|
||||||
for provenance, research, or some other kind of development. You should
|
|
||||||
follow the instructions in the `spack monitor documentation <https://spack-monitor.readthedocs.org>`_
|
|
||||||
to first create a server along with a username and token for yourself.
|
|
||||||
You can then use this guide to interact with the server.
|
|
||||||
|
|
||||||
-------------------
|
|
||||||
Analysis Monitoring
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
To read about how to monitor an analysis (meaning you want to send analysis results
|
|
||||||
to a server) see :ref:`analyze_monitoring`.
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
Monitoring An Install
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Since an install is typically when you build packages, we logically want
|
|
||||||
to tell spack to monitor during this step. Let's start with an example
|
|
||||||
where we want to monitor the install of hdf5. Unless you have disabled authentication
|
|
||||||
for the server, we first want to export our spack monitor token and username to the environment:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ export SPACKMON_TOKEN=50445263afd8f67e59bd79bff597836ee6c05438
|
|
||||||
$ export SPACKMON_USER=spacky
|
|
||||||
|
|
||||||
|
|
||||||
By default, the host for your server is expected to be at ``http://127.0.0.1``
|
|
||||||
with a prefix of ``ms1``, and if this is the case, you can simply add the
|
|
||||||
``--monitor`` flag to the install command:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack install --monitor hdf5
|
|
||||||
|
|
||||||
|
|
||||||
If you need to customize the host or the prefix, you can do that as well:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack install --monitor --monitor-prefix monitor --monitor-host https://monitor-service.io hdf5
|
|
||||||
|
|
||||||
|
|
||||||
As a precaution, we cut out early in the spack client if you have not provided
|
|
||||||
authentication credentials. For example, if you run the command above without
|
|
||||||
exporting your username or token, you'll see:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
==> Error: You are required to export SPACKMON_TOKEN and SPACKMON_USER
|
|
||||||
|
|
||||||
This extra check is to ensure that we don't start any builds,
|
|
||||||
and then discover that you forgot to export your token. However, if
|
|
||||||
your monitoring server has authentication disabled, you can tell this to
|
|
||||||
the client to skip this step:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack install --monitor --monitor-disable-auth hdf5
|
|
||||||
|
|
||||||
If the service is not running, you'll cleanly exit early - the install will
|
|
||||||
not continue if you've asked it to monitor and there is no service.
|
|
||||||
For example, here is what you'll see if the monitoring service is not running:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
[Errno 111] Connection refused
|
|
||||||
|
|
||||||
|
|
||||||
If you want to continue builds (and stop monitoring) you can set the ``--monitor-keep-going``
|
|
||||||
flag.
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack install --monitor --monitor-keep-going hdf5
|
|
||||||
|
|
||||||
This could mean that if a request fails, you only have partial or no data
|
|
||||||
added to your monitoring database. This setting will not be applied to the
|
|
||||||
first request to check if the server is running, but to subsequent requests.
|
|
||||||
If you don't have a monitor server running and you want to build, simply
|
|
||||||
don't provide the ``--monitor`` flag! Finally, if you want to provide one or
|
|
||||||
more tags to your build, you can do:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
# Add one tag, "pizza"
|
|
||||||
$ spack install --monitor --monitor-tags pizza hdf5
|
|
||||||
|
|
||||||
# Add two tags, "pizza" and "pasta"
|
|
||||||
$ spack install --monitor --monitor-tags pizza,pasta hdf5
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------
|
|
||||||
Monitoring with Containerize
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
The same argument group is available to add to a containerize command.
|
|
||||||
|
|
||||||
^^^^^^
|
|
||||||
Docker
|
|
||||||
^^^^^^
|
|
||||||
|
|
||||||
To add monitoring to a Docker container recipe generation using the defaults,
|
|
||||||
and assuming a monitor server running on localhost, you would
|
|
||||||
start with a spack.yaml in your present working directory:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
spack:
|
|
||||||
specs:
|
|
||||||
- samtools
|
|
||||||
|
|
||||||
And then do:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
# preview first
|
|
||||||
spack containerize --monitor
|
|
||||||
|
|
||||||
# and then write to a Dockerfile
|
|
||||||
spack containerize --monitor > Dockerfile
|
|
||||||
|
|
||||||
|
|
||||||
The install command will be edited to include commands for enabling monitoring.
|
|
||||||
However, getting secrets into the container for your monitor server is something
|
|
||||||
that should be done carefully. Specifically you should:
|
|
||||||
|
|
||||||
- Never try to define secrets as ENV, ARG, or using ``--build-arg``
|
|
||||||
- Do not try to get the secret into the container via a "temporary" file that you remove (it in fact will still exist in a layer)
|
|
||||||
|
|
||||||
Instead, it's recommended to use buildkit `as explained here <https://pythonspeed.com/articles/docker-build-secrets/>`_.
|
|
||||||
You'll need to again export environment variables for your spack monitor server:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ export SPACKMON_TOKEN=50445263afd8f67e59bd79bff597836ee6c05438
|
|
||||||
$ export SPACKMON_USER=spacky
|
|
||||||
|
|
||||||
And then use buildkit along with your build and identifying the name of the secret:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ DOCKER_BUILDKIT=1 docker build --secret id=st,env=SPACKMON_TOKEN --secret id=su,env=SPACKMON_USER -t spack/container .
|
|
||||||
|
|
||||||
The secrets are expected to come from your environment, and then will be temporarily mounted and available
|
|
||||||
at ``/run/secrets/<name>``. If you forget to supply them (and authentication is required) the build
|
|
||||||
will fail. If you need to build on your host (and interact with a spack monitor at localhost) you'll
|
|
||||||
need to tell Docker to use the host network:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ DOCKER_BUILDKIT=1 docker build --network="host" --secret id=st,env=SPACKMON_TOKEN --secret id=su,env=SPACKMON_USER -t spack/container .
|
|
||||||
|
|
||||||
|
|
||||||
^^^^^^^^^^^
|
|
||||||
Singularity
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
To add monitoring to a Singularity container build, the spack.yaml needs to
|
|
||||||
be modified slightly to specify wanting a different format:
|
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
spack:
|
|
||||||
specs:
|
|
||||||
- samtools
|
|
||||||
container:
|
|
||||||
format: singularity
|
|
||||||
|
|
||||||
|
|
||||||
Again, generate the recipe:
|
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
# preview first
|
|
||||||
$ spack containerize --monitor
|
|
||||||
|
|
||||||
# then write to a Singularity recipe
|
|
||||||
$ spack containerize --monitor > Singularity
|
|
||||||
|
|
||||||
|
|
||||||
Singularity doesn't have a direct way to define secrets at build time, so we have
|
|
||||||
to do a bit of a manual command to add a file, source secrets in it, and remove it.
|
|
||||||
Since Singularity doesn't have layers like Docker, deleting a file will truly
|
|
||||||
remove it from the container and history. So let's say we have this file,
|
|
||||||
``secrets.sh``:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
# secrets.sh
|
|
||||||
export SPACKMON_USER=spack
|
|
||||||
export SPACKMON_TOKEN=50445263afd8f67e59bd79bff597836ee6c05438
|
|
||||||
|
|
||||||
|
|
||||||
We would then generate the Singularity recipe, and add a files section,
|
|
||||||
a source of that file at the start of ``%post``, and **importantly**
|
|
||||||
a removal of the final at the end of that same section.
|
|
||||||
|
|
||||||
.. code-block::
|
|
||||||
|
|
||||||
Bootstrap: docker
|
|
||||||
From: spack/ubuntu-bionic:latest
|
|
||||||
Stage: build
|
|
||||||
|
|
||||||
%files
|
|
||||||
secrets.sh /opt/secrets.sh
|
|
||||||
|
|
||||||
%post
|
|
||||||
. /opt/secrets.sh
|
|
||||||
|
|
||||||
# spack install commands are here
|
|
||||||
...
|
|
||||||
|
|
||||||
# Don't forget to remove here!
|
|
||||||
rm /opt/secrets.sh
|
|
||||||
|
|
||||||
|
|
||||||
You can then build the container as your normally would.
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ sudo singularity build container.sif Singularity
|
|
||||||
|
|
||||||
|
|
||||||
------------------
|
|
||||||
Monitoring Offline
|
|
||||||
------------------
|
|
||||||
|
|
||||||
In the case that you want to save monitor results to your filesystem
|
|
||||||
and then upload them later (perhaps you are in an environment where you don't
|
|
||||||
have credentials or it isn't safe to use them) you can use the ``--monitor-save-local``
|
|
||||||
flag.
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack install --monitor --monitor-save-local hdf5
|
|
||||||
|
|
||||||
This will save results in a subfolder, "monitor" in your designated spack
|
|
||||||
reports folder, which defaults to ``$HOME/.spack/reports/monitor``. When
|
|
||||||
you are ready to upload them to a spack monitor server:
|
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ spack monitor upload ~/.spack/reports/monitor
|
|
||||||
|
|
||||||
|
|
||||||
You can choose the root directory of results as shown above, or a specific
|
|
||||||
subdirectory. The command accepts other arguments to specify configuration
|
|
||||||
for the monitor.
|
|
@@ -34,6 +34,15 @@ ubiquitous in the scientific software community. Second, it's a modern
|
|||||||
language and has many powerful features to help make package writing
|
language and has many powerful features to help make package writing
|
||||||
easy.
|
easy.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
As a general rule, packages should install the software *from source*.
|
||||||
|
The only exception is for proprietary software (e.g., vendor compilers).
|
||||||
|
|
||||||
|
If a special build system needs to be added in order to support building
|
||||||
|
a package from source, then the associated code and recipe need to be added
|
||||||
|
first.
|
||||||
|
|
||||||
|
|
||||||
.. _installation_procedure:
|
.. _installation_procedure:
|
||||||
|
|
||||||
@@ -2397,13 +2406,15 @@ this because uninstalling the dependency would break the package.
|
|||||||
|
|
||||||
``build``, ``link``, and ``run`` dependencies all affect the hash of Spack
|
``build``, ``link``, and ``run`` dependencies all affect the hash of Spack
|
||||||
packages (along with ``sha256`` sums of patches and archives used to build the
|
packages (along with ``sha256`` sums of patches and archives used to build the
|
||||||
package, and a [canonical hash](https://github.com/spack/spack/pull/28156) of
|
package, and a `canonical hash <https://github.com/spack/spack/pull/28156>`_ of
|
||||||
the ``package.py`` recipes). ``test`` dependencies do not affect the package
|
the ``package.py`` recipes). ``test`` dependencies do not affect the package
|
||||||
hash, as they are only used to construct a test environment *after* building and
|
hash, as they are only used to construct a test environment *after* building and
|
||||||
installing a given package installation. Older versions of Spack did not include
|
installing a given package installation. Older versions of Spack did not include
|
||||||
build dependencies in the hash, but this has been
|
build dependencies in the hash, but this has been
|
||||||
[fixed](https://github.com/spack/spack/pull/28504) as of [Spack
|
`fixed <https://github.com/spack/spack/pull/28504>`_ as of |Spack v0.18|_.
|
||||||
``v0.18``](https://github.com/spack/spack/releases/tag/v0.18.0)
|
|
||||||
|
.. |Spack v0.18| replace:: Spack ``v0.18``
|
||||||
|
.. _Spack v0.18: https://github.com/spack/spack/releases/tag/v0.18.0
|
||||||
|
|
||||||
If the dependency type is not specified, Spack uses a default of
|
If the dependency type is not specified, Spack uses a default of
|
||||||
``('build', 'link')``. This is the common case for compiler languages.
|
``('build', 'link')``. This is the common case for compiler languages.
|
||||||
@@ -2634,9 +2645,12 @@ extendable package:
|
|||||||
extends('python')
|
extends('python')
|
||||||
...
|
...
|
||||||
|
|
||||||
Now, the ``py-numpy`` package can be used as an argument to ``spack
|
This accomplishes a few things. Firstly, the Python package can set special
|
||||||
activate``. When it is activated, all the files in its prefix will be
|
variables such as ``PYTHONPATH`` for all extensions when the run or build
|
||||||
symbolically linked into the prefix of the python package.
|
environment is set up. Secondly, filesystem views can ensure that extensions
|
||||||
|
are put in the same prefix as their extendee. This ensures that Python in
|
||||||
|
a view can always locate its Python packages, even without environment
|
||||||
|
variables set.
|
||||||
|
|
||||||
A package can only extend one other package at a time. To support packages
|
A package can only extend one other package at a time. To support packages
|
||||||
that may extend one of a list of other packages, Spack supports multiple
|
that may extend one of a list of other packages, Spack supports multiple
|
||||||
@@ -2684,9 +2698,8 @@ variant(s) are selected. This may be accomplished with conditional
|
|||||||
...
|
...
|
||||||
|
|
||||||
Sometimes, certain files in one package will conflict with those in
|
Sometimes, certain files in one package will conflict with those in
|
||||||
another, which means they cannot both be activated (symlinked) at the
|
another, which means they cannot both be used in a view at the
|
||||||
same time. In this case, you can tell Spack to ignore those files
|
same time. In this case, you can tell Spack to ignore those files:
|
||||||
when it does the activation:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -2698,7 +2711,7 @@ when it does the activation:
|
|||||||
...
|
...
|
||||||
|
|
||||||
The code above will prevent everything in the ``$prefix/bin/`` directory
|
The code above will prevent everything in the ``$prefix/bin/`` directory
|
||||||
from being linked in at activation time.
|
from being linked in a view.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@@ -2722,67 +2735,6 @@ extensions; as a consequence python extension packages (those inheriting from
|
|||||||
``PythonPackage``) likewise override ``add_files_to_view`` in order to rewrite
|
``PythonPackage``) likewise override ``add_files_to_view`` in order to rewrite
|
||||||
shebang lines which point to the Python interpreter.
|
shebang lines which point to the Python interpreter.
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
Activation & deactivation
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Adding an extension to a view is referred to as an activation. If the view is
|
|
||||||
maintained in the Spack installation prefix of the extendee this is called a
|
|
||||||
global activation. Activations may involve updating some centralized state
|
|
||||||
that is maintained by the extendee package, so there can be additional work
|
|
||||||
for adding extensions compared with non-extension packages.
|
|
||||||
|
|
||||||
Spack's ``Package`` class has default ``activate`` and ``deactivate``
|
|
||||||
implementations that handle symbolically linking extensions' prefixes
|
|
||||||
into a specified view. Extendable packages can override these methods
|
|
||||||
to add custom activate/deactivate logic of their own. For example,
|
|
||||||
the ``activate`` and ``deactivate`` methods in the Python class handle
|
|
||||||
symbolic linking of extensions, but they also handle details surrounding
|
|
||||||
Python's ``.pth`` files, and other aspects of Python packaging.
|
|
||||||
|
|
||||||
Spack's extensions mechanism is designed to be extensible, so that
|
|
||||||
other packages (like Ruby, R, Perl, etc.) can provide their own
|
|
||||||
custom extension management logic, as they may not handle modules the
|
|
||||||
same way that Python does.
|
|
||||||
|
|
||||||
Let's look at Python's activate function:
|
|
||||||
|
|
||||||
.. literalinclude:: _spack_root/var/spack/repos/builtin/packages/python/package.py
|
|
||||||
:pyobject: Python.activate
|
|
||||||
:linenos:
|
|
||||||
|
|
||||||
This function is called on the *extendee* (Python). It first calls
|
|
||||||
``activate`` in the superclass, which handles symlinking the
|
|
||||||
extension package's prefix into the specified view. It then does
|
|
||||||
some special handling of the ``easy-install.pth`` file, part of
|
|
||||||
Python's setuptools.
|
|
||||||
|
|
||||||
Deactivate behaves similarly to activate, but it unlinks files:
|
|
||||||
|
|
||||||
.. literalinclude:: _spack_root/var/spack/repos/builtin/packages/python/package.py
|
|
||||||
:pyobject: Python.deactivate
|
|
||||||
:linenos:
|
|
||||||
|
|
||||||
Both of these methods call some custom functions in the Python
|
|
||||||
package. See the source for Spack's Python package for details.
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
|
||||||
Activation arguments
|
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
You may have noticed that the ``activate`` function defined above
|
|
||||||
takes keyword arguments. These are the keyword arguments from
|
|
||||||
``extends()``, and they are passed to both activate and deactivate.
|
|
||||||
|
|
||||||
This capability allows an extension to customize its own activation by
|
|
||||||
passing arguments to the extendee. Extendees can likewise implement
|
|
||||||
custom ``activate()`` and ``deactivate()`` functions to suit their
|
|
||||||
needs.
|
|
||||||
|
|
||||||
The only keyword argument supported by default is the ``ignore``
|
|
||||||
argument, which can take a regex, list of regexes, or a predicate to
|
|
||||||
determine which files *not* to symlink during activation.
|
|
||||||
|
|
||||||
.. _virtual-dependencies:
|
.. _virtual-dependencies:
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
@@ -3584,7 +3536,7 @@ will likely contain some overriding of default builder methods:
|
|||||||
def cmake_args(self):
|
def cmake_args(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Autotoolsbuilder(spack.build_systems.autotools.AutotoolsBuilder):
|
class AutotoolsBuilder(spack.build_systems.autotools.AutotoolsBuilder):
|
||||||
def configure_args(self):
|
def configure_args(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -3652,6 +3604,70 @@ In the example above ``Cp2k`` inherits all the conflicts and variants that ``Cud
|
|||||||
|
|
||||||
.. _install-environment:
|
.. _install-environment:
|
||||||
|
|
||||||
|
--------------------------------
|
||||||
|
Package Inheritance
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Spack packages are Python classes, and you can use inheritance with them just as you can
|
||||||
|
with any Python class. This is common when you have your own package :ref:`repository
|
||||||
|
<repositories>` with packages that extend Spack's ``builtin`` packages.
|
||||||
|
|
||||||
|
You can extend a ``builtin`` package like this:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from spack.pkg.builtin.mpich import Mpich
|
||||||
|
|
||||||
|
class MyPackage(Mpich):
|
||||||
|
version("1.0", "0209444070d9c8af9b62c94095a217e3bc6843692d1e3fdc1ff5371e03aac47c")
|
||||||
|
version("2.0", "5dda192154047d6296ba14a4ab2d869c6926fd7f44dce8ce94f63aae2e359c5b")
|
||||||
|
|
||||||
|
Every repository registered with Spack ends up in a submodule of ``spack.pkg`` with a
|
||||||
|
name corresponding to its :ref:`namespace <namespaces>`. So, if you have a different
|
||||||
|
repository with namespace ``myrepo`` you want to import packages from , you might write:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from spack.pkg.myrepo.my_package import MyPackage
|
||||||
|
|
||||||
|
class NewPackage(MyPackage):
|
||||||
|
version("3.0", "08721a102fefcea2ae4add8c9cc548df77e9224f5385ad0872a9150fdd26a415")
|
||||||
|
version("4.0", "9cc39dd33dd4227bb82301d285437588d705290846d22ab6b8791c7e631ce385")
|
||||||
|
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
``disinherit``
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When you inherit from a package in Spack, you inherit all the metadata from its
|
||||||
|
directives, including ``version``, ``provides``, ``depends_on``, ``conflicts``, etc. For
|
||||||
|
example, ``NewPackage`` above will have four versions: ``1.0`` and ``2.0`` inherited
|
||||||
|
from ``MyPackage``, as well as, ``3.0``, and ``4.0`` defined in ``NewPackage``.
|
||||||
|
|
||||||
|
If you do not want your package to define all the same things as its base class, you can
|
||||||
|
use the ``disinherit`` directive to start fresh in your subclass:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from spack.pkg.myrepo.my_package import MyPackage
|
||||||
|
|
||||||
|
class NewerPackage(MyPackage):
|
||||||
|
disinherit("versions") # don't inherit any versions from MyPackage
|
||||||
|
version("5.0", "08721a102fefcea2ae4add8c9cc548df77e9224f5385ad0872a9150fdd26a415")
|
||||||
|
version("6.0", "9cc39dd33dd4227bb82301d285437588d705290846d22ab6b8791c7e631ce385")
|
||||||
|
|
||||||
|
Now, ``NewerPackage`` will have **only** versions ``5.0`` and ``6.0``, and will not
|
||||||
|
inherit ``1.0`` or ``2.0`` from ``MyPackage``. You can ``disinherit`` many different
|
||||||
|
properties from base packages. The full list of options is:
|
||||||
|
|
||||||
|
* ``conflicts``
|
||||||
|
* ``dependencies``
|
||||||
|
* ``extendees``
|
||||||
|
* ``patches``
|
||||||
|
* ``provided``
|
||||||
|
* ``resources``
|
||||||
|
* ``variants``
|
||||||
|
* ``versions``
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
The build environment
|
The build environment
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@@ -184,13 +184,48 @@ simply run the following commands:
|
|||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ spack env activate myenv
|
$ spack env activate myenv
|
||||||
$ spack concretize --force
|
$ spack concretize --fresh --force
|
||||||
$ spack install
|
$ spack install
|
||||||
|
|
||||||
The ``--force`` flag tells Spack to overwrite its previous concretization
|
The ``--fresh`` flag tells Spack to use the latest version of every package
|
||||||
decisions, allowing you to choose a new version of Python. If any of the new
|
where possible instead of trying to optimize for reuse of existing installed
|
||||||
packages like Bash are already installed, ``spack install`` won't re-install
|
packages.
|
||||||
them, it will keep the symlinks in place.
|
|
||||||
|
The ``--force`` flag in addition tells Spack to overwrite its previous
|
||||||
|
concretization decisions, allowing you to choose a new version of Python.
|
||||||
|
If any of the new packages like Bash are already installed, ``spack install``
|
||||||
|
won't re-install them, it will keep the symlinks in place.
|
||||||
|
|
||||||
|
-----------------------------------
|
||||||
|
Updating & Cleaning Up Old Packages
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
If you're looking to mimic the behavior of Homebrew, you may also want to
|
||||||
|
clean up out-of-date packages from your environment after an upgrade. To
|
||||||
|
upgrade your entire software stack within an environment and clean up old
|
||||||
|
package versions, simply run the following commands:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ spack env activate myenv
|
||||||
|
$ spack mark -i --all
|
||||||
|
$ spack concretize --fresh --force
|
||||||
|
$ spack install
|
||||||
|
$ spack gc
|
||||||
|
|
||||||
|
Running ``spack mark -i --all`` tells Spack to mark all of the existing
|
||||||
|
packages within an environment as "implicitly" installed. This tells
|
||||||
|
spack's garbage collection system that these packages should be cleaned up.
|
||||||
|
|
||||||
|
Don't worry however, this will not remove your entire environment.
|
||||||
|
Running ``spack install`` will reexamine your spack environment after
|
||||||
|
a fresh concretization and will re-mark any packages that should remain
|
||||||
|
installed as "explicitly" installed.
|
||||||
|
|
||||||
|
**Note:** if you use multiple spack environments you should re-run ``spack install``
|
||||||
|
in each of your environments prior to running ``spack gc`` to prevent spack
|
||||||
|
from uninstalling any shared packages that are no longer required by the
|
||||||
|
environment you just upgraded.
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
Uninstallation
|
Uninstallation
|
||||||
|
@@ -91,6 +91,8 @@ packages and use the first valid file:
|
|||||||
to eventually support URLs in ``repos.yaml``, so that you can easily
|
to eventually support URLs in ``repos.yaml``, so that you can easily
|
||||||
point to remote package repositories, but that is not yet implemented.
|
point to remote package repositories, but that is not yet implemented.
|
||||||
|
|
||||||
|
.. _namespaces:
|
||||||
|
|
||||||
---------------------
|
---------------------
|
||||||
Namespaces
|
Namespaces
|
||||||
---------------------
|
---------------------
|
||||||
@@ -426,36 +428,3 @@ By path:
|
|||||||
$ spack repo list
|
$ spack repo list
|
||||||
==> 1 package repository.
|
==> 1 package repository.
|
||||||
builtin ~/spack/var/spack/repos/builtin
|
builtin ~/spack/var/spack/repos/builtin
|
||||||
|
|
||||||
--------------------------------
|
|
||||||
Repo namespaces and Python
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
You may have noticed that namespace notation for repositories is similar
|
|
||||||
to the notation for namespaces in Python. As it turns out, you *can*
|
|
||||||
treat Spack repositories like Python packages; this is how they are
|
|
||||||
implemented.
|
|
||||||
|
|
||||||
You could, for example, extend a ``builtin`` package in your own
|
|
||||||
repository:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from spack.pkg.builtin.mpich import Mpich
|
|
||||||
|
|
||||||
class MyPackage(Mpich):
|
|
||||||
...
|
|
||||||
|
|
||||||
Spack repo namespaces are actually Python namespaces tacked on under
|
|
||||||
``spack.pkg``. The search semantics of ``repos.yaml`` are actually
|
|
||||||
implemented using Python's built-in `sys.path
|
|
||||||
<https://docs.python.org/2/library/sys.html#sys.path>`_ search. The
|
|
||||||
:py:mod:`spack.repo` module implements a custom `Python importer
|
|
||||||
<https://docs.python.org/2/library/imp.html>`_.
|
|
||||||
|
|
||||||
.. warning::
|
|
||||||
|
|
||||||
The mechanism for extending packages is not yet extensively tested,
|
|
||||||
and extending packages across repositories imposes inter-repo
|
|
||||||
dependencies, which may be hard to manage. Use this feature at your
|
|
||||||
own risk, but let us know if you have a use case for it.
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
Name, Supported Versions, Notes, Requirement Reason
|
Name, Supported Versions, Notes, Requirement Reason
|
||||||
Python, 2.7/3.6-3.11, , Interpreter for Spack
|
Python, 3.6--3.11, , Interpreter for Spack
|
||||||
C/C++ Compilers, , , Building software
|
C/C++ Compilers, , , Building software
|
||||||
make, , , Build software
|
make, , , Build software
|
||||||
patch, , , Build software
|
patch, , , Build software
|
||||||
|
|
41
lib/spack/env/cc
vendored
41
lib/spack/env/cc
vendored
@@ -440,6 +440,47 @@ while [ $# -ne 0 ]; do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "${SPACK_COMPILER_FLAGS_KEEP}" ] ; then
|
||||||
|
# NOTE: the eval is required to allow `|` alternatives inside the variable
|
||||||
|
eval "\
|
||||||
|
case \"\$1\" in
|
||||||
|
$SPACK_COMPILER_FLAGS_KEEP)
|
||||||
|
append other_args_list \"\$1\"
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
# the replace list is a space-separated list of pipe-separated pairs,
|
||||||
|
# the first in each pair is the original prefix to be matched, the
|
||||||
|
# second is the replacement prefix
|
||||||
|
if [ -n "${SPACK_COMPILER_FLAGS_REPLACE}" ] ; then
|
||||||
|
for rep in ${SPACK_COMPILER_FLAGS_REPLACE} ; do
|
||||||
|
before=${rep%|*}
|
||||||
|
after=${rep#*|}
|
||||||
|
eval "\
|
||||||
|
stripped=\"\${1##$before}\"
|
||||||
|
"
|
||||||
|
if [ "$stripped" = "$1" ] ; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
replaced="$after$stripped"
|
||||||
|
|
||||||
|
# it matched, remove it
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ -z "$replaced" ] ; then
|
||||||
|
# completely removed, continue OUTER loop
|
||||||
|
continue 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# re-build argument list with replacement
|
||||||
|
set -- "$replaced" "$@"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-isystem*)
|
-isystem*)
|
||||||
arg="${1#-isystem}"
|
arg="${1#-isystem}"
|
||||||
|
57
lib/spack/external/__init__.py
vendored
57
lib/spack/external/__init__.py
vendored
@@ -11,25 +11,14 @@
|
|||||||
|
|
||||||
* Homepage: https://altgraph.readthedocs.io/en/latest/index.html
|
* Homepage: https://altgraph.readthedocs.io/en/latest/index.html
|
||||||
* Usage: dependency of macholib
|
* Usage: dependency of macholib
|
||||||
* Version: 0.17.2
|
* Version: 0.17.3
|
||||||
|
|
||||||
archspec
|
archspec
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* Homepage: https://pypi.python.org/pypi/archspec
|
* Homepage: https://pypi.python.org/pypi/archspec
|
||||||
* Usage: Labeling, comparison and detection of microarchitectures
|
* Usage: Labeling, comparison and detection of microarchitectures
|
||||||
* Version: 0.2.0 (commit 77640e572725ad97f18e63a04857155752ace045)
|
* Version: 0.2.0 (commit e44bad9c7b6defac73696f64078b2fe634719b62)
|
||||||
|
|
||||||
argparse
|
|
||||||
--------
|
|
||||||
|
|
||||||
* Homepage: https://pypi.python.org/pypi/argparse
|
|
||||||
* Usage: We include our own version to be Python 3.X compatible.
|
|
||||||
* Version: 1.4.0
|
|
||||||
* Note: This package has been slightly modified to improve
|
|
||||||
error message formatting. See the following commit if the
|
|
||||||
vendored copy ever needs to be updated again:
|
|
||||||
https://github.com/spack/spack/pull/6786/commits/dfcef577b77249106ea4e4c69a6cd9e64fa6c418
|
|
||||||
|
|
||||||
astunparse
|
astunparse
|
||||||
----------------
|
----------------
|
||||||
@@ -52,7 +41,7 @@
|
|||||||
|
|
||||||
* Homepage: https://github.com/python-attrs/attrs
|
* Homepage: https://github.com/python-attrs/attrs
|
||||||
* Usage: Needed by jsonschema.
|
* Usage: Needed by jsonschema.
|
||||||
* Version: 21.2.0 (83d3cd70f90a3f4d19ee8b508e58d1c58821c0ad)
|
* Version: 22.1.0
|
||||||
|
|
||||||
ctest_log_parser
|
ctest_log_parser
|
||||||
----------------
|
----------------
|
||||||
@@ -67,21 +56,14 @@
|
|||||||
|
|
||||||
* Homepage: https://pypi.python.org/pypi/distro
|
* Homepage: https://pypi.python.org/pypi/distro
|
||||||
* Usage: Provides a more stable linux distribution detection.
|
* Usage: Provides a more stable linux distribution detection.
|
||||||
* Version: 1.6.0 (64946a1e2a9ff529047070657728600e006c99ff)
|
* Version: 1.8.0
|
||||||
* Note: Last version supporting Python 2.7
|
|
||||||
|
|
||||||
functools32
|
|
||||||
-----------
|
|
||||||
* Homepage: https://github.com/MiCHiLU/python-functools32
|
|
||||||
* Usage: Needed by jsonschema when using Python 2.7.
|
|
||||||
* Version: 3.2.3-2
|
|
||||||
|
|
||||||
jinja2
|
jinja2
|
||||||
------
|
------
|
||||||
|
|
||||||
* Homepage: https://pypi.python.org/pypi/Jinja2
|
* Homepage: https://pypi.python.org/pypi/Jinja2
|
||||||
* Usage: A modern and designer-friendly templating language for Python.
|
* Usage: A modern and designer-friendly templating language for Python.
|
||||||
* Version: 2.11.3 (last version supporting Python 2.7)
|
* Version: 3.0.3 (last version supporting Python 3.6)
|
||||||
|
|
||||||
jsonschema
|
jsonschema
|
||||||
----------
|
----------
|
||||||
@@ -96,44 +78,21 @@
|
|||||||
|
|
||||||
* Homepage: https://macholib.readthedocs.io/en/latest/index.html#
|
* Homepage: https://macholib.readthedocs.io/en/latest/index.html#
|
||||||
* Usage: Manipulation of Mach-o binaries for relocating macOS buildcaches on Linux
|
* Usage: Manipulation of Mach-o binaries for relocating macOS buildcaches on Linux
|
||||||
* Version: 1.15.2
|
* Version: 1.16.2
|
||||||
|
|
||||||
markupsafe
|
markupsafe
|
||||||
----------
|
----------
|
||||||
|
|
||||||
* Homepage: https://pypi.python.org/pypi/MarkupSafe
|
* Homepage: https://pypi.python.org/pypi/MarkupSafe
|
||||||
* Usage: Implements a XML/HTML/XHTML Markup safe string for Python.
|
* Usage: Implements a XML/HTML/XHTML Markup safe string for Python.
|
||||||
* Version: 1.1.1 (last version supporting Python 2.7)
|
* Version: 2.0.1 (last version supporting Python 3.6)
|
||||||
|
|
||||||
py
|
|
||||||
--
|
|
||||||
|
|
||||||
* Homepage: https://pypi.python.org/pypi/py
|
|
||||||
* Usage: Needed by pytest. Library with cross-python path,
|
|
||||||
ini-parsing, io, code, and log facilities.
|
|
||||||
* Version: 1.4.34 (last version supporting Python 2.6)
|
|
||||||
* Note: This packages has been modified:
|
|
||||||
* https://github.com/pytest-dev/py/pull/186 was backported
|
|
||||||
|
|
||||||
pyrsistent
|
pyrsistent
|
||||||
----------
|
----------
|
||||||
|
|
||||||
* Homepage: http://github.com/tobgu/pyrsistent/
|
* Homepage: http://github.com/tobgu/pyrsistent/
|
||||||
* Usage: Needed by `jsonschema`
|
* Usage: Needed by `jsonschema`
|
||||||
* Version: 0.16.1 (last version supporting Python 2.7)
|
* Version: 0.18.0
|
||||||
* Note: We only include the parts needed for `jsonschema`.
|
|
||||||
|
|
||||||
pytest
|
|
||||||
------
|
|
||||||
|
|
||||||
* Homepage: https://pypi.python.org/pypi/pytest
|
|
||||||
* Usage: Testing framework used by Spack.
|
|
||||||
* Version: 3.2.5 (last version supporting Python 2.6)
|
|
||||||
* Note: This package has been slightly modified:
|
|
||||||
* We improve Python 2.6 compatibility. See:
|
|
||||||
https://github.com/spack/spack/pull/6801.
|
|
||||||
* We have patched pytest not to depend on setuptools. See:
|
|
||||||
https://github.com/spack/spack/pull/15612
|
|
||||||
|
|
||||||
ruamel.yaml
|
ruamel.yaml
|
||||||
------
|
------
|
||||||
|
1
lib/spack/external/_vendoring/_pyrsistent_version.py
vendored
Normal file
1
lib/spack/external/_vendoring/_pyrsistent_version.py
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__version__ = '0.18.0'
|
1
lib/spack/external/_vendoring/_pyrsistent_version.pyi
vendored
Normal file
1
lib/spack/external/_vendoring/_pyrsistent_version.pyi
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from _pyrsistent_version import *
|
1
lib/spack/external/_vendoring/altgraph.pyi
vendored
Normal file
1
lib/spack/external/_vendoring/altgraph.pyi
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from altgraph import *
|
18
lib/spack/external/_vendoring/altgraph/LICENSE
vendored
Normal file
18
lib/spack/external/_vendoring/altgraph/LICENSE
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Copyright (c) 2004 Istvan Albert unless otherwise noted.
|
||||||
|
Copyright (c) 2006-2010 Bob Ippolito
|
||||||
|
Copyright (2) 2010-2020 Ronald Oussoren, et. al.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to
|
||||||
|
deal in the Software without restriction, including without limitation the
|
||||||
|
rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
IN THE SOFTWARE.
|
@@ -1,4 +1,5 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
from ._version_info import VersionInfo
|
from ._version_info import VersionInfo
|
||||||
|
|
||||||
|
|
||||||
__version__ = "21.2.0"
|
__version__ = "22.1.0"
|
||||||
__version_info__ = VersionInfo._from_version_string(__version__)
|
__version_info__ = VersionInfo._from_version_string(__version__)
|
||||||
|
|
||||||
__title__ = "attrs"
|
__title__ = "attrs"
|
||||||
@@ -73,6 +74,6 @@
|
|||||||
]
|
]
|
||||||
|
|
||||||
if sys.version_info[:2] >= (3, 6):
|
if sys.version_info[:2] >= (3, 6):
|
||||||
from ._next_gen import define, field, frozen, mutable
|
from ._next_gen import define, field, frozen, mutable # noqa: F401
|
||||||
|
|
||||||
__all__.extend((define, field, frozen, mutable))
|
__all__.extend(("define", "field", "frozen", "mutable"))
|
486
lib/spack/external/_vendoring/attr/__init__.pyi
vendored
Normal file
486
lib/spack/external/_vendoring/attr/__init__.pyi
vendored
Normal file
@@ -0,0 +1,486 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
from typing import (
|
||||||
|
Any,
|
||||||
|
Callable,
|
||||||
|
ClassVar,
|
||||||
|
Dict,
|
||||||
|
Generic,
|
||||||
|
List,
|
||||||
|
Mapping,
|
||||||
|
Optional,
|
||||||
|
Protocol,
|
||||||
|
Sequence,
|
||||||
|
Tuple,
|
||||||
|
Type,
|
||||||
|
TypeVar,
|
||||||
|
Union,
|
||||||
|
overload,
|
||||||
|
)
|
||||||
|
|
||||||
|
# `import X as X` is required to make these public
|
||||||
|
from . import converters as converters
|
||||||
|
from . import exceptions as exceptions
|
||||||
|
from . import filters as filters
|
||||||
|
from . import setters as setters
|
||||||
|
from . import validators as validators
|
||||||
|
from ._cmp import cmp_using as cmp_using
|
||||||
|
from ._version_info import VersionInfo
|
||||||
|
|
||||||
|
__version__: str
|
||||||
|
__version_info__: VersionInfo
|
||||||
|
__title__: str
|
||||||
|
__description__: str
|
||||||
|
__url__: str
|
||||||
|
__uri__: str
|
||||||
|
__author__: str
|
||||||
|
__email__: str
|
||||||
|
__license__: str
|
||||||
|
__copyright__: str
|
||||||
|
|
||||||
|
_T = TypeVar("_T")
|
||||||
|
_C = TypeVar("_C", bound=type)
|
||||||
|
|
||||||
|
_EqOrderType = Union[bool, Callable[[Any], Any]]
|
||||||
|
_ValidatorType = Callable[[Any, Attribute[_T], _T], Any]
|
||||||
|
_ConverterType = Callable[[Any], Any]
|
||||||
|
_FilterType = Callable[[Attribute[_T], _T], bool]
|
||||||
|
_ReprType = Callable[[Any], str]
|
||||||
|
_ReprArgType = Union[bool, _ReprType]
|
||||||
|
_OnSetAttrType = Callable[[Any, Attribute[Any], Any], Any]
|
||||||
|
_OnSetAttrArgType = Union[
|
||||||
|
_OnSetAttrType, List[_OnSetAttrType], setters._NoOpType
|
||||||
|
]
|
||||||
|
_FieldTransformer = Callable[
|
||||||
|
[type, List[Attribute[Any]]], List[Attribute[Any]]
|
||||||
|
]
|
||||||
|
# FIXME: in reality, if multiple validators are passed they must be in a list
|
||||||
|
# or tuple, but those are invariant and so would prevent subtypes of
|
||||||
|
# _ValidatorType from working when passed in a list or tuple.
|
||||||
|
_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]]
|
||||||
|
|
||||||
|
# A protocol to be able to statically accept an attrs class.
|
||||||
|
class AttrsInstance(Protocol):
|
||||||
|
__attrs_attrs__: ClassVar[Any]
|
||||||
|
|
||||||
|
# _make --
|
||||||
|
|
||||||
|
NOTHING: object
|
||||||
|
|
||||||
|
# NOTE: Factory lies about its return type to make this possible:
|
||||||
|
# `x: List[int] # = Factory(list)`
|
||||||
|
# Work around mypy issue #4554 in the common case by using an overload.
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
from typing import Literal
|
||||||
|
@overload
|
||||||
|
def Factory(factory: Callable[[], _T]) -> _T: ...
|
||||||
|
@overload
|
||||||
|
def Factory(
|
||||||
|
factory: Callable[[Any], _T],
|
||||||
|
takes_self: Literal[True],
|
||||||
|
) -> _T: ...
|
||||||
|
@overload
|
||||||
|
def Factory(
|
||||||
|
factory: Callable[[], _T],
|
||||||
|
takes_self: Literal[False],
|
||||||
|
) -> _T: ...
|
||||||
|
|
||||||
|
else:
|
||||||
|
@overload
|
||||||
|
def Factory(factory: Callable[[], _T]) -> _T: ...
|
||||||
|
@overload
|
||||||
|
def Factory(
|
||||||
|
factory: Union[Callable[[Any], _T], Callable[[], _T]],
|
||||||
|
takes_self: bool = ...,
|
||||||
|
) -> _T: ...
|
||||||
|
|
||||||
|
# Static type inference support via __dataclass_transform__ implemented as per:
|
||||||
|
# https://github.com/microsoft/pyright/blob/1.1.135/specs/dataclass_transforms.md
|
||||||
|
# This annotation must be applied to all overloads of "define" and "attrs"
|
||||||
|
#
|
||||||
|
# NOTE: This is a typing construct and does not exist at runtime. Extensions
|
||||||
|
# wrapping attrs decorators should declare a separate __dataclass_transform__
|
||||||
|
# signature in the extension module using the specification linked above to
|
||||||
|
# provide pyright support.
|
||||||
|
def __dataclass_transform__(
|
||||||
|
*,
|
||||||
|
eq_default: bool = True,
|
||||||
|
order_default: bool = False,
|
||||||
|
kw_only_default: bool = False,
|
||||||
|
field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()),
|
||||||
|
) -> Callable[[_T], _T]: ...
|
||||||
|
|
||||||
|
class Attribute(Generic[_T]):
|
||||||
|
name: str
|
||||||
|
default: Optional[_T]
|
||||||
|
validator: Optional[_ValidatorType[_T]]
|
||||||
|
repr: _ReprArgType
|
||||||
|
cmp: _EqOrderType
|
||||||
|
eq: _EqOrderType
|
||||||
|
order: _EqOrderType
|
||||||
|
hash: Optional[bool]
|
||||||
|
init: bool
|
||||||
|
converter: Optional[_ConverterType]
|
||||||
|
metadata: Dict[Any, Any]
|
||||||
|
type: Optional[Type[_T]]
|
||||||
|
kw_only: bool
|
||||||
|
on_setattr: _OnSetAttrType
|
||||||
|
def evolve(self, **changes: Any) -> "Attribute[Any]": ...
|
||||||
|
|
||||||
|
# NOTE: We had several choices for the annotation to use for type arg:
|
||||||
|
# 1) Type[_T]
|
||||||
|
# - Pros: Handles simple cases correctly
|
||||||
|
# - Cons: Might produce less informative errors in the case of conflicting
|
||||||
|
# TypeVars e.g. `attr.ib(default='bad', type=int)`
|
||||||
|
# 2) Callable[..., _T]
|
||||||
|
# - Pros: Better error messages than #1 for conflicting TypeVars
|
||||||
|
# - Cons: Terrible error messages for validator checks.
|
||||||
|
# e.g. attr.ib(type=int, validator=validate_str)
|
||||||
|
# -> error: Cannot infer function type argument
|
||||||
|
# 3) type (and do all of the work in the mypy plugin)
|
||||||
|
# - Pros: Simple here, and we could customize the plugin with our own errors.
|
||||||
|
# - Cons: Would need to write mypy plugin code to handle all the cases.
|
||||||
|
# We chose option #1.
|
||||||
|
|
||||||
|
# `attr` lies about its return type to make the following possible:
|
||||||
|
# attr() -> Any
|
||||||
|
# attr(8) -> int
|
||||||
|
# attr(validator=<some callable>) -> Whatever the callable expects.
|
||||||
|
# This makes this type of assignments possible:
|
||||||
|
# x: int = attr(8)
|
||||||
|
#
|
||||||
|
# This form catches explicit None or no default but with no other arguments
|
||||||
|
# returns Any.
|
||||||
|
@overload
|
||||||
|
def attrib(
|
||||||
|
default: None = ...,
|
||||||
|
validator: None = ...,
|
||||||
|
repr: _ReprArgType = ...,
|
||||||
|
cmp: Optional[_EqOrderType] = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||||
|
type: None = ...,
|
||||||
|
converter: None = ...,
|
||||||
|
factory: None = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
) -> Any: ...
|
||||||
|
|
||||||
|
# This form catches an explicit None or no default and infers the type from the
|
||||||
|
# other arguments.
|
||||||
|
@overload
|
||||||
|
def attrib(
|
||||||
|
default: None = ...,
|
||||||
|
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||||
|
repr: _ReprArgType = ...,
|
||||||
|
cmp: Optional[_EqOrderType] = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||||
|
type: Optional[Type[_T]] = ...,
|
||||||
|
converter: Optional[_ConverterType] = ...,
|
||||||
|
factory: Optional[Callable[[], _T]] = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
) -> _T: ...
|
||||||
|
|
||||||
|
# This form catches an explicit default argument.
|
||||||
|
@overload
|
||||||
|
def attrib(
|
||||||
|
default: _T,
|
||||||
|
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||||
|
repr: _ReprArgType = ...,
|
||||||
|
cmp: Optional[_EqOrderType] = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||||
|
type: Optional[Type[_T]] = ...,
|
||||||
|
converter: Optional[_ConverterType] = ...,
|
||||||
|
factory: Optional[Callable[[], _T]] = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
) -> _T: ...
|
||||||
|
|
||||||
|
# This form covers type=non-Type: e.g. forward references (str), Any
|
||||||
|
@overload
|
||||||
|
def attrib(
|
||||||
|
default: Optional[_T] = ...,
|
||||||
|
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||||
|
repr: _ReprArgType = ...,
|
||||||
|
cmp: Optional[_EqOrderType] = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||||
|
type: object = ...,
|
||||||
|
converter: Optional[_ConverterType] = ...,
|
||||||
|
factory: Optional[Callable[[], _T]] = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
) -> Any: ...
|
||||||
|
@overload
|
||||||
|
def field(
|
||||||
|
*,
|
||||||
|
default: None = ...,
|
||||||
|
validator: None = ...,
|
||||||
|
repr: _ReprArgType = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||||
|
converter: None = ...,
|
||||||
|
factory: None = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
eq: Optional[bool] = ...,
|
||||||
|
order: Optional[bool] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
) -> Any: ...
|
||||||
|
|
||||||
|
# This form catches an explicit None or no default and infers the type from the
|
||||||
|
# other arguments.
|
||||||
|
@overload
|
||||||
|
def field(
|
||||||
|
*,
|
||||||
|
default: None = ...,
|
||||||
|
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||||
|
repr: _ReprArgType = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||||
|
converter: Optional[_ConverterType] = ...,
|
||||||
|
factory: Optional[Callable[[], _T]] = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
) -> _T: ...
|
||||||
|
|
||||||
|
# This form catches an explicit default argument.
|
||||||
|
@overload
|
||||||
|
def field(
|
||||||
|
*,
|
||||||
|
default: _T,
|
||||||
|
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||||
|
repr: _ReprArgType = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||||
|
converter: Optional[_ConverterType] = ...,
|
||||||
|
factory: Optional[Callable[[], _T]] = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
) -> _T: ...
|
||||||
|
|
||||||
|
# This form covers type=non-Type: e.g. forward references (str), Any
|
||||||
|
@overload
|
||||||
|
def field(
|
||||||
|
*,
|
||||||
|
default: Optional[_T] = ...,
|
||||||
|
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||||
|
repr: _ReprArgType = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||||
|
converter: Optional[_ConverterType] = ...,
|
||||||
|
factory: Optional[Callable[[], _T]] = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
) -> Any: ...
|
||||||
|
@overload
|
||||||
|
@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))
|
||||||
|
def attrs(
|
||||||
|
maybe_cls: _C,
|
||||||
|
these: Optional[Dict[str, Any]] = ...,
|
||||||
|
repr_ns: Optional[str] = ...,
|
||||||
|
repr: bool = ...,
|
||||||
|
cmp: Optional[_EqOrderType] = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
slots: bool = ...,
|
||||||
|
frozen: bool = ...,
|
||||||
|
weakref_slot: bool = ...,
|
||||||
|
str: bool = ...,
|
||||||
|
auto_attribs: bool = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
cache_hash: bool = ...,
|
||||||
|
auto_exc: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
auto_detect: bool = ...,
|
||||||
|
collect_by_mro: bool = ...,
|
||||||
|
getstate_setstate: Optional[bool] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
field_transformer: Optional[_FieldTransformer] = ...,
|
||||||
|
match_args: bool = ...,
|
||||||
|
) -> _C: ...
|
||||||
|
@overload
|
||||||
|
@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))
|
||||||
|
def attrs(
|
||||||
|
maybe_cls: None = ...,
|
||||||
|
these: Optional[Dict[str, Any]] = ...,
|
||||||
|
repr_ns: Optional[str] = ...,
|
||||||
|
repr: bool = ...,
|
||||||
|
cmp: Optional[_EqOrderType] = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
slots: bool = ...,
|
||||||
|
frozen: bool = ...,
|
||||||
|
weakref_slot: bool = ...,
|
||||||
|
str: bool = ...,
|
||||||
|
auto_attribs: bool = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
cache_hash: bool = ...,
|
||||||
|
auto_exc: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
auto_detect: bool = ...,
|
||||||
|
collect_by_mro: bool = ...,
|
||||||
|
getstate_setstate: Optional[bool] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
field_transformer: Optional[_FieldTransformer] = ...,
|
||||||
|
match_args: bool = ...,
|
||||||
|
) -> Callable[[_C], _C]: ...
|
||||||
|
@overload
|
||||||
|
@__dataclass_transform__(field_descriptors=(attrib, field))
|
||||||
|
def define(
|
||||||
|
maybe_cls: _C,
|
||||||
|
*,
|
||||||
|
these: Optional[Dict[str, Any]] = ...,
|
||||||
|
repr: bool = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
slots: bool = ...,
|
||||||
|
frozen: bool = ...,
|
||||||
|
weakref_slot: bool = ...,
|
||||||
|
str: bool = ...,
|
||||||
|
auto_attribs: bool = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
cache_hash: bool = ...,
|
||||||
|
auto_exc: bool = ...,
|
||||||
|
eq: Optional[bool] = ...,
|
||||||
|
order: Optional[bool] = ...,
|
||||||
|
auto_detect: bool = ...,
|
||||||
|
getstate_setstate: Optional[bool] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
field_transformer: Optional[_FieldTransformer] = ...,
|
||||||
|
match_args: bool = ...,
|
||||||
|
) -> _C: ...
|
||||||
|
@overload
|
||||||
|
@__dataclass_transform__(field_descriptors=(attrib, field))
|
||||||
|
def define(
|
||||||
|
maybe_cls: None = ...,
|
||||||
|
*,
|
||||||
|
these: Optional[Dict[str, Any]] = ...,
|
||||||
|
repr: bool = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
slots: bool = ...,
|
||||||
|
frozen: bool = ...,
|
||||||
|
weakref_slot: bool = ...,
|
||||||
|
str: bool = ...,
|
||||||
|
auto_attribs: bool = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
cache_hash: bool = ...,
|
||||||
|
auto_exc: bool = ...,
|
||||||
|
eq: Optional[bool] = ...,
|
||||||
|
order: Optional[bool] = ...,
|
||||||
|
auto_detect: bool = ...,
|
||||||
|
getstate_setstate: Optional[bool] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
field_transformer: Optional[_FieldTransformer] = ...,
|
||||||
|
match_args: bool = ...,
|
||||||
|
) -> Callable[[_C], _C]: ...
|
||||||
|
|
||||||
|
mutable = define
|
||||||
|
frozen = define # they differ only in their defaults
|
||||||
|
|
||||||
|
def fields(cls: Type[AttrsInstance]) -> Any: ...
|
||||||
|
def fields_dict(cls: Type[AttrsInstance]) -> Dict[str, Attribute[Any]]: ...
|
||||||
|
def validate(inst: AttrsInstance) -> None: ...
|
||||||
|
def resolve_types(
|
||||||
|
cls: _C,
|
||||||
|
globalns: Optional[Dict[str, Any]] = ...,
|
||||||
|
localns: Optional[Dict[str, Any]] = ...,
|
||||||
|
attribs: Optional[List[Attribute[Any]]] = ...,
|
||||||
|
) -> _C: ...
|
||||||
|
|
||||||
|
# TODO: add support for returning a proper attrs class from the mypy plugin
|
||||||
|
# we use Any instead of _CountingAttr so that e.g. `make_class('Foo',
|
||||||
|
# [attr.ib()])` is valid
|
||||||
|
def make_class(
|
||||||
|
name: str,
|
||||||
|
attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]],
|
||||||
|
bases: Tuple[type, ...] = ...,
|
||||||
|
repr_ns: Optional[str] = ...,
|
||||||
|
repr: bool = ...,
|
||||||
|
cmp: Optional[_EqOrderType] = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
slots: bool = ...,
|
||||||
|
frozen: bool = ...,
|
||||||
|
weakref_slot: bool = ...,
|
||||||
|
str: bool = ...,
|
||||||
|
auto_attribs: bool = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
cache_hash: bool = ...,
|
||||||
|
auto_exc: bool = ...,
|
||||||
|
eq: Optional[_EqOrderType] = ...,
|
||||||
|
order: Optional[_EqOrderType] = ...,
|
||||||
|
collect_by_mro: bool = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
field_transformer: Optional[_FieldTransformer] = ...,
|
||||||
|
) -> type: ...
|
||||||
|
|
||||||
|
# _funcs --
|
||||||
|
|
||||||
|
# TODO: add support for returning TypedDict from the mypy plugin
|
||||||
|
# FIXME: asdict/astuple do not honor their factory args. Waiting on one of
|
||||||
|
# these:
|
||||||
|
# https://github.com/python/mypy/issues/4236
|
||||||
|
# https://github.com/python/typing/issues/253
|
||||||
|
# XXX: remember to fix attrs.asdict/astuple too!
|
||||||
|
def asdict(
|
||||||
|
inst: AttrsInstance,
|
||||||
|
recurse: bool = ...,
|
||||||
|
filter: Optional[_FilterType[Any]] = ...,
|
||||||
|
dict_factory: Type[Mapping[Any, Any]] = ...,
|
||||||
|
retain_collection_types: bool = ...,
|
||||||
|
value_serializer: Optional[
|
||||||
|
Callable[[type, Attribute[Any], Any], Any]
|
||||||
|
] = ...,
|
||||||
|
tuple_keys: Optional[bool] = ...,
|
||||||
|
) -> Dict[str, Any]: ...
|
||||||
|
|
||||||
|
# TODO: add support for returning NamedTuple from the mypy plugin
|
||||||
|
def astuple(
|
||||||
|
inst: AttrsInstance,
|
||||||
|
recurse: bool = ...,
|
||||||
|
filter: Optional[_FilterType[Any]] = ...,
|
||||||
|
tuple_factory: Type[Sequence[Any]] = ...,
|
||||||
|
retain_collection_types: bool = ...,
|
||||||
|
) -> Tuple[Any, ...]: ...
|
||||||
|
def has(cls: type) -> bool: ...
|
||||||
|
def assoc(inst: _T, **changes: Any) -> _T: ...
|
||||||
|
def evolve(inst: _T, **changes: Any) -> _T: ...
|
||||||
|
|
||||||
|
# _config --
|
||||||
|
|
||||||
|
def set_run_validators(run: bool) -> None: ...
|
||||||
|
def get_run_validators() -> bool: ...
|
||||||
|
|
||||||
|
# aliases --
|
||||||
|
|
||||||
|
s = attributes = attrs
|
||||||
|
ib = attr = attrib
|
||||||
|
dataclass = attrs # Technically, partial(attrs, auto_attribs=True) ;)
|
@@ -1,8 +1,9 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
import types
|
||||||
|
|
||||||
from ._compat import new_class
|
|
||||||
from ._make import _make_ne
|
from ._make import _make_ne
|
||||||
|
|
||||||
|
|
||||||
@@ -78,7 +79,9 @@ def cmp_using(
|
|||||||
num_order_functions += 1
|
num_order_functions += 1
|
||||||
body["__ge__"] = _make_operator("ge", ge)
|
body["__ge__"] = _make_operator("ge", ge)
|
||||||
|
|
||||||
type_ = new_class(class_name, (object,), {}, lambda ns: ns.update(body))
|
type_ = types.new_class(
|
||||||
|
class_name, (object,), {}, lambda ns: ns.update(body)
|
||||||
|
)
|
||||||
|
|
||||||
# Add same type requirement.
|
# Add same type requirement.
|
||||||
if require_same_type:
|
if require_same_type:
|
13
lib/spack/external/_vendoring/attr/_cmp.pyi
vendored
Normal file
13
lib/spack/external/_vendoring/attr/_cmp.pyi
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from typing import Any, Callable, Optional, Type
|
||||||
|
|
||||||
|
_CompareWithType = Callable[[Any, Any], bool]
|
||||||
|
|
||||||
|
def cmp_using(
|
||||||
|
eq: Optional[_CompareWithType],
|
||||||
|
lt: Optional[_CompareWithType],
|
||||||
|
le: Optional[_CompareWithType],
|
||||||
|
gt: Optional[_CompareWithType],
|
||||||
|
ge: Optional[_CompareWithType],
|
||||||
|
require_same_type: bool,
|
||||||
|
class_name: str,
|
||||||
|
) -> Type: ...
|
185
lib/spack/external/_vendoring/attr/_compat.py
vendored
Normal file
185
lib/spack/external/_vendoring/attr/_compat.py
vendored
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
import platform
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
import types
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
from collections.abc import Mapping, Sequence # noqa
|
||||||
|
|
||||||
|
|
||||||
|
PYPY = platform.python_implementation() == "PyPy"
|
||||||
|
PY36 = sys.version_info[:2] >= (3, 6)
|
||||||
|
HAS_F_STRINGS = PY36
|
||||||
|
PY310 = sys.version_info[:2] >= (3, 10)
|
||||||
|
|
||||||
|
|
||||||
|
if PYPY or PY36:
|
||||||
|
ordered_dict = dict
|
||||||
|
else:
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
ordered_dict = OrderedDict
|
||||||
|
|
||||||
|
|
||||||
|
def just_warn(*args, **kw):
|
||||||
|
warnings.warn(
|
||||||
|
"Running interpreter doesn't sufficiently support code object "
|
||||||
|
"introspection. Some features like bare super() or accessing "
|
||||||
|
"__class__ will not work with slotted classes.",
|
||||||
|
RuntimeWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class _AnnotationExtractor:
|
||||||
|
"""
|
||||||
|
Extract type annotations from a callable, returning None whenever there
|
||||||
|
is none.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ["sig"]
|
||||||
|
|
||||||
|
def __init__(self, callable):
|
||||||
|
try:
|
||||||
|
self.sig = inspect.signature(callable)
|
||||||
|
except (ValueError, TypeError): # inspect failed
|
||||||
|
self.sig = None
|
||||||
|
|
||||||
|
def get_first_param_type(self):
|
||||||
|
"""
|
||||||
|
Return the type annotation of the first argument if it's not empty.
|
||||||
|
"""
|
||||||
|
if not self.sig:
|
||||||
|
return None
|
||||||
|
|
||||||
|
params = list(self.sig.parameters.values())
|
||||||
|
if params and params[0].annotation is not inspect.Parameter.empty:
|
||||||
|
return params[0].annotation
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_return_type(self):
|
||||||
|
"""
|
||||||
|
Return the return type if it's not empty.
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
self.sig
|
||||||
|
and self.sig.return_annotation is not inspect.Signature.empty
|
||||||
|
):
|
||||||
|
return self.sig.return_annotation
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def make_set_closure_cell():
|
||||||
|
"""Return a function of two arguments (cell, value) which sets
|
||||||
|
the value stored in the closure cell `cell` to `value`.
|
||||||
|
"""
|
||||||
|
# pypy makes this easy. (It also supports the logic below, but
|
||||||
|
# why not do the easy/fast thing?)
|
||||||
|
if PYPY:
|
||||||
|
|
||||||
|
def set_closure_cell(cell, value):
|
||||||
|
cell.__setstate__((value,))
|
||||||
|
|
||||||
|
return set_closure_cell
|
||||||
|
|
||||||
|
# Otherwise gotta do it the hard way.
|
||||||
|
|
||||||
|
# Create a function that will set its first cellvar to `value`.
|
||||||
|
def set_first_cellvar_to(value):
|
||||||
|
x = value
|
||||||
|
return
|
||||||
|
|
||||||
|
# This function will be eliminated as dead code, but
|
||||||
|
# not before its reference to `x` forces `x` to be
|
||||||
|
# represented as a closure cell rather than a local.
|
||||||
|
def force_x_to_be_a_cell(): # pragma: no cover
|
||||||
|
return x
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Extract the code object and make sure our assumptions about
|
||||||
|
# the closure behavior are correct.
|
||||||
|
co = set_first_cellvar_to.__code__
|
||||||
|
if co.co_cellvars != ("x",) or co.co_freevars != ():
|
||||||
|
raise AssertionError # pragma: no cover
|
||||||
|
|
||||||
|
# Convert this code object to a code object that sets the
|
||||||
|
# function's first _freevar_ (not cellvar) to the argument.
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
|
||||||
|
def set_closure_cell(cell, value):
|
||||||
|
cell.cell_contents = value
|
||||||
|
|
||||||
|
else:
|
||||||
|
args = [co.co_argcount]
|
||||||
|
args.append(co.co_kwonlyargcount)
|
||||||
|
args.extend(
|
||||||
|
[
|
||||||
|
co.co_nlocals,
|
||||||
|
co.co_stacksize,
|
||||||
|
co.co_flags,
|
||||||
|
co.co_code,
|
||||||
|
co.co_consts,
|
||||||
|
co.co_names,
|
||||||
|
co.co_varnames,
|
||||||
|
co.co_filename,
|
||||||
|
co.co_name,
|
||||||
|
co.co_firstlineno,
|
||||||
|
co.co_lnotab,
|
||||||
|
# These two arguments are reversed:
|
||||||
|
co.co_cellvars,
|
||||||
|
co.co_freevars,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
set_first_freevar_code = types.CodeType(*args)
|
||||||
|
|
||||||
|
def set_closure_cell(cell, value):
|
||||||
|
# Create a function using the set_first_freevar_code,
|
||||||
|
# whose first closure cell is `cell`. Calling it will
|
||||||
|
# change the value of that cell.
|
||||||
|
setter = types.FunctionType(
|
||||||
|
set_first_freevar_code, {}, "setter", (), (cell,)
|
||||||
|
)
|
||||||
|
# And call it to set the cell.
|
||||||
|
setter(value)
|
||||||
|
|
||||||
|
# Make sure it works on this interpreter:
|
||||||
|
def make_func_with_cell():
|
||||||
|
x = None
|
||||||
|
|
||||||
|
def func():
|
||||||
|
return x # pragma: no cover
|
||||||
|
|
||||||
|
return func
|
||||||
|
|
||||||
|
cell = make_func_with_cell().__closure__[0]
|
||||||
|
set_closure_cell(cell, 100)
|
||||||
|
if cell.cell_contents != 100:
|
||||||
|
raise AssertionError # pragma: no cover
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
return just_warn
|
||||||
|
else:
|
||||||
|
return set_closure_cell
|
||||||
|
|
||||||
|
|
||||||
|
set_closure_cell = make_set_closure_cell()
|
||||||
|
|
||||||
|
# Thread-local global to track attrs instances which are already being repr'd.
|
||||||
|
# This is needed because there is no other (thread-safe) way to pass info
|
||||||
|
# about the instances that are already being repr'd through the call stack
|
||||||
|
# in order to ensure we don't perform infinite recursion.
|
||||||
|
#
|
||||||
|
# For instance, if an instance contains a dict which contains that instance,
|
||||||
|
# we need to know that we're already repr'ing the outside instance from within
|
||||||
|
# the dict's repr() call.
|
||||||
|
#
|
||||||
|
# This lives here rather than in _make.py so that the functions in _make.py
|
||||||
|
# don't have a direct reference to the thread-local in their globals dict.
|
||||||
|
# If they have such a reference, it breaks cloudpickle.
|
||||||
|
repr_context = threading.local()
|
@@ -1,4 +1,4 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["set_run_validators", "get_run_validators"]
|
__all__ = ["set_run_validators", "get_run_validators"]
|
||||||
@@ -9,6 +9,10 @@
|
|||||||
def set_run_validators(run):
|
def set_run_validators(run):
|
||||||
"""
|
"""
|
||||||
Set whether or not validators are run. By default, they are run.
|
Set whether or not validators are run. By default, they are run.
|
||||||
|
|
||||||
|
.. deprecated:: 21.3.0 It will not be removed, but it also will not be
|
||||||
|
moved to new ``attrs`` namespace. Use `attrs.validators.set_disabled()`
|
||||||
|
instead.
|
||||||
"""
|
"""
|
||||||
if not isinstance(run, bool):
|
if not isinstance(run, bool):
|
||||||
raise TypeError("'run' must be bool.")
|
raise TypeError("'run' must be bool.")
|
||||||
@@ -19,5 +23,9 @@ def set_run_validators(run):
|
|||||||
def get_run_validators():
|
def get_run_validators():
|
||||||
"""
|
"""
|
||||||
Return whether or not validators are run.
|
Return whether or not validators are run.
|
||||||
|
|
||||||
|
.. deprecated:: 21.3.0 It will not be removed, but it also will not be
|
||||||
|
moved to new ``attrs`` namespace. Use `attrs.validators.get_disabled()`
|
||||||
|
instead.
|
||||||
"""
|
"""
|
||||||
return _run_validators
|
return _run_validators
|
@@ -1,8 +1,8 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ._compat import iteritems
|
|
||||||
from ._make import NOTHING, _obj_setattr, fields
|
from ._make import NOTHING, _obj_setattr, fields
|
||||||
from .exceptions import AttrsAttributeNotFoundError
|
from .exceptions import AttrsAttributeNotFoundError
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ def asdict(
|
|||||||
``attrs``-decorated.
|
``attrs``-decorated.
|
||||||
:param callable filter: A callable whose return code determines whether an
|
:param callable filter: A callable whose return code determines whether an
|
||||||
attribute or element is included (``True``) or dropped (``False``). Is
|
attribute or element is included (``True``) or dropped (``False``). Is
|
||||||
called with the `attr.Attribute` as the first argument and the
|
called with the `attrs.Attribute` as the first argument and the
|
||||||
value as the second argument.
|
value as the second argument.
|
||||||
:param callable dict_factory: A callable to produce dictionaries from. For
|
:param callable dict_factory: A callable to produce dictionaries from. For
|
||||||
example, to produce ordered dictionaries instead of normal Python
|
example, to produce ordered dictionaries instead of normal Python
|
||||||
@@ -46,6 +46,8 @@ def asdict(
|
|||||||
.. versionadded:: 16.0.0 *dict_factory*
|
.. versionadded:: 16.0.0 *dict_factory*
|
||||||
.. versionadded:: 16.1.0 *retain_collection_types*
|
.. versionadded:: 16.1.0 *retain_collection_types*
|
||||||
.. versionadded:: 20.3.0 *value_serializer*
|
.. versionadded:: 20.3.0 *value_serializer*
|
||||||
|
.. versionadded:: 21.3.0 If a dict has a collection for a key, it is
|
||||||
|
serialized as a tuple.
|
||||||
"""
|
"""
|
||||||
attrs = fields(inst.__class__)
|
attrs = fields(inst.__class__)
|
||||||
rv = dict_factory()
|
rv = dict_factory()
|
||||||
@@ -61,11 +63,11 @@ def asdict(
|
|||||||
if has(v.__class__):
|
if has(v.__class__):
|
||||||
rv[a.name] = asdict(
|
rv[a.name] = asdict(
|
||||||
v,
|
v,
|
||||||
True,
|
recurse=True,
|
||||||
filter,
|
filter=filter,
|
||||||
dict_factory,
|
dict_factory=dict_factory,
|
||||||
retain_collection_types,
|
retain_collection_types=retain_collection_types,
|
||||||
value_serializer,
|
value_serializer=value_serializer,
|
||||||
)
|
)
|
||||||
elif isinstance(v, (tuple, list, set, frozenset)):
|
elif isinstance(v, (tuple, list, set, frozenset)):
|
||||||
cf = v.__class__ if retain_collection_types is True else list
|
cf = v.__class__ if retain_collection_types is True else list
|
||||||
@@ -73,10 +75,11 @@ def asdict(
|
|||||||
[
|
[
|
||||||
_asdict_anything(
|
_asdict_anything(
|
||||||
i,
|
i,
|
||||||
filter,
|
is_key=False,
|
||||||
dict_factory,
|
filter=filter,
|
||||||
retain_collection_types,
|
dict_factory=dict_factory,
|
||||||
value_serializer,
|
retain_collection_types=retain_collection_types,
|
||||||
|
value_serializer=value_serializer,
|
||||||
)
|
)
|
||||||
for i in v
|
for i in v
|
||||||
]
|
]
|
||||||
@@ -87,20 +90,22 @@ def asdict(
|
|||||||
(
|
(
|
||||||
_asdict_anything(
|
_asdict_anything(
|
||||||
kk,
|
kk,
|
||||||
filter,
|
is_key=True,
|
||||||
df,
|
filter=filter,
|
||||||
retain_collection_types,
|
dict_factory=df,
|
||||||
value_serializer,
|
retain_collection_types=retain_collection_types,
|
||||||
|
value_serializer=value_serializer,
|
||||||
),
|
),
|
||||||
_asdict_anything(
|
_asdict_anything(
|
||||||
vv,
|
vv,
|
||||||
filter,
|
is_key=False,
|
||||||
df,
|
filter=filter,
|
||||||
retain_collection_types,
|
dict_factory=df,
|
||||||
value_serializer,
|
retain_collection_types=retain_collection_types,
|
||||||
|
value_serializer=value_serializer,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
for kk, vv in iteritems(v)
|
for kk, vv in v.items()
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
rv[a.name] = v
|
rv[a.name] = v
|
||||||
@@ -111,6 +116,7 @@ def asdict(
|
|||||||
|
|
||||||
def _asdict_anything(
|
def _asdict_anything(
|
||||||
val,
|
val,
|
||||||
|
is_key,
|
||||||
filter,
|
filter,
|
||||||
dict_factory,
|
dict_factory,
|
||||||
retain_collection_types,
|
retain_collection_types,
|
||||||
@@ -123,22 +129,29 @@ def _asdict_anything(
|
|||||||
# Attrs class.
|
# Attrs class.
|
||||||
rv = asdict(
|
rv = asdict(
|
||||||
val,
|
val,
|
||||||
True,
|
recurse=True,
|
||||||
filter,
|
filter=filter,
|
||||||
dict_factory,
|
dict_factory=dict_factory,
|
||||||
retain_collection_types,
|
retain_collection_types=retain_collection_types,
|
||||||
value_serializer,
|
value_serializer=value_serializer,
|
||||||
)
|
)
|
||||||
elif isinstance(val, (tuple, list, set, frozenset)):
|
elif isinstance(val, (tuple, list, set, frozenset)):
|
||||||
cf = val.__class__ if retain_collection_types is True else list
|
if retain_collection_types is True:
|
||||||
|
cf = val.__class__
|
||||||
|
elif is_key:
|
||||||
|
cf = tuple
|
||||||
|
else:
|
||||||
|
cf = list
|
||||||
|
|
||||||
rv = cf(
|
rv = cf(
|
||||||
[
|
[
|
||||||
_asdict_anything(
|
_asdict_anything(
|
||||||
i,
|
i,
|
||||||
filter,
|
is_key=False,
|
||||||
dict_factory,
|
filter=filter,
|
||||||
retain_collection_types,
|
dict_factory=dict_factory,
|
||||||
value_serializer,
|
retain_collection_types=retain_collection_types,
|
||||||
|
value_serializer=value_serializer,
|
||||||
)
|
)
|
||||||
for i in val
|
for i in val
|
||||||
]
|
]
|
||||||
@@ -148,13 +161,23 @@ def _asdict_anything(
|
|||||||
rv = df(
|
rv = df(
|
||||||
(
|
(
|
||||||
_asdict_anything(
|
_asdict_anything(
|
||||||
kk, filter, df, retain_collection_types, value_serializer
|
kk,
|
||||||
|
is_key=True,
|
||||||
|
filter=filter,
|
||||||
|
dict_factory=df,
|
||||||
|
retain_collection_types=retain_collection_types,
|
||||||
|
value_serializer=value_serializer,
|
||||||
),
|
),
|
||||||
_asdict_anything(
|
_asdict_anything(
|
||||||
vv, filter, df, retain_collection_types, value_serializer
|
vv,
|
||||||
|
is_key=False,
|
||||||
|
filter=filter,
|
||||||
|
dict_factory=df,
|
||||||
|
retain_collection_types=retain_collection_types,
|
||||||
|
value_serializer=value_serializer,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
for kk, vv in iteritems(val)
|
for kk, vv in val.items()
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
rv = val
|
rv = val
|
||||||
@@ -181,7 +204,7 @@ def astuple(
|
|||||||
``attrs``-decorated.
|
``attrs``-decorated.
|
||||||
:param callable filter: A callable whose return code determines whether an
|
:param callable filter: A callable whose return code determines whether an
|
||||||
attribute or element is included (``True``) or dropped (``False``). Is
|
attribute or element is included (``True``) or dropped (``False``). Is
|
||||||
called with the `attr.Attribute` as the first argument and the
|
called with the `attrs.Attribute` as the first argument and the
|
||||||
value as the second argument.
|
value as the second argument.
|
||||||
:param callable tuple_factory: A callable to produce tuples from. For
|
:param callable tuple_factory: A callable to produce tuples from. For
|
||||||
example, to produce lists instead of tuples.
|
example, to produce lists instead of tuples.
|
||||||
@@ -253,7 +276,7 @@ def astuple(
|
|||||||
if has(vv.__class__)
|
if has(vv.__class__)
|
||||||
else vv,
|
else vv,
|
||||||
)
|
)
|
||||||
for kk, vv in iteritems(v)
|
for kk, vv in v.items()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -291,7 +314,9 @@ def assoc(inst, **changes):
|
|||||||
class.
|
class.
|
||||||
|
|
||||||
.. deprecated:: 17.1.0
|
.. deprecated:: 17.1.0
|
||||||
Use `evolve` instead.
|
Use `attrs.evolve` instead if you can.
|
||||||
|
This function will not be removed du to the slightly different approach
|
||||||
|
compared to `attrs.evolve`.
|
||||||
"""
|
"""
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
@@ -302,7 +327,7 @@ def assoc(inst, **changes):
|
|||||||
)
|
)
|
||||||
new = copy.copy(inst)
|
new = copy.copy(inst)
|
||||||
attrs = fields(inst.__class__)
|
attrs = fields(inst.__class__)
|
||||||
for k, v in iteritems(changes):
|
for k, v in changes.items():
|
||||||
a = getattr(attrs, k, NOTHING)
|
a = getattr(attrs, k, NOTHING)
|
||||||
if a is NOTHING:
|
if a is NOTHING:
|
||||||
raise AttrsAttributeNotFoundError(
|
raise AttrsAttributeNotFoundError(
|
||||||
@@ -370,18 +395,16 @@ class and you didn't pass any attribs.
|
|||||||
:raise NameError: If types cannot be resolved because of missing variables.
|
:raise NameError: If types cannot be resolved because of missing variables.
|
||||||
|
|
||||||
:returns: *cls* so you can use this function also as a class decorator.
|
:returns: *cls* so you can use this function also as a class decorator.
|
||||||
Please note that you have to apply it **after** `attr.s`. That means
|
Please note that you have to apply it **after** `attrs.define`. That
|
||||||
the decorator has to come in the line **before** `attr.s`.
|
means the decorator has to come in the line **before** `attrs.define`.
|
||||||
|
|
||||||
.. versionadded:: 20.1.0
|
.. versionadded:: 20.1.0
|
||||||
.. versionadded:: 21.1.0 *attribs*
|
.. versionadded:: 21.1.0 *attribs*
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
# Since calling get_type_hints is expensive we cache whether we've
|
||||||
# Since calling get_type_hints is expensive we cache whether we've
|
# done it already.
|
||||||
# done it already.
|
if getattr(cls, "__attrs_types_resolved__", None) != cls:
|
||||||
cls.__attrs_types_resolved__
|
|
||||||
except AttributeError:
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
hints = typing.get_type_hints(cls, globalns=globalns, localns=localns)
|
hints = typing.get_type_hints(cls, globalns=globalns, localns=localns)
|
||||||
@@ -389,7 +412,9 @@ class and you didn't pass any attribs.
|
|||||||
if field.name in hints:
|
if field.name in hints:
|
||||||
# Since fields have been frozen we must work around it.
|
# Since fields have been frozen we must work around it.
|
||||||
_obj_setattr(field, "type", hints[field.name])
|
_obj_setattr(field, "type", hints[field.name])
|
||||||
cls.__attrs_types_resolved__ = True
|
# We store the class we resolved so that subclasses know they haven't
|
||||||
|
# been resolved.
|
||||||
|
cls.__attrs_types_resolved__ = cls
|
||||||
|
|
||||||
# Return the class so you can use it as a decorator too.
|
# Return the class so you can use it as a decorator too.
|
||||||
return cls
|
return cls
|
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,24 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
"""
|
"""
|
||||||
These are Python 3.6+-only and keyword-only APIs that call `attr.s` and
|
These are Python 3.6+-only and keyword-only APIs that call `attr.s` and
|
||||||
`attr.ib` with different default values.
|
`attr.ib` with different default values.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from attr.exceptions import UnannotatedAttributeError
|
|
||||||
|
|
||||||
from . import setters
|
from . import setters
|
||||||
from ._make import NOTHING, _frozen_setattrs, attrib, attrs
|
from ._funcs import asdict as _asdict
|
||||||
|
from ._funcs import astuple as _astuple
|
||||||
|
from ._make import (
|
||||||
|
NOTHING,
|
||||||
|
_frozen_setattrs,
|
||||||
|
_ng_default_on_setattr,
|
||||||
|
attrib,
|
||||||
|
attrs,
|
||||||
|
)
|
||||||
|
from .exceptions import UnannotatedAttributeError
|
||||||
|
|
||||||
|
|
||||||
def define(
|
def define(
|
||||||
@@ -32,22 +42,45 @@ def define(
|
|||||||
getstate_setstate=None,
|
getstate_setstate=None,
|
||||||
on_setattr=None,
|
on_setattr=None,
|
||||||
field_transformer=None,
|
field_transformer=None,
|
||||||
|
match_args=True,
|
||||||
):
|
):
|
||||||
r"""
|
r"""
|
||||||
The only behavioral differences are the handling of the *auto_attribs*
|
Define an ``attrs`` class.
|
||||||
option:
|
|
||||||
|
Differences to the classic `attr.s` that it uses underneath:
|
||||||
|
|
||||||
|
- Automatically detect whether or not *auto_attribs* should be `True` (c.f.
|
||||||
|
*auto_attribs* parameter).
|
||||||
|
- If *frozen* is `False`, run converters and validators when setting an
|
||||||
|
attribute by default.
|
||||||
|
- *slots=True*
|
||||||
|
|
||||||
|
.. caution::
|
||||||
|
|
||||||
|
Usually this has only upsides and few visible effects in everyday
|
||||||
|
programming. But it *can* lead to some suprising behaviors, so please
|
||||||
|
make sure to read :term:`slotted classes`.
|
||||||
|
- *auto_exc=True*
|
||||||
|
- *auto_detect=True*
|
||||||
|
- *order=False*
|
||||||
|
- Some options that were only relevant on Python 2 or were kept around for
|
||||||
|
backwards-compatibility have been removed.
|
||||||
|
|
||||||
|
Please note that these are all defaults and you can change them as you
|
||||||
|
wish.
|
||||||
|
|
||||||
:param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves
|
:param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves
|
||||||
exactly like `attr.s`. If left `None`, `attr.s` will try to guess:
|
exactly like `attr.s`. If left `None`, `attr.s` will try to guess:
|
||||||
|
|
||||||
1. If any attributes are annotated and no unannotated `attr.ib`\ s
|
1. If any attributes are annotated and no unannotated `attrs.fields`\ s
|
||||||
are found, it assumes *auto_attribs=True*.
|
are found, it assumes *auto_attribs=True*.
|
||||||
2. Otherwise it assumes *auto_attribs=False* and tries to collect
|
2. Otherwise it assumes *auto_attribs=False* and tries to collect
|
||||||
`attr.ib`\ s.
|
`attrs.fields`\ s.
|
||||||
|
|
||||||
and that mutable classes (``frozen=False``) validate on ``__setattr__``.
|
For now, please refer to `attr.s` for the rest of the parameters.
|
||||||
|
|
||||||
.. versionadded:: 20.1.0
|
.. versionadded:: 20.1.0
|
||||||
|
.. versionchanged:: 21.3.0 Converters are also run ``on_setattr``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def do_it(cls, auto_attribs):
|
def do_it(cls, auto_attribs):
|
||||||
@@ -72,6 +105,7 @@ def do_it(cls, auto_attribs):
|
|||||||
getstate_setstate=getstate_setstate,
|
getstate_setstate=getstate_setstate,
|
||||||
on_setattr=on_setattr,
|
on_setattr=on_setattr,
|
||||||
field_transformer=field_transformer,
|
field_transformer=field_transformer,
|
||||||
|
match_args=match_args,
|
||||||
)
|
)
|
||||||
|
|
||||||
def wrap(cls):
|
def wrap(cls):
|
||||||
@@ -84,9 +118,9 @@ def wrap(cls):
|
|||||||
|
|
||||||
had_on_setattr = on_setattr not in (None, setters.NO_OP)
|
had_on_setattr = on_setattr not in (None, setters.NO_OP)
|
||||||
|
|
||||||
# By default, mutable classes validate on setattr.
|
# By default, mutable classes convert & validate on setattr.
|
||||||
if frozen is False and on_setattr is None:
|
if frozen is False and on_setattr is None:
|
||||||
on_setattr = setters.validate
|
on_setattr = _ng_default_on_setattr
|
||||||
|
|
||||||
# However, if we subclass a frozen class, we inherit the immutability
|
# However, if we subclass a frozen class, we inherit the immutability
|
||||||
# and disable on_setattr.
|
# and disable on_setattr.
|
||||||
@@ -156,3 +190,31 @@ def field(
|
|||||||
order=order,
|
order=order,
|
||||||
on_setattr=on_setattr,
|
on_setattr=on_setattr,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def asdict(inst, *, recurse=True, filter=None, value_serializer=None):
|
||||||
|
"""
|
||||||
|
Same as `attr.asdict`, except that collections types are always retained
|
||||||
|
and dict is always used as *dict_factory*.
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
return _asdict(
|
||||||
|
inst=inst,
|
||||||
|
recurse=recurse,
|
||||||
|
filter=filter,
|
||||||
|
value_serializer=value_serializer,
|
||||||
|
retain_collection_types=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def astuple(inst, *, recurse=True, filter=None):
|
||||||
|
"""
|
||||||
|
Same as `attr.astuple`, except that collections types are always retained
|
||||||
|
and `tuple` is always used as the *tuple_factory*.
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
return _astuple(
|
||||||
|
inst=inst, recurse=recurse, filter=filter, retain_collection_types=True
|
||||||
|
)
|
@@ -1,4 +1,5 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
from functools import total_ordering
|
from functools import total_ordering
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@
|
|||||||
|
|
||||||
@total_ordering
|
@total_ordering
|
||||||
@attrs(eq=False, order=False, slots=True, frozen=True)
|
@attrs(eq=False, order=False, slots=True, frozen=True)
|
||||||
class VersionInfo(object):
|
class VersionInfo:
|
||||||
"""
|
"""
|
||||||
A version object that can be compared to tuple of length 1--4:
|
A version object that can be compared to tuple of length 1--4:
|
||||||
|
|
9
lib/spack/external/_vendoring/attr/_version_info.pyi
vendored
Normal file
9
lib/spack/external/_vendoring/attr/_version_info.pyi
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
class VersionInfo:
|
||||||
|
@property
|
||||||
|
def year(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def minor(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def micro(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def releaselevel(self) -> str: ...
|
@@ -1,22 +1,21 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Commonly useful converters.
|
Commonly useful converters.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
from ._compat import PY2
|
import typing
|
||||||
|
|
||||||
|
from ._compat import _AnnotationExtractor
|
||||||
from ._make import NOTHING, Factory, pipe
|
from ._make import NOTHING, Factory, pipe
|
||||||
|
|
||||||
|
|
||||||
if not PY2:
|
|
||||||
import inspect
|
|
||||||
import typing
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"pipe",
|
|
||||||
"optional",
|
|
||||||
"default_if_none",
|
"default_if_none",
|
||||||
|
"optional",
|
||||||
|
"pipe",
|
||||||
|
"to_bool",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -39,22 +38,15 @@ def optional_converter(val):
|
|||||||
return None
|
return None
|
||||||
return converter(val)
|
return converter(val)
|
||||||
|
|
||||||
if not PY2:
|
xtr = _AnnotationExtractor(converter)
|
||||||
sig = None
|
|
||||||
try:
|
t = xtr.get_first_param_type()
|
||||||
sig = inspect.signature(converter)
|
if t:
|
||||||
except (ValueError, TypeError): # inspect failed
|
optional_converter.__annotations__["val"] = typing.Optional[t]
|
||||||
pass
|
|
||||||
if sig:
|
rt = xtr.get_return_type()
|
||||||
params = list(sig.parameters.values())
|
if rt:
|
||||||
if params and params[0].annotation is not inspect.Parameter.empty:
|
optional_converter.__annotations__["return"] = typing.Optional[rt]
|
||||||
optional_converter.__annotations__["val"] = typing.Optional[
|
|
||||||
params[0].annotation
|
|
||||||
]
|
|
||||||
if sig.return_annotation is not inspect.Signature.empty:
|
|
||||||
optional_converter.__annotations__["return"] = typing.Optional[
|
|
||||||
sig.return_annotation
|
|
||||||
]
|
|
||||||
|
|
||||||
return optional_converter
|
return optional_converter
|
||||||
|
|
||||||
@@ -65,14 +57,14 @@ def default_if_none(default=NOTHING, factory=None):
|
|||||||
result of *factory*.
|
result of *factory*.
|
||||||
|
|
||||||
:param default: Value to be used if ``None`` is passed. Passing an instance
|
:param default: Value to be used if ``None`` is passed. Passing an instance
|
||||||
of `attr.Factory` is supported, however the ``takes_self`` option
|
of `attrs.Factory` is supported, however the ``takes_self`` option
|
||||||
is *not*.
|
is *not*.
|
||||||
:param callable factory: A callable that takes no parameters whose result
|
:param callable factory: A callable that takes no parameters whose result
|
||||||
is used if ``None`` is passed.
|
is used if ``None`` is passed.
|
||||||
|
|
||||||
:raises TypeError: If **neither** *default* or *factory* is passed.
|
:raises TypeError: If **neither** *default* or *factory* is passed.
|
||||||
:raises TypeError: If **both** *default* and *factory* are passed.
|
:raises TypeError: If **both** *default* and *factory* are passed.
|
||||||
:raises ValueError: If an instance of `attr.Factory` is passed with
|
:raises ValueError: If an instance of `attrs.Factory` is passed with
|
||||||
``takes_self=True``.
|
``takes_self=True``.
|
||||||
|
|
||||||
.. versionadded:: 18.2.0
|
.. versionadded:: 18.2.0
|
||||||
@@ -109,3 +101,44 @@ def default_if_none_converter(val):
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
return default_if_none_converter
|
return default_if_none_converter
|
||||||
|
|
||||||
|
|
||||||
|
def to_bool(val):
|
||||||
|
"""
|
||||||
|
Convert "boolean" strings (e.g., from env. vars.) to real booleans.
|
||||||
|
|
||||||
|
Values mapping to :code:`True`:
|
||||||
|
|
||||||
|
- :code:`True`
|
||||||
|
- :code:`"true"` / :code:`"t"`
|
||||||
|
- :code:`"yes"` / :code:`"y"`
|
||||||
|
- :code:`"on"`
|
||||||
|
- :code:`"1"`
|
||||||
|
- :code:`1`
|
||||||
|
|
||||||
|
Values mapping to :code:`False`:
|
||||||
|
|
||||||
|
- :code:`False`
|
||||||
|
- :code:`"false"` / :code:`"f"`
|
||||||
|
- :code:`"no"` / :code:`"n"`
|
||||||
|
- :code:`"off"`
|
||||||
|
- :code:`"0"`
|
||||||
|
- :code:`0`
|
||||||
|
|
||||||
|
:raises ValueError: for any other value.
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
if isinstance(val, str):
|
||||||
|
val = val.lower()
|
||||||
|
truthy = {True, "true", "t", "yes", "y", "on", "1", 1}
|
||||||
|
falsy = {False, "false", "f", "no", "n", "off", "0", 0}
|
||||||
|
try:
|
||||||
|
if val in truthy:
|
||||||
|
return True
|
||||||
|
if val in falsy:
|
||||||
|
return False
|
||||||
|
except TypeError:
|
||||||
|
# Raised when "val" is not hashable (e.g., lists)
|
||||||
|
pass
|
||||||
|
raise ValueError("Cannot convert value to bool: {}".format(val))
|
13
lib/spack/external/_vendoring/attr/converters.pyi
vendored
Normal file
13
lib/spack/external/_vendoring/attr/converters.pyi
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from typing import Callable, Optional, TypeVar, overload
|
||||||
|
|
||||||
|
from . import _ConverterType
|
||||||
|
|
||||||
|
_T = TypeVar("_T")
|
||||||
|
|
||||||
|
def pipe(*validators: _ConverterType) -> _ConverterType: ...
|
||||||
|
def optional(converter: _ConverterType) -> _ConverterType: ...
|
||||||
|
@overload
|
||||||
|
def default_if_none(default: _T) -> _ConverterType: ...
|
||||||
|
@overload
|
||||||
|
def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType: ...
|
||||||
|
def to_bool(val: str) -> bool: ...
|
@@ -1,4 +1,4 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
class FrozenError(AttributeError):
|
class FrozenError(AttributeError):
|
17
lib/spack/external/_vendoring/attr/exceptions.pyi
vendored
Normal file
17
lib/spack/external/_vendoring/attr/exceptions.pyi
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
class FrozenError(AttributeError):
|
||||||
|
msg: str = ...
|
||||||
|
|
||||||
|
class FrozenInstanceError(FrozenError): ...
|
||||||
|
class FrozenAttributeError(FrozenError): ...
|
||||||
|
class AttrsAttributeNotFoundError(ValueError): ...
|
||||||
|
class NotAnAttrsClassError(ValueError): ...
|
||||||
|
class DefaultAlreadySetError(RuntimeError): ...
|
||||||
|
class UnannotatedAttributeError(RuntimeError): ...
|
||||||
|
class PythonTooOldError(RuntimeError): ...
|
||||||
|
|
||||||
|
class NotCallableError(TypeError):
|
||||||
|
msg: str = ...
|
||||||
|
value: Any = ...
|
||||||
|
def __init__(self, msg: str, value: Any) -> None: ...
|
@@ -1,10 +1,9 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Commonly useful filters for `attr.asdict`.
|
Commonly useful filters for `attr.asdict`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
from ._compat import isclass
|
|
||||||
from ._make import Attribute
|
from ._make import Attribute
|
||||||
|
|
||||||
|
|
||||||
@@ -13,17 +12,17 @@ def _split_what(what):
|
|||||||
Returns a tuple of `frozenset`s of classes and attributes.
|
Returns a tuple of `frozenset`s of classes and attributes.
|
||||||
"""
|
"""
|
||||||
return (
|
return (
|
||||||
frozenset(cls for cls in what if isclass(cls)),
|
frozenset(cls for cls in what if isinstance(cls, type)),
|
||||||
frozenset(cls for cls in what if isinstance(cls, Attribute)),
|
frozenset(cls for cls in what if isinstance(cls, Attribute)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def include(*what):
|
def include(*what):
|
||||||
"""
|
"""
|
||||||
Whitelist *what*.
|
Include *what*.
|
||||||
|
|
||||||
:param what: What to whitelist.
|
:param what: What to include.
|
||||||
:type what: `list` of `type` or `attr.Attribute`\\ s
|
:type what: `list` of `type` or `attrs.Attribute`\\ s
|
||||||
|
|
||||||
:rtype: `callable`
|
:rtype: `callable`
|
||||||
"""
|
"""
|
||||||
@@ -37,10 +36,10 @@ def include_(attribute, value):
|
|||||||
|
|
||||||
def exclude(*what):
|
def exclude(*what):
|
||||||
"""
|
"""
|
||||||
Blacklist *what*.
|
Exclude *what*.
|
||||||
|
|
||||||
:param what: What to blacklist.
|
:param what: What to exclude.
|
||||||
:type what: `list` of classes or `attr.Attribute`\\ s.
|
:type what: `list` of classes or `attrs.Attribute`\\ s.
|
||||||
|
|
||||||
:rtype: `callable`
|
:rtype: `callable`
|
||||||
"""
|
"""
|
6
lib/spack/external/_vendoring/attr/filters.pyi
vendored
Normal file
6
lib/spack/external/_vendoring/attr/filters.pyi
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from typing import Any, Union
|
||||||
|
|
||||||
|
from . import Attribute, _FilterType
|
||||||
|
|
||||||
|
def include(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ...
|
||||||
|
def exclude(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ...
|
@@ -1,8 +1,9 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Commonly used hooks for on_setattr.
|
Commonly used hooks for on_setattr.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
from . import _config
|
from . import _config
|
||||||
from .exceptions import FrozenAttributeError
|
from .exceptions import FrozenAttributeError
|
||||||
@@ -67,11 +68,6 @@ def convert(instance, attrib, new_value):
|
|||||||
return new_value
|
return new_value
|
||||||
|
|
||||||
|
|
||||||
|
# Sentinel for disabling class-wide *on_setattr* hooks for certain attributes.
|
||||||
|
# autodata stopped working, so the docstring is inlined in the API docs.
|
||||||
NO_OP = object()
|
NO_OP = object()
|
||||||
"""
|
|
||||||
Sentinel for disabling class-wide *on_setattr* hooks for certain attributes.
|
|
||||||
|
|
||||||
Does not work in `pipe` or within lists.
|
|
||||||
|
|
||||||
.. versionadded:: 20.1.0
|
|
||||||
"""
|
|
19
lib/spack/external/_vendoring/attr/setters.pyi
vendored
Normal file
19
lib/spack/external/_vendoring/attr/setters.pyi
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from typing import Any, NewType, NoReturn, TypeVar, cast
|
||||||
|
|
||||||
|
from . import Attribute, _OnSetAttrType
|
||||||
|
|
||||||
|
_T = TypeVar("_T")
|
||||||
|
|
||||||
|
def frozen(
|
||||||
|
instance: Any, attribute: Attribute[Any], new_value: Any
|
||||||
|
) -> NoReturn: ...
|
||||||
|
def pipe(*setters: _OnSetAttrType) -> _OnSetAttrType: ...
|
||||||
|
def validate(instance: Any, attribute: Attribute[_T], new_value: _T) -> _T: ...
|
||||||
|
|
||||||
|
# convert is allowed to return Any, because they can be chained using pipe.
|
||||||
|
def convert(
|
||||||
|
instance: Any, attribute: Attribute[Any], new_value: Any
|
||||||
|
) -> Any: ...
|
||||||
|
|
||||||
|
_NoOpType = NewType("_NoOpType", object)
|
||||||
|
NO_OP: _NoOpType
|
@@ -1,30 +1,98 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Commonly useful validators.
|
Commonly useful validators.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
|
import operator
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
from ._config import get_run_validators, set_run_validators
|
||||||
from ._make import _AndValidator, and_, attrib, attrs
|
from ._make import _AndValidator, and_, attrib, attrs
|
||||||
from .exceptions import NotCallableError
|
from .exceptions import NotCallableError
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
Pattern = re.Pattern
|
||||||
|
except AttributeError: # Python <3.7 lacks a Pattern type.
|
||||||
|
Pattern = type(re.compile(""))
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"and_",
|
"and_",
|
||||||
"deep_iterable",
|
"deep_iterable",
|
||||||
"deep_mapping",
|
"deep_mapping",
|
||||||
|
"disabled",
|
||||||
|
"ge",
|
||||||
|
"get_disabled",
|
||||||
|
"gt",
|
||||||
"in_",
|
"in_",
|
||||||
"instance_of",
|
"instance_of",
|
||||||
"is_callable",
|
"is_callable",
|
||||||
|
"le",
|
||||||
|
"lt",
|
||||||
"matches_re",
|
"matches_re",
|
||||||
|
"max_len",
|
||||||
|
"min_len",
|
||||||
"optional",
|
"optional",
|
||||||
"provides",
|
"provides",
|
||||||
|
"set_disabled",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def set_disabled(disabled):
|
||||||
|
"""
|
||||||
|
Globally disable or enable running validators.
|
||||||
|
|
||||||
|
By default, they are run.
|
||||||
|
|
||||||
|
:param disabled: If ``True``, disable running all validators.
|
||||||
|
:type disabled: bool
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
This function is not thread-safe!
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
set_run_validators(not disabled)
|
||||||
|
|
||||||
|
|
||||||
|
def get_disabled():
|
||||||
|
"""
|
||||||
|
Return a bool indicating whether validators are currently disabled or not.
|
||||||
|
|
||||||
|
:return: ``True`` if validators are currently disabled.
|
||||||
|
:rtype: bool
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
return not get_run_validators()
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def disabled():
|
||||||
|
"""
|
||||||
|
Context manager that disables running validators within its context.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
This context manager is not thread-safe!
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
set_run_validators(False)
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
set_run_validators(True)
|
||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, slots=True, hash=True)
|
@attrs(repr=False, slots=True, hash=True)
|
||||||
class _InstanceOfValidator(object):
|
class _InstanceOfValidator:
|
||||||
type = attrib()
|
type = attrib()
|
||||||
|
|
||||||
def __call__(self, inst, attr, value):
|
def __call__(self, inst, attr, value):
|
||||||
@@ -61,16 +129,15 @@ def instance_of(type):
|
|||||||
:type type: type or tuple of types
|
:type type: type or tuple of types
|
||||||
|
|
||||||
:raises TypeError: With a human readable error message, the attribute
|
:raises TypeError: With a human readable error message, the attribute
|
||||||
(of type `attr.Attribute`), the expected type, and the value it
|
(of type `attrs.Attribute`), the expected type, and the value it
|
||||||
got.
|
got.
|
||||||
"""
|
"""
|
||||||
return _InstanceOfValidator(type)
|
return _InstanceOfValidator(type)
|
||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, frozen=True, slots=True)
|
@attrs(repr=False, frozen=True, slots=True)
|
||||||
class _MatchesReValidator(object):
|
class _MatchesReValidator:
|
||||||
regex = attrib()
|
pattern = attrib()
|
||||||
flags = attrib()
|
|
||||||
match_func = attrib()
|
match_func = attrib()
|
||||||
|
|
||||||
def __call__(self, inst, attr, value):
|
def __call__(self, inst, attr, value):
|
||||||
@@ -79,18 +146,18 @@ def __call__(self, inst, attr, value):
|
|||||||
"""
|
"""
|
||||||
if not self.match_func(value):
|
if not self.match_func(value):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"'{name}' must match regex {regex!r}"
|
"'{name}' must match regex {pattern!r}"
|
||||||
" ({value!r} doesn't)".format(
|
" ({value!r} doesn't)".format(
|
||||||
name=attr.name, regex=self.regex.pattern, value=value
|
name=attr.name, pattern=self.pattern.pattern, value=value
|
||||||
),
|
),
|
||||||
attr,
|
attr,
|
||||||
self.regex,
|
self.pattern,
|
||||||
value,
|
value,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<matches_re validator for pattern {regex!r}>".format(
|
return "<matches_re validator for pattern {pattern!r}>".format(
|
||||||
regex=self.regex
|
pattern=self.pattern
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -99,48 +166,51 @@ def matches_re(regex, flags=0, func=None):
|
|||||||
A validator that raises `ValueError` if the initializer is called
|
A validator that raises `ValueError` if the initializer is called
|
||||||
with a string that doesn't match *regex*.
|
with a string that doesn't match *regex*.
|
||||||
|
|
||||||
:param str regex: a regex string to match against
|
:param regex: a regex string or precompiled pattern to match against
|
||||||
:param int flags: flags that will be passed to the underlying re function
|
:param int flags: flags that will be passed to the underlying re function
|
||||||
(default 0)
|
(default 0)
|
||||||
:param callable func: which underlying `re` function to call (options
|
:param callable func: which underlying `re` function to call. Valid options
|
||||||
are `re.fullmatch`, `re.search`, `re.match`, default
|
are `re.fullmatch`, `re.search`, and `re.match`; the default ``None``
|
||||||
is ``None`` which means either `re.fullmatch` or an emulation of
|
means `re.fullmatch`. For performance reasons, the pattern is always
|
||||||
it on Python 2). For performance reasons, they won't be used directly
|
precompiled using `re.compile`.
|
||||||
but on a pre-`re.compile`\ ed pattern.
|
|
||||||
|
|
||||||
.. versionadded:: 19.2.0
|
.. versionadded:: 19.2.0
|
||||||
|
.. versionchanged:: 21.3.0 *regex* can be a pre-compiled pattern.
|
||||||
"""
|
"""
|
||||||
fullmatch = getattr(re, "fullmatch", None)
|
valid_funcs = (re.fullmatch, None, re.search, re.match)
|
||||||
valid_funcs = (fullmatch, None, re.search, re.match)
|
|
||||||
if func not in valid_funcs:
|
if func not in valid_funcs:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"'func' must be one of %s."
|
"'func' must be one of {}.".format(
|
||||||
% (
|
|
||||||
", ".join(
|
", ".join(
|
||||||
sorted(
|
sorted(
|
||||||
e and e.__name__ or "None" for e in set(valid_funcs)
|
e and e.__name__ or "None" for e in set(valid_funcs)
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
pattern = re.compile(regex, flags)
|
if isinstance(regex, Pattern):
|
||||||
|
if flags:
|
||||||
|
raise TypeError(
|
||||||
|
"'flags' can only be used with a string pattern; "
|
||||||
|
"pass flags to re.compile() instead"
|
||||||
|
)
|
||||||
|
pattern = regex
|
||||||
|
else:
|
||||||
|
pattern = re.compile(regex, flags)
|
||||||
|
|
||||||
if func is re.match:
|
if func is re.match:
|
||||||
match_func = pattern.match
|
match_func = pattern.match
|
||||||
elif func is re.search:
|
elif func is re.search:
|
||||||
match_func = pattern.search
|
match_func = pattern.search
|
||||||
else:
|
else:
|
||||||
if fullmatch:
|
match_func = pattern.fullmatch
|
||||||
match_func = pattern.fullmatch
|
|
||||||
else:
|
|
||||||
pattern = re.compile(r"(?:{})\Z".format(regex), flags)
|
|
||||||
match_func = pattern.match
|
|
||||||
|
|
||||||
return _MatchesReValidator(pattern, flags, match_func)
|
return _MatchesReValidator(pattern, match_func)
|
||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, slots=True, hash=True)
|
@attrs(repr=False, slots=True, hash=True)
|
||||||
class _ProvidesValidator(object):
|
class _ProvidesValidator:
|
||||||
interface = attrib()
|
interface = attrib()
|
||||||
|
|
||||||
def __call__(self, inst, attr, value):
|
def __call__(self, inst, attr, value):
|
||||||
@@ -175,14 +245,14 @@ def provides(interface):
|
|||||||
:type interface: ``zope.interface.Interface``
|
:type interface: ``zope.interface.Interface``
|
||||||
|
|
||||||
:raises TypeError: With a human readable error message, the attribute
|
:raises TypeError: With a human readable error message, the attribute
|
||||||
(of type `attr.Attribute`), the expected interface, and the
|
(of type `attrs.Attribute`), the expected interface, and the
|
||||||
value it got.
|
value it got.
|
||||||
"""
|
"""
|
||||||
return _ProvidesValidator(interface)
|
return _ProvidesValidator(interface)
|
||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, slots=True, hash=True)
|
@attrs(repr=False, slots=True, hash=True)
|
||||||
class _OptionalValidator(object):
|
class _OptionalValidator:
|
||||||
validator = attrib()
|
validator = attrib()
|
||||||
|
|
||||||
def __call__(self, inst, attr, value):
|
def __call__(self, inst, attr, value):
|
||||||
@@ -216,7 +286,7 @@ def optional(validator):
|
|||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, slots=True, hash=True)
|
@attrs(repr=False, slots=True, hash=True)
|
||||||
class _InValidator(object):
|
class _InValidator:
|
||||||
options = attrib()
|
options = attrib()
|
||||||
|
|
||||||
def __call__(self, inst, attr, value):
|
def __call__(self, inst, attr, value):
|
||||||
@@ -229,7 +299,10 @@ def __call__(self, inst, attr, value):
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
"'{name}' must be in {options!r} (got {value!r})".format(
|
"'{name}' must be in {options!r} (got {value!r})".format(
|
||||||
name=attr.name, options=self.options, value=value
|
name=attr.name, options=self.options, value=value
|
||||||
)
|
),
|
||||||
|
attr,
|
||||||
|
self.options,
|
||||||
|
value,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -248,16 +321,20 @@ def in_(options):
|
|||||||
:type options: list, tuple, `enum.Enum`, ...
|
:type options: list, tuple, `enum.Enum`, ...
|
||||||
|
|
||||||
:raises ValueError: With a human readable error message, the attribute (of
|
:raises ValueError: With a human readable error message, the attribute (of
|
||||||
type `attr.Attribute`), the expected options, and the value it
|
type `attrs.Attribute`), the expected options, and the value it
|
||||||
got.
|
got.
|
||||||
|
|
||||||
.. versionadded:: 17.1.0
|
.. versionadded:: 17.1.0
|
||||||
|
.. versionchanged:: 22.1.0
|
||||||
|
The ValueError was incomplete until now and only contained the human
|
||||||
|
readable error message. Now it contains all the information that has
|
||||||
|
been promised since 17.1.0.
|
||||||
"""
|
"""
|
||||||
return _InValidator(options)
|
return _InValidator(options)
|
||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, slots=False, hash=True)
|
@attrs(repr=False, slots=False, hash=True)
|
||||||
class _IsCallableValidator(object):
|
class _IsCallableValidator:
|
||||||
def __call__(self, inst, attr, value):
|
def __call__(self, inst, attr, value):
|
||||||
"""
|
"""
|
||||||
We use a callable class to be able to change the ``__repr__``.
|
We use a callable class to be able to change the ``__repr__``.
|
||||||
@@ -287,14 +364,14 @@ def is_callable():
|
|||||||
.. versionadded:: 19.1.0
|
.. versionadded:: 19.1.0
|
||||||
|
|
||||||
:raises `attr.exceptions.NotCallableError`: With a human readable error
|
:raises `attr.exceptions.NotCallableError`: With a human readable error
|
||||||
message containing the attribute (`attr.Attribute`) name,
|
message containing the attribute (`attrs.Attribute`) name,
|
||||||
and the value it got.
|
and the value it got.
|
||||||
"""
|
"""
|
||||||
return _IsCallableValidator()
|
return _IsCallableValidator()
|
||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, slots=True, hash=True)
|
@attrs(repr=False, slots=True, hash=True)
|
||||||
class _DeepIterable(object):
|
class _DeepIterable:
|
||||||
member_validator = attrib(validator=is_callable())
|
member_validator = attrib(validator=is_callable())
|
||||||
iterable_validator = attrib(
|
iterable_validator = attrib(
|
||||||
default=None, validator=optional(is_callable())
|
default=None, validator=optional(is_callable())
|
||||||
@@ -329,7 +406,7 @@ def deep_iterable(member_validator, iterable_validator=None):
|
|||||||
"""
|
"""
|
||||||
A validator that performs deep validation of an iterable.
|
A validator that performs deep validation of an iterable.
|
||||||
|
|
||||||
:param member_validator: Validator to apply to iterable members
|
:param member_validator: Validator(s) to apply to iterable members
|
||||||
:param iterable_validator: Validator to apply to iterable itself
|
:param iterable_validator: Validator to apply to iterable itself
|
||||||
(optional)
|
(optional)
|
||||||
|
|
||||||
@@ -337,11 +414,13 @@ def deep_iterable(member_validator, iterable_validator=None):
|
|||||||
|
|
||||||
:raises TypeError: if any sub-validators fail
|
:raises TypeError: if any sub-validators fail
|
||||||
"""
|
"""
|
||||||
|
if isinstance(member_validator, (list, tuple)):
|
||||||
|
member_validator = and_(*member_validator)
|
||||||
return _DeepIterable(member_validator, iterable_validator)
|
return _DeepIterable(member_validator, iterable_validator)
|
||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, slots=True, hash=True)
|
@attrs(repr=False, slots=True, hash=True)
|
||||||
class _DeepMapping(object):
|
class _DeepMapping:
|
||||||
key_validator = attrib(validator=is_callable())
|
key_validator = attrib(validator=is_callable())
|
||||||
value_validator = attrib(validator=is_callable())
|
value_validator = attrib(validator=is_callable())
|
||||||
mapping_validator = attrib(default=None, validator=optional(is_callable()))
|
mapping_validator = attrib(default=None, validator=optional(is_callable()))
|
||||||
@@ -377,3 +456,139 @@ def deep_mapping(key_validator, value_validator, mapping_validator=None):
|
|||||||
:raises TypeError: if any sub-validators fail
|
:raises TypeError: if any sub-validators fail
|
||||||
"""
|
"""
|
||||||
return _DeepMapping(key_validator, value_validator, mapping_validator)
|
return _DeepMapping(key_validator, value_validator, mapping_validator)
|
||||||
|
|
||||||
|
|
||||||
|
@attrs(repr=False, frozen=True, slots=True)
|
||||||
|
class _NumberValidator:
|
||||||
|
bound = attrib()
|
||||||
|
compare_op = attrib()
|
||||||
|
compare_func = attrib()
|
||||||
|
|
||||||
|
def __call__(self, inst, attr, value):
|
||||||
|
"""
|
||||||
|
We use a callable class to be able to change the ``__repr__``.
|
||||||
|
"""
|
||||||
|
if not self.compare_func(value, self.bound):
|
||||||
|
raise ValueError(
|
||||||
|
"'{name}' must be {op} {bound}: {value}".format(
|
||||||
|
name=attr.name,
|
||||||
|
op=self.compare_op,
|
||||||
|
bound=self.bound,
|
||||||
|
value=value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Validator for x {op} {bound}>".format(
|
||||||
|
op=self.compare_op, bound=self.bound
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def lt(val):
|
||||||
|
"""
|
||||||
|
A validator that raises `ValueError` if the initializer is called
|
||||||
|
with a number larger or equal to *val*.
|
||||||
|
|
||||||
|
:param val: Exclusive upper bound for values
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
return _NumberValidator(val, "<", operator.lt)
|
||||||
|
|
||||||
|
|
||||||
|
def le(val):
|
||||||
|
"""
|
||||||
|
A validator that raises `ValueError` if the initializer is called
|
||||||
|
with a number greater than *val*.
|
||||||
|
|
||||||
|
:param val: Inclusive upper bound for values
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
return _NumberValidator(val, "<=", operator.le)
|
||||||
|
|
||||||
|
|
||||||
|
def ge(val):
|
||||||
|
"""
|
||||||
|
A validator that raises `ValueError` if the initializer is called
|
||||||
|
with a number smaller than *val*.
|
||||||
|
|
||||||
|
:param val: Inclusive lower bound for values
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
return _NumberValidator(val, ">=", operator.ge)
|
||||||
|
|
||||||
|
|
||||||
|
def gt(val):
|
||||||
|
"""
|
||||||
|
A validator that raises `ValueError` if the initializer is called
|
||||||
|
with a number smaller or equal to *val*.
|
||||||
|
|
||||||
|
:param val: Exclusive lower bound for values
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
return _NumberValidator(val, ">", operator.gt)
|
||||||
|
|
||||||
|
|
||||||
|
@attrs(repr=False, frozen=True, slots=True)
|
||||||
|
class _MaxLengthValidator:
|
||||||
|
max_length = attrib()
|
||||||
|
|
||||||
|
def __call__(self, inst, attr, value):
|
||||||
|
"""
|
||||||
|
We use a callable class to be able to change the ``__repr__``.
|
||||||
|
"""
|
||||||
|
if len(value) > self.max_length:
|
||||||
|
raise ValueError(
|
||||||
|
"Length of '{name}' must be <= {max}: {len}".format(
|
||||||
|
name=attr.name, max=self.max_length, len=len(value)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<max_len validator for {max}>".format(max=self.max_length)
|
||||||
|
|
||||||
|
|
||||||
|
def max_len(length):
|
||||||
|
"""
|
||||||
|
A validator that raises `ValueError` if the initializer is called
|
||||||
|
with a string or iterable that is longer than *length*.
|
||||||
|
|
||||||
|
:param int length: Maximum length of the string or iterable
|
||||||
|
|
||||||
|
.. versionadded:: 21.3.0
|
||||||
|
"""
|
||||||
|
return _MaxLengthValidator(length)
|
||||||
|
|
||||||
|
|
||||||
|
@attrs(repr=False, frozen=True, slots=True)
|
||||||
|
class _MinLengthValidator:
|
||||||
|
min_length = attrib()
|
||||||
|
|
||||||
|
def __call__(self, inst, attr, value):
|
||||||
|
"""
|
||||||
|
We use a callable class to be able to change the ``__repr__``.
|
||||||
|
"""
|
||||||
|
if len(value) < self.min_length:
|
||||||
|
raise ValueError(
|
||||||
|
"Length of '{name}' must be => {min}: {len}".format(
|
||||||
|
name=attr.name, min=self.min_length, len=len(value)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<min_len validator for {min}>".format(min=self.min_length)
|
||||||
|
|
||||||
|
|
||||||
|
def min_len(length):
|
||||||
|
"""
|
||||||
|
A validator that raises `ValueError` if the initializer is called
|
||||||
|
with a string or iterable that is shorter than *length*.
|
||||||
|
|
||||||
|
:param int length: Minimum length of the string or iterable
|
||||||
|
|
||||||
|
.. versionadded:: 22.1.0
|
||||||
|
"""
|
||||||
|
return _MinLengthValidator(length)
|
80
lib/spack/external/_vendoring/attr/validators.pyi
vendored
Normal file
80
lib/spack/external/_vendoring/attr/validators.pyi
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
from typing import (
|
||||||
|
Any,
|
||||||
|
AnyStr,
|
||||||
|
Callable,
|
||||||
|
Container,
|
||||||
|
ContextManager,
|
||||||
|
Iterable,
|
||||||
|
List,
|
||||||
|
Mapping,
|
||||||
|
Match,
|
||||||
|
Optional,
|
||||||
|
Pattern,
|
||||||
|
Tuple,
|
||||||
|
Type,
|
||||||
|
TypeVar,
|
||||||
|
Union,
|
||||||
|
overload,
|
||||||
|
)
|
||||||
|
|
||||||
|
from . import _ValidatorType
|
||||||
|
from . import _ValidatorArgType
|
||||||
|
|
||||||
|
_T = TypeVar("_T")
|
||||||
|
_T1 = TypeVar("_T1")
|
||||||
|
_T2 = TypeVar("_T2")
|
||||||
|
_T3 = TypeVar("_T3")
|
||||||
|
_I = TypeVar("_I", bound=Iterable)
|
||||||
|
_K = TypeVar("_K")
|
||||||
|
_V = TypeVar("_V")
|
||||||
|
_M = TypeVar("_M", bound=Mapping)
|
||||||
|
|
||||||
|
def set_disabled(run: bool) -> None: ...
|
||||||
|
def get_disabled() -> bool: ...
|
||||||
|
def disabled() -> ContextManager[None]: ...
|
||||||
|
|
||||||
|
# To be more precise on instance_of use some overloads.
|
||||||
|
# If there are more than 3 items in the tuple then we fall back to Any
|
||||||
|
@overload
|
||||||
|
def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ...
|
||||||
|
@overload
|
||||||
|
def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ...
|
||||||
|
@overload
|
||||||
|
def instance_of(
|
||||||
|
type: Tuple[Type[_T1], Type[_T2]]
|
||||||
|
) -> _ValidatorType[Union[_T1, _T2]]: ...
|
||||||
|
@overload
|
||||||
|
def instance_of(
|
||||||
|
type: Tuple[Type[_T1], Type[_T2], Type[_T3]]
|
||||||
|
) -> _ValidatorType[Union[_T1, _T2, _T3]]: ...
|
||||||
|
@overload
|
||||||
|
def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ...
|
||||||
|
def provides(interface: Any) -> _ValidatorType[Any]: ...
|
||||||
|
def optional(
|
||||||
|
validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]]
|
||||||
|
) -> _ValidatorType[Optional[_T]]: ...
|
||||||
|
def in_(options: Container[_T]) -> _ValidatorType[_T]: ...
|
||||||
|
def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ...
|
||||||
|
def matches_re(
|
||||||
|
regex: Union[Pattern[AnyStr], AnyStr],
|
||||||
|
flags: int = ...,
|
||||||
|
func: Optional[
|
||||||
|
Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]]
|
||||||
|
] = ...,
|
||||||
|
) -> _ValidatorType[AnyStr]: ...
|
||||||
|
def deep_iterable(
|
||||||
|
member_validator: _ValidatorArgType[_T],
|
||||||
|
iterable_validator: Optional[_ValidatorType[_I]] = ...,
|
||||||
|
) -> _ValidatorType[_I]: ...
|
||||||
|
def deep_mapping(
|
||||||
|
key_validator: _ValidatorType[_K],
|
||||||
|
value_validator: _ValidatorType[_V],
|
||||||
|
mapping_validator: Optional[_ValidatorType[_M]] = ...,
|
||||||
|
) -> _ValidatorType[_M]: ...
|
||||||
|
def is_callable() -> _ValidatorType[_T]: ...
|
||||||
|
def lt(val: _T) -> _ValidatorType[_T]: ...
|
||||||
|
def le(val: _T) -> _ValidatorType[_T]: ...
|
||||||
|
def ge(val: _T) -> _ValidatorType[_T]: ...
|
||||||
|
def gt(val: _T) -> _ValidatorType[_T]: ...
|
||||||
|
def max_len(length: int) -> _ValidatorType[_T]: ...
|
||||||
|
def min_len(length: int) -> _ValidatorType[_T]: ...
|
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015 Hynek Schlawack
|
Copyright (c) 2015 Hynek Schlawack and the attrs contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
70
lib/spack/external/_vendoring/attrs/__init__.py
vendored
Normal file
70
lib/spack/external/_vendoring/attrs/__init__.py
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from attr import (
|
||||||
|
NOTHING,
|
||||||
|
Attribute,
|
||||||
|
Factory,
|
||||||
|
__author__,
|
||||||
|
__copyright__,
|
||||||
|
__description__,
|
||||||
|
__doc__,
|
||||||
|
__email__,
|
||||||
|
__license__,
|
||||||
|
__title__,
|
||||||
|
__url__,
|
||||||
|
__version__,
|
||||||
|
__version_info__,
|
||||||
|
assoc,
|
||||||
|
cmp_using,
|
||||||
|
define,
|
||||||
|
evolve,
|
||||||
|
field,
|
||||||
|
fields,
|
||||||
|
fields_dict,
|
||||||
|
frozen,
|
||||||
|
has,
|
||||||
|
make_class,
|
||||||
|
mutable,
|
||||||
|
resolve_types,
|
||||||
|
validate,
|
||||||
|
)
|
||||||
|
from attr._next_gen import asdict, astuple
|
||||||
|
|
||||||
|
from . import converters, exceptions, filters, setters, validators
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"__author__",
|
||||||
|
"__copyright__",
|
||||||
|
"__description__",
|
||||||
|
"__doc__",
|
||||||
|
"__email__",
|
||||||
|
"__license__",
|
||||||
|
"__title__",
|
||||||
|
"__url__",
|
||||||
|
"__version__",
|
||||||
|
"__version_info__",
|
||||||
|
"asdict",
|
||||||
|
"assoc",
|
||||||
|
"astuple",
|
||||||
|
"Attribute",
|
||||||
|
"cmp_using",
|
||||||
|
"converters",
|
||||||
|
"define",
|
||||||
|
"evolve",
|
||||||
|
"exceptions",
|
||||||
|
"Factory",
|
||||||
|
"field",
|
||||||
|
"fields_dict",
|
||||||
|
"fields",
|
||||||
|
"filters",
|
||||||
|
"frozen",
|
||||||
|
"has",
|
||||||
|
"make_class",
|
||||||
|
"mutable",
|
||||||
|
"NOTHING",
|
||||||
|
"resolve_types",
|
||||||
|
"setters",
|
||||||
|
"validate",
|
||||||
|
"validators",
|
||||||
|
]
|
66
lib/spack/external/_vendoring/attrs/__init__.pyi
vendored
Normal file
66
lib/spack/external/_vendoring/attrs/__init__.pyi
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
from typing import (
|
||||||
|
Any,
|
||||||
|
Callable,
|
||||||
|
Dict,
|
||||||
|
Mapping,
|
||||||
|
Optional,
|
||||||
|
Sequence,
|
||||||
|
Tuple,
|
||||||
|
Type,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Because we need to type our own stuff, we have to make everything from
|
||||||
|
# attr explicitly public too.
|
||||||
|
from attr import __author__ as __author__
|
||||||
|
from attr import __copyright__ as __copyright__
|
||||||
|
from attr import __description__ as __description__
|
||||||
|
from attr import __email__ as __email__
|
||||||
|
from attr import __license__ as __license__
|
||||||
|
from attr import __title__ as __title__
|
||||||
|
from attr import __url__ as __url__
|
||||||
|
from attr import __version__ as __version__
|
||||||
|
from attr import __version_info__ as __version_info__
|
||||||
|
from attr import _FilterType
|
||||||
|
from attr import assoc as assoc
|
||||||
|
from attr import Attribute as Attribute
|
||||||
|
from attr import cmp_using as cmp_using
|
||||||
|
from attr import converters as converters
|
||||||
|
from attr import define as define
|
||||||
|
from attr import evolve as evolve
|
||||||
|
from attr import exceptions as exceptions
|
||||||
|
from attr import Factory as Factory
|
||||||
|
from attr import field as field
|
||||||
|
from attr import fields as fields
|
||||||
|
from attr import fields_dict as fields_dict
|
||||||
|
from attr import filters as filters
|
||||||
|
from attr import frozen as frozen
|
||||||
|
from attr import has as has
|
||||||
|
from attr import make_class as make_class
|
||||||
|
from attr import mutable as mutable
|
||||||
|
from attr import NOTHING as NOTHING
|
||||||
|
from attr import resolve_types as resolve_types
|
||||||
|
from attr import setters as setters
|
||||||
|
from attr import validate as validate
|
||||||
|
from attr import validators as validators
|
||||||
|
|
||||||
|
# TODO: see definition of attr.asdict/astuple
|
||||||
|
def asdict(
|
||||||
|
inst: Any,
|
||||||
|
recurse: bool = ...,
|
||||||
|
filter: Optional[_FilterType[Any]] = ...,
|
||||||
|
dict_factory: Type[Mapping[Any, Any]] = ...,
|
||||||
|
retain_collection_types: bool = ...,
|
||||||
|
value_serializer: Optional[
|
||||||
|
Callable[[type, Attribute[Any], Any], Any]
|
||||||
|
] = ...,
|
||||||
|
tuple_keys: bool = ...,
|
||||||
|
) -> Dict[str, Any]: ...
|
||||||
|
|
||||||
|
# TODO: add support for returning NamedTuple from the mypy plugin
|
||||||
|
def astuple(
|
||||||
|
inst: Any,
|
||||||
|
recurse: bool = ...,
|
||||||
|
filter: Optional[_FilterType[Any]] = ...,
|
||||||
|
tuple_factory: Type[Sequence[Any]] = ...,
|
||||||
|
retain_collection_types: bool = ...,
|
||||||
|
) -> Tuple[Any, ...]: ...
|
3
lib/spack/external/_vendoring/attrs/converters.py
vendored
Normal file
3
lib/spack/external/_vendoring/attrs/converters.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from attr.converters import * # noqa
|
3
lib/spack/external/_vendoring/attrs/exceptions.py
vendored
Normal file
3
lib/spack/external/_vendoring/attrs/exceptions.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from attr.exceptions import * # noqa
|
3
lib/spack/external/_vendoring/attrs/filters.py
vendored
Normal file
3
lib/spack/external/_vendoring/attrs/filters.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from attr.filters import * # noqa
|
0
lib/spack/external/_vendoring/attrs/py.typed
vendored
Normal file
0
lib/spack/external/_vendoring/attrs/py.typed
vendored
Normal file
3
lib/spack/external/_vendoring/attrs/setters.py
vendored
Normal file
3
lib/spack/external/_vendoring/attrs/setters.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from attr.setters import * # noqa
|
3
lib/spack/external/_vendoring/attrs/validators.py
vendored
Normal file
3
lib/spack/external/_vendoring/attrs/validators.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from attr.validators import * # noqa
|
202
lib/spack/external/_vendoring/distro/LICENSE
vendored
Normal file
202
lib/spack/external/_vendoring/distro/LICENSE
vendored
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
54
lib/spack/external/_vendoring/distro/__init__.py
vendored
Normal file
54
lib/spack/external/_vendoring/distro/__init__.py
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
from .distro import (
|
||||||
|
NORMALIZED_DISTRO_ID,
|
||||||
|
NORMALIZED_LSB_ID,
|
||||||
|
NORMALIZED_OS_ID,
|
||||||
|
LinuxDistribution,
|
||||||
|
__version__,
|
||||||
|
build_number,
|
||||||
|
codename,
|
||||||
|
distro_release_attr,
|
||||||
|
distro_release_info,
|
||||||
|
id,
|
||||||
|
info,
|
||||||
|
like,
|
||||||
|
linux_distribution,
|
||||||
|
lsb_release_attr,
|
||||||
|
lsb_release_info,
|
||||||
|
major_version,
|
||||||
|
minor_version,
|
||||||
|
name,
|
||||||
|
os_release_attr,
|
||||||
|
os_release_info,
|
||||||
|
uname_attr,
|
||||||
|
uname_info,
|
||||||
|
version,
|
||||||
|
version_parts,
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"NORMALIZED_DISTRO_ID",
|
||||||
|
"NORMALIZED_LSB_ID",
|
||||||
|
"NORMALIZED_OS_ID",
|
||||||
|
"LinuxDistribution",
|
||||||
|
"build_number",
|
||||||
|
"codename",
|
||||||
|
"distro_release_attr",
|
||||||
|
"distro_release_info",
|
||||||
|
"id",
|
||||||
|
"info",
|
||||||
|
"like",
|
||||||
|
"linux_distribution",
|
||||||
|
"lsb_release_attr",
|
||||||
|
"lsb_release_info",
|
||||||
|
"major_version",
|
||||||
|
"minor_version",
|
||||||
|
"name",
|
||||||
|
"os_release_attr",
|
||||||
|
"os_release_info",
|
||||||
|
"uname_attr",
|
||||||
|
"uname_info",
|
||||||
|
"version",
|
||||||
|
"version_parts",
|
||||||
|
]
|
||||||
|
|
||||||
|
__version__ = __version__
|
4
lib/spack/external/_vendoring/distro/__main__.py
vendored
Normal file
4
lib/spack/external/_vendoring/distro/__main__.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .distro import main
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
# Copyright 2015,2016,2017 Nir Cohen
|
# Copyright 2015,2016,2017 Nir Cohen
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -36,40 +37,39 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
from typing import (
|
||||||
|
Any,
|
||||||
|
Callable,
|
||||||
|
Dict,
|
||||||
|
Iterable,
|
||||||
|
Optional,
|
||||||
|
Sequence,
|
||||||
|
TextIO,
|
||||||
|
Tuple,
|
||||||
|
Type,
|
||||||
|
)
|
||||||
|
|
||||||
__version__ = "1.6.0"
|
try:
|
||||||
|
from typing import TypedDict
|
||||||
|
except ImportError:
|
||||||
|
# Python 3.7
|
||||||
|
TypedDict = dict
|
||||||
|
|
||||||
# Use `if False` to avoid an ImportError on Python 2. After dropping Python 2
|
__version__ = "1.8.0"
|
||||||
# support, can use typing.TYPE_CHECKING instead. See:
|
|
||||||
# https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING
|
|
||||||
if False: # pragma: nocover
|
|
||||||
from typing import (
|
|
||||||
Any,
|
|
||||||
Callable,
|
|
||||||
Dict,
|
|
||||||
Iterable,
|
|
||||||
Optional,
|
|
||||||
Sequence,
|
|
||||||
TextIO,
|
|
||||||
Tuple,
|
|
||||||
Type,
|
|
||||||
TypedDict,
|
|
||||||
Union,
|
|
||||||
)
|
|
||||||
|
|
||||||
VersionDict = TypedDict(
|
|
||||||
"VersionDict", {"major": str, "minor": str, "build_number": str}
|
class VersionDict(TypedDict):
|
||||||
)
|
major: str
|
||||||
InfoDict = TypedDict(
|
minor: str
|
||||||
"InfoDict",
|
build_number: str
|
||||||
{
|
|
||||||
"id": str,
|
|
||||||
"version": str,
|
class InfoDict(TypedDict):
|
||||||
"version_parts": VersionDict,
|
id: str
|
||||||
"like": str,
|
version: str
|
||||||
"codename": str,
|
version_parts: VersionDict
|
||||||
},
|
like: str
|
||||||
)
|
codename: str
|
||||||
|
|
||||||
|
|
||||||
_UNIXCONFDIR = os.environ.get("UNIXCONFDIR", "/etc")
|
_UNIXCONFDIR = os.environ.get("UNIXCONFDIR", "/etc")
|
||||||
@@ -85,6 +85,7 @@
|
|||||||
#: * Value: Normalized value.
|
#: * Value: Normalized value.
|
||||||
NORMALIZED_OS_ID = {
|
NORMALIZED_OS_ID = {
|
||||||
"ol": "oracle", # Oracle Linux
|
"ol": "oracle", # Oracle Linux
|
||||||
|
"opensuse-leap": "opensuse", # Newer versions of OpenSuSE report as opensuse-leap
|
||||||
}
|
}
|
||||||
|
|
||||||
#: Translation table for normalizing the "Distributor ID" attribute returned by
|
#: Translation table for normalizing the "Distributor ID" attribute returned by
|
||||||
@@ -121,6 +122,26 @@
|
|||||||
# Pattern for base file name of distro release file
|
# Pattern for base file name of distro release file
|
||||||
_DISTRO_RELEASE_BASENAME_PATTERN = re.compile(r"(\w+)[-_](release|version)$")
|
_DISTRO_RELEASE_BASENAME_PATTERN = re.compile(r"(\w+)[-_](release|version)$")
|
||||||
|
|
||||||
|
# Base file names to be looked up for if _UNIXCONFDIR is not readable.
|
||||||
|
_DISTRO_RELEASE_BASENAMES = [
|
||||||
|
"SuSE-release",
|
||||||
|
"arch-release",
|
||||||
|
"base-release",
|
||||||
|
"centos-release",
|
||||||
|
"fedora-release",
|
||||||
|
"gentoo-release",
|
||||||
|
"mageia-release",
|
||||||
|
"mandrake-release",
|
||||||
|
"mandriva-release",
|
||||||
|
"mandrivalinux-release",
|
||||||
|
"manjaro-release",
|
||||||
|
"oracle-release",
|
||||||
|
"redhat-release",
|
||||||
|
"rocky-release",
|
||||||
|
"sl-release",
|
||||||
|
"slackware-version",
|
||||||
|
]
|
||||||
|
|
||||||
# Base file names to be ignored when searching for distro release file
|
# Base file names to be ignored when searching for distro release file
|
||||||
_DISTRO_RELEASE_IGNORE_BASENAMES = (
|
_DISTRO_RELEASE_IGNORE_BASENAMES = (
|
||||||
"debian_version",
|
"debian_version",
|
||||||
@@ -133,8 +154,7 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def linux_distribution(full_distribution_name=True):
|
def linux_distribution(full_distribution_name: bool = True) -> Tuple[str, str, str]:
|
||||||
# type: (bool) -> Tuple[str, str, str]
|
|
||||||
"""
|
"""
|
||||||
.. deprecated:: 1.6.0
|
.. deprecated:: 1.6.0
|
||||||
|
|
||||||
@@ -151,7 +171,8 @@ def linux_distribution(full_distribution_name=True):
|
|||||||
|
|
||||||
* ``version``: The result of :func:`distro.version`.
|
* ``version``: The result of :func:`distro.version`.
|
||||||
|
|
||||||
* ``codename``: The result of :func:`distro.codename`.
|
* ``codename``: The extra item (usually in parentheses) after the
|
||||||
|
os-release version number, or the result of :func:`distro.codename`.
|
||||||
|
|
||||||
The interface of this function is compatible with the original
|
The interface of this function is compatible with the original
|
||||||
:py:func:`platform.linux_distribution` function, supporting a subset of
|
:py:func:`platform.linux_distribution` function, supporting a subset of
|
||||||
@@ -176,8 +197,7 @@ def linux_distribution(full_distribution_name=True):
|
|||||||
return _distro.linux_distribution(full_distribution_name)
|
return _distro.linux_distribution(full_distribution_name)
|
||||||
|
|
||||||
|
|
||||||
def id():
|
def id() -> str:
|
||||||
# type: () -> str
|
|
||||||
"""
|
"""
|
||||||
Return the distro ID of the current distribution, as a
|
Return the distro ID of the current distribution, as a
|
||||||
machine-readable string.
|
machine-readable string.
|
||||||
@@ -198,8 +218,9 @@ def id():
|
|||||||
"fedora" Fedora
|
"fedora" Fedora
|
||||||
"sles" SUSE Linux Enterprise Server
|
"sles" SUSE Linux Enterprise Server
|
||||||
"opensuse" openSUSE
|
"opensuse" openSUSE
|
||||||
"amazon" Amazon Linux
|
"amzn" Amazon Linux
|
||||||
"arch" Arch Linux
|
"arch" Arch Linux
|
||||||
|
"buildroot" Buildroot
|
||||||
"cloudlinux" CloudLinux OS
|
"cloudlinux" CloudLinux OS
|
||||||
"exherbo" Exherbo Linux
|
"exherbo" Exherbo Linux
|
||||||
"gentoo" GenToo Linux
|
"gentoo" GenToo Linux
|
||||||
@@ -219,6 +240,9 @@ def id():
|
|||||||
"netbsd" NetBSD
|
"netbsd" NetBSD
|
||||||
"freebsd" FreeBSD
|
"freebsd" FreeBSD
|
||||||
"midnightbsd" MidnightBSD
|
"midnightbsd" MidnightBSD
|
||||||
|
"rocky" Rocky Linux
|
||||||
|
"aix" AIX
|
||||||
|
"guix" Guix System
|
||||||
============== =========================================
|
============== =========================================
|
||||||
|
|
||||||
If you have a need to get distros for reliable IDs added into this set,
|
If you have a need to get distros for reliable IDs added into this set,
|
||||||
@@ -256,8 +280,7 @@ def id():
|
|||||||
return _distro.id()
|
return _distro.id()
|
||||||
|
|
||||||
|
|
||||||
def name(pretty=False):
|
def name(pretty: bool = False) -> str:
|
||||||
# type: (bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the name of the current OS distribution, as a human-readable
|
Return the name of the current OS distribution, as a human-readable
|
||||||
string.
|
string.
|
||||||
@@ -296,8 +319,7 @@ def name(pretty=False):
|
|||||||
return _distro.name(pretty)
|
return _distro.name(pretty)
|
||||||
|
|
||||||
|
|
||||||
def version(pretty=False, best=False):
|
def version(pretty: bool = False, best: bool = False) -> str:
|
||||||
# type: (bool, bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the version of the current OS distribution, as a human-readable
|
Return the version of the current OS distribution, as a human-readable
|
||||||
string.
|
string.
|
||||||
@@ -313,6 +335,10 @@ def version(pretty=False, best=False):
|
|||||||
sources in a fixed priority order does not always yield the most precise
|
sources in a fixed priority order does not always yield the most precise
|
||||||
version (e.g. for Debian 8.2, or CentOS 7.1).
|
version (e.g. for Debian 8.2, or CentOS 7.1).
|
||||||
|
|
||||||
|
Some other distributions may not provide this kind of information. In these
|
||||||
|
cases, an empty string would be returned. This behavior can be observed
|
||||||
|
with rolling releases distributions (e.g. Arch Linux).
|
||||||
|
|
||||||
The *best* parameter can be used to control the approach for the returned
|
The *best* parameter can be used to control the approach for the returned
|
||||||
version:
|
version:
|
||||||
|
|
||||||
@@ -341,8 +367,7 @@ def version(pretty=False, best=False):
|
|||||||
return _distro.version(pretty, best)
|
return _distro.version(pretty, best)
|
||||||
|
|
||||||
|
|
||||||
def version_parts(best=False):
|
def version_parts(best: bool = False) -> Tuple[str, str, str]:
|
||||||
# type: (bool) -> Tuple[str, str, str]
|
|
||||||
"""
|
"""
|
||||||
Return the version of the current OS distribution as a tuple
|
Return the version of the current OS distribution as a tuple
|
||||||
``(major, minor, build_number)`` with items as follows:
|
``(major, minor, build_number)`` with items as follows:
|
||||||
@@ -359,8 +384,7 @@ def version_parts(best=False):
|
|||||||
return _distro.version_parts(best)
|
return _distro.version_parts(best)
|
||||||
|
|
||||||
|
|
||||||
def major_version(best=False):
|
def major_version(best: bool = False) -> str:
|
||||||
# type: (bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the major version of the current OS distribution, as a string,
|
Return the major version of the current OS distribution, as a string,
|
||||||
if provided.
|
if provided.
|
||||||
@@ -373,8 +397,7 @@ def major_version(best=False):
|
|||||||
return _distro.major_version(best)
|
return _distro.major_version(best)
|
||||||
|
|
||||||
|
|
||||||
def minor_version(best=False):
|
def minor_version(best: bool = False) -> str:
|
||||||
# type: (bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the minor version of the current OS distribution, as a string,
|
Return the minor version of the current OS distribution, as a string,
|
||||||
if provided.
|
if provided.
|
||||||
@@ -387,8 +410,7 @@ def minor_version(best=False):
|
|||||||
return _distro.minor_version(best)
|
return _distro.minor_version(best)
|
||||||
|
|
||||||
|
|
||||||
def build_number(best=False):
|
def build_number(best: bool = False) -> str:
|
||||||
# type: (bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the build number of the current OS distribution, as a string,
|
Return the build number of the current OS distribution, as a string,
|
||||||
if provided.
|
if provided.
|
||||||
@@ -401,8 +423,7 @@ def build_number(best=False):
|
|||||||
return _distro.build_number(best)
|
return _distro.build_number(best)
|
||||||
|
|
||||||
|
|
||||||
def like():
|
def like() -> str:
|
||||||
# type: () -> str
|
|
||||||
"""
|
"""
|
||||||
Return a space-separated list of distro IDs of distributions that are
|
Return a space-separated list of distro IDs of distributions that are
|
||||||
closely related to the current OS distribution in regards to packaging
|
closely related to the current OS distribution in regards to packaging
|
||||||
@@ -419,8 +440,7 @@ def like():
|
|||||||
return _distro.like()
|
return _distro.like()
|
||||||
|
|
||||||
|
|
||||||
def codename():
|
def codename() -> str:
|
||||||
# type: () -> str
|
|
||||||
"""
|
"""
|
||||||
Return the codename for the release of the current OS distribution,
|
Return the codename for the release of the current OS distribution,
|
||||||
as a string.
|
as a string.
|
||||||
@@ -444,8 +464,7 @@ def codename():
|
|||||||
return _distro.codename()
|
return _distro.codename()
|
||||||
|
|
||||||
|
|
||||||
def info(pretty=False, best=False):
|
def info(pretty: bool = False, best: bool = False) -> InfoDict:
|
||||||
# type: (bool, bool) -> InfoDict
|
|
||||||
"""
|
"""
|
||||||
Return certain machine-readable information items about the current OS
|
Return certain machine-readable information items about the current OS
|
||||||
distribution in a dictionary, as shown in the following example:
|
distribution in a dictionary, as shown in the following example:
|
||||||
@@ -489,8 +508,7 @@ def info(pretty=False, best=False):
|
|||||||
return _distro.info(pretty, best)
|
return _distro.info(pretty, best)
|
||||||
|
|
||||||
|
|
||||||
def os_release_info():
|
def os_release_info() -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Return a dictionary containing key-value pairs for the information items
|
Return a dictionary containing key-value pairs for the information items
|
||||||
from the os-release file data source of the current OS distribution.
|
from the os-release file data source of the current OS distribution.
|
||||||
@@ -500,8 +518,7 @@ def os_release_info():
|
|||||||
return _distro.os_release_info()
|
return _distro.os_release_info()
|
||||||
|
|
||||||
|
|
||||||
def lsb_release_info():
|
def lsb_release_info() -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Return a dictionary containing key-value pairs for the information items
|
Return a dictionary containing key-value pairs for the information items
|
||||||
from the lsb_release command data source of the current OS distribution.
|
from the lsb_release command data source of the current OS distribution.
|
||||||
@@ -512,8 +529,7 @@ def lsb_release_info():
|
|||||||
return _distro.lsb_release_info()
|
return _distro.lsb_release_info()
|
||||||
|
|
||||||
|
|
||||||
def distro_release_info():
|
def distro_release_info() -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Return a dictionary containing key-value pairs for the information items
|
Return a dictionary containing key-value pairs for the information items
|
||||||
from the distro release file data source of the current OS distribution.
|
from the distro release file data source of the current OS distribution.
|
||||||
@@ -523,8 +539,7 @@ def distro_release_info():
|
|||||||
return _distro.distro_release_info()
|
return _distro.distro_release_info()
|
||||||
|
|
||||||
|
|
||||||
def uname_info():
|
def uname_info() -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Return a dictionary containing key-value pairs for the information items
|
Return a dictionary containing key-value pairs for the information items
|
||||||
from the distro release file data source of the current OS distribution.
|
from the distro release file data source of the current OS distribution.
|
||||||
@@ -532,8 +547,7 @@ def uname_info():
|
|||||||
return _distro.uname_info()
|
return _distro.uname_info()
|
||||||
|
|
||||||
|
|
||||||
def os_release_attr(attribute):
|
def os_release_attr(attribute: str) -> str:
|
||||||
# type: (str) -> str
|
|
||||||
"""
|
"""
|
||||||
Return a single named information item from the os-release file data source
|
Return a single named information item from the os-release file data source
|
||||||
of the current OS distribution.
|
of the current OS distribution.
|
||||||
@@ -552,8 +566,7 @@ def os_release_attr(attribute):
|
|||||||
return _distro.os_release_attr(attribute)
|
return _distro.os_release_attr(attribute)
|
||||||
|
|
||||||
|
|
||||||
def lsb_release_attr(attribute):
|
def lsb_release_attr(attribute: str) -> str:
|
||||||
# type: (str) -> str
|
|
||||||
"""
|
"""
|
||||||
Return a single named information item from the lsb_release command output
|
Return a single named information item from the lsb_release command output
|
||||||
data source of the current OS distribution.
|
data source of the current OS distribution.
|
||||||
@@ -573,8 +586,7 @@ def lsb_release_attr(attribute):
|
|||||||
return _distro.lsb_release_attr(attribute)
|
return _distro.lsb_release_attr(attribute)
|
||||||
|
|
||||||
|
|
||||||
def distro_release_attr(attribute):
|
def distro_release_attr(attribute: str) -> str:
|
||||||
# type: (str) -> str
|
|
||||||
"""
|
"""
|
||||||
Return a single named information item from the distro release file
|
Return a single named information item from the distro release file
|
||||||
data source of the current OS distribution.
|
data source of the current OS distribution.
|
||||||
@@ -593,8 +605,7 @@ def distro_release_attr(attribute):
|
|||||||
return _distro.distro_release_attr(attribute)
|
return _distro.distro_release_attr(attribute)
|
||||||
|
|
||||||
|
|
||||||
def uname_attr(attribute):
|
def uname_attr(attribute: str) -> str:
|
||||||
# type: (str) -> str
|
|
||||||
"""
|
"""
|
||||||
Return a single named information item from the distro release file
|
Return a single named information item from the distro release file
|
||||||
data source of the current OS distribution.
|
data source of the current OS distribution.
|
||||||
@@ -615,25 +626,23 @@ def uname_attr(attribute):
|
|||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# Python < 3.8
|
# Python < 3.8
|
||||||
class cached_property(object): # type: ignore
|
class cached_property: # type: ignore
|
||||||
"""A version of @property which caches the value. On access, it calls the
|
"""A version of @property which caches the value. On access, it calls the
|
||||||
underlying function and sets the value in `__dict__` so future accesses
|
underlying function and sets the value in `__dict__` so future accesses
|
||||||
will not re-call the property.
|
will not re-call the property.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, f):
|
def __init__(self, f: Callable[[Any], Any]) -> None:
|
||||||
# type: (Callable[[Any], Any]) -> None
|
|
||||||
self._fname = f.__name__
|
self._fname = f.__name__
|
||||||
self._f = f
|
self._f = f
|
||||||
|
|
||||||
def __get__(self, obj, owner):
|
def __get__(self, obj: Any, owner: Type[Any]) -> Any:
|
||||||
# type: (Any, Type[Any]) -> Any
|
assert obj is not None, f"call {self._fname} on an instance"
|
||||||
assert obj is not None, "call {} on an instance".format(self._fname)
|
|
||||||
ret = obj.__dict__[self._fname] = self._f(obj)
|
ret = obj.__dict__[self._fname] = self._f(obj)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class LinuxDistribution(object):
|
class LinuxDistribution:
|
||||||
"""
|
"""
|
||||||
Provides information about a OS distribution.
|
Provides information about a OS distribution.
|
||||||
|
|
||||||
@@ -653,13 +662,13 @@ class LinuxDistribution(object):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
include_lsb=True,
|
include_lsb: Optional[bool] = None,
|
||||||
os_release_file="",
|
os_release_file: str = "",
|
||||||
distro_release_file="",
|
distro_release_file: str = "",
|
||||||
include_uname=True,
|
include_uname: Optional[bool] = None,
|
||||||
root_dir=None,
|
root_dir: Optional[str] = None,
|
||||||
):
|
include_oslevel: Optional[bool] = None,
|
||||||
# type: (bool, str, str, bool, Optional[str]) -> None
|
) -> None:
|
||||||
"""
|
"""
|
||||||
The initialization method of this class gathers information from the
|
The initialization method of this class gathers information from the
|
||||||
available data sources, and stores that in private instance attributes.
|
available data sources, and stores that in private instance attributes.
|
||||||
@@ -699,7 +708,13 @@ def __init__(
|
|||||||
be empty.
|
be empty.
|
||||||
|
|
||||||
* ``root_dir`` (string): The absolute path to the root directory to use
|
* ``root_dir`` (string): The absolute path to the root directory to use
|
||||||
to find distro-related information files.
|
to find distro-related information files. Note that ``include_*``
|
||||||
|
parameters must not be enabled in combination with ``root_dir``.
|
||||||
|
|
||||||
|
* ``include_oslevel`` (bool): Controls whether (AIX) oslevel command
|
||||||
|
output is included as a data source. If the oslevel command is not
|
||||||
|
available in the program execution path the data source will be
|
||||||
|
empty.
|
||||||
|
|
||||||
Public instance attributes:
|
Public instance attributes:
|
||||||
|
|
||||||
@@ -718,14 +733,21 @@ def __init__(
|
|||||||
parameter. This controls whether the uname information will
|
parameter. This controls whether the uname information will
|
||||||
be loaded.
|
be loaded.
|
||||||
|
|
||||||
|
* ``include_oslevel`` (bool): The result of the ``include_oslevel``
|
||||||
|
parameter. This controls whether (AIX) oslevel information will be
|
||||||
|
loaded.
|
||||||
|
|
||||||
|
* ``root_dir`` (string): The result of the ``root_dir`` parameter.
|
||||||
|
The absolute path to the root directory to use to find distro-related
|
||||||
|
information files.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
|
|
||||||
* :py:exc:`IOError`: Some I/O issue with an os-release file or distro
|
* :py:exc:`ValueError`: Initialization parameters combination is not
|
||||||
release file.
|
supported.
|
||||||
|
|
||||||
* :py:exc:`subprocess.CalledProcessError`: The lsb_release command had
|
* :py:exc:`OSError`: Some I/O issue with an os-release file or distro
|
||||||
some issue (other than not being available in the program execution
|
release file.
|
||||||
path).
|
|
||||||
|
|
||||||
* :py:exc:`UnicodeError`: A data source has unexpected characters or
|
* :py:exc:`UnicodeError`: A data source has unexpected characters or
|
||||||
uses an unexpected encoding.
|
uses an unexpected encoding.
|
||||||
@@ -754,11 +776,24 @@ def __init__(
|
|||||||
self.os_release_file = usr_lib_os_release_file
|
self.os_release_file = usr_lib_os_release_file
|
||||||
|
|
||||||
self.distro_release_file = distro_release_file or "" # updated later
|
self.distro_release_file = distro_release_file or "" # updated later
|
||||||
self.include_lsb = include_lsb
|
|
||||||
self.include_uname = include_uname
|
|
||||||
|
|
||||||
def __repr__(self):
|
is_root_dir_defined = root_dir is not None
|
||||||
# type: () -> str
|
if is_root_dir_defined and (include_lsb or include_uname or include_oslevel):
|
||||||
|
raise ValueError(
|
||||||
|
"Including subprocess data sources from specific root_dir is disallowed"
|
||||||
|
" to prevent false information"
|
||||||
|
)
|
||||||
|
self.include_lsb = (
|
||||||
|
include_lsb if include_lsb is not None else not is_root_dir_defined
|
||||||
|
)
|
||||||
|
self.include_uname = (
|
||||||
|
include_uname if include_uname is not None else not is_root_dir_defined
|
||||||
|
)
|
||||||
|
self.include_oslevel = (
|
||||||
|
include_oslevel if include_oslevel is not None else not is_root_dir_defined
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
"""Return repr of all info"""
|
"""Return repr of all info"""
|
||||||
return (
|
return (
|
||||||
"LinuxDistribution("
|
"LinuxDistribution("
|
||||||
@@ -766,14 +801,18 @@ def __repr__(self):
|
|||||||
"distro_release_file={self.distro_release_file!r}, "
|
"distro_release_file={self.distro_release_file!r}, "
|
||||||
"include_lsb={self.include_lsb!r}, "
|
"include_lsb={self.include_lsb!r}, "
|
||||||
"include_uname={self.include_uname!r}, "
|
"include_uname={self.include_uname!r}, "
|
||||||
|
"include_oslevel={self.include_oslevel!r}, "
|
||||||
|
"root_dir={self.root_dir!r}, "
|
||||||
"_os_release_info={self._os_release_info!r}, "
|
"_os_release_info={self._os_release_info!r}, "
|
||||||
"_lsb_release_info={self._lsb_release_info!r}, "
|
"_lsb_release_info={self._lsb_release_info!r}, "
|
||||||
"_distro_release_info={self._distro_release_info!r}, "
|
"_distro_release_info={self._distro_release_info!r}, "
|
||||||
"_uname_info={self._uname_info!r})".format(self=self)
|
"_uname_info={self._uname_info!r}, "
|
||||||
|
"_oslevel_info={self._oslevel_info!r})".format(self=self)
|
||||||
)
|
)
|
||||||
|
|
||||||
def linux_distribution(self, full_distribution_name=True):
|
def linux_distribution(
|
||||||
# type: (bool) -> Tuple[str, str, str]
|
self, full_distribution_name: bool = True
|
||||||
|
) -> Tuple[str, str, str]:
|
||||||
"""
|
"""
|
||||||
Return information about the OS distribution that is compatible
|
Return information about the OS distribution that is compatible
|
||||||
with Python's :func:`platform.linux_distribution`, supporting a subset
|
with Python's :func:`platform.linux_distribution`, supporting a subset
|
||||||
@@ -784,18 +823,16 @@ def linux_distribution(self, full_distribution_name=True):
|
|||||||
return (
|
return (
|
||||||
self.name() if full_distribution_name else self.id(),
|
self.name() if full_distribution_name else self.id(),
|
||||||
self.version(),
|
self.version(),
|
||||||
self.codename(),
|
self._os_release_info.get("release_codename") or self.codename(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def id(self):
|
def id(self) -> str:
|
||||||
# type: () -> str
|
|
||||||
"""Return the distro ID of the OS distribution, as a string.
|
"""Return the distro ID of the OS distribution, as a string.
|
||||||
|
|
||||||
For details, see :func:`distro.id`.
|
For details, see :func:`distro.id`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def normalize(distro_id, table):
|
def normalize(distro_id: str, table: Dict[str, str]) -> str:
|
||||||
# type: (str, Dict[str, str]) -> str
|
|
||||||
distro_id = distro_id.lower().replace(" ", "_")
|
distro_id = distro_id.lower().replace(" ", "_")
|
||||||
return table.get(distro_id, distro_id)
|
return table.get(distro_id, distro_id)
|
||||||
|
|
||||||
@@ -817,8 +854,7 @@ def normalize(distro_id, table):
|
|||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def name(self, pretty=False):
|
def name(self, pretty: bool = False) -> str:
|
||||||
# type: (bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the name of the OS distribution, as a string.
|
Return the name of the OS distribution, as a string.
|
||||||
|
|
||||||
@@ -838,11 +874,10 @@ def name(self, pretty=False):
|
|||||||
name = self.distro_release_attr("name") or self.uname_attr("name")
|
name = self.distro_release_attr("name") or self.uname_attr("name")
|
||||||
version = self.version(pretty=True)
|
version = self.version(pretty=True)
|
||||||
if version:
|
if version:
|
||||||
name = name + " " + version
|
name = f"{name} {version}"
|
||||||
return name or ""
|
return name or ""
|
||||||
|
|
||||||
def version(self, pretty=False, best=False):
|
def version(self, pretty: bool = False, best: bool = False) -> str:
|
||||||
# type: (bool, bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the version of the OS distribution, as a string.
|
Return the version of the OS distribution, as a string.
|
||||||
|
|
||||||
@@ -860,6 +895,12 @@ def version(self, pretty=False, best=False):
|
|||||||
).get("version_id", ""),
|
).get("version_id", ""),
|
||||||
self.uname_attr("release"),
|
self.uname_attr("release"),
|
||||||
]
|
]
|
||||||
|
if self.uname_attr("id").startswith("aix"):
|
||||||
|
# On AIX platforms, prefer oslevel command output.
|
||||||
|
versions.insert(0, self.oslevel_info())
|
||||||
|
elif self.id() == "debian" or "debian" in self.like().split():
|
||||||
|
# On Debian-like, add debian_version file content to candidates list.
|
||||||
|
versions.append(self._debian_version)
|
||||||
version = ""
|
version = ""
|
||||||
if best:
|
if best:
|
||||||
# This algorithm uses the last version in priority order that has
|
# This algorithm uses the last version in priority order that has
|
||||||
@@ -875,11 +916,10 @@ def version(self, pretty=False, best=False):
|
|||||||
version = v
|
version = v
|
||||||
break
|
break
|
||||||
if pretty and version and self.codename():
|
if pretty and version and self.codename():
|
||||||
version = "{0} ({1})".format(version, self.codename())
|
version = f"{version} ({self.codename()})"
|
||||||
return version
|
return version
|
||||||
|
|
||||||
def version_parts(self, best=False):
|
def version_parts(self, best: bool = False) -> Tuple[str, str, str]:
|
||||||
# type: (bool) -> Tuple[str, str, str]
|
|
||||||
"""
|
"""
|
||||||
Return the version of the OS distribution, as a tuple of version
|
Return the version of the OS distribution, as a tuple of version
|
||||||
numbers.
|
numbers.
|
||||||
@@ -895,8 +935,7 @@ def version_parts(self, best=False):
|
|||||||
return major, minor or "", build_number or ""
|
return major, minor or "", build_number or ""
|
||||||
return "", "", ""
|
return "", "", ""
|
||||||
|
|
||||||
def major_version(self, best=False):
|
def major_version(self, best: bool = False) -> str:
|
||||||
# type: (bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the major version number of the current distribution.
|
Return the major version number of the current distribution.
|
||||||
|
|
||||||
@@ -904,8 +943,7 @@ def major_version(self, best=False):
|
|||||||
"""
|
"""
|
||||||
return self.version_parts(best)[0]
|
return self.version_parts(best)[0]
|
||||||
|
|
||||||
def minor_version(self, best=False):
|
def minor_version(self, best: bool = False) -> str:
|
||||||
# type: (bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the minor version number of the current distribution.
|
Return the minor version number of the current distribution.
|
||||||
|
|
||||||
@@ -913,8 +951,7 @@ def minor_version(self, best=False):
|
|||||||
"""
|
"""
|
||||||
return self.version_parts(best)[1]
|
return self.version_parts(best)[1]
|
||||||
|
|
||||||
def build_number(self, best=False):
|
def build_number(self, best: bool = False) -> str:
|
||||||
# type: (bool) -> str
|
|
||||||
"""
|
"""
|
||||||
Return the build number of the current distribution.
|
Return the build number of the current distribution.
|
||||||
|
|
||||||
@@ -922,8 +959,7 @@ def build_number(self, best=False):
|
|||||||
"""
|
"""
|
||||||
return self.version_parts(best)[2]
|
return self.version_parts(best)[2]
|
||||||
|
|
||||||
def like(self):
|
def like(self) -> str:
|
||||||
# type: () -> str
|
|
||||||
"""
|
"""
|
||||||
Return the IDs of distributions that are like the OS distribution.
|
Return the IDs of distributions that are like the OS distribution.
|
||||||
|
|
||||||
@@ -931,8 +967,7 @@ def like(self):
|
|||||||
"""
|
"""
|
||||||
return self.os_release_attr("id_like") or ""
|
return self.os_release_attr("id_like") or ""
|
||||||
|
|
||||||
def codename(self):
|
def codename(self) -> str:
|
||||||
# type: () -> str
|
|
||||||
"""
|
"""
|
||||||
Return the codename of the OS distribution.
|
Return the codename of the OS distribution.
|
||||||
|
|
||||||
@@ -949,8 +984,7 @@ def codename(self):
|
|||||||
or ""
|
or ""
|
||||||
)
|
)
|
||||||
|
|
||||||
def info(self, pretty=False, best=False):
|
def info(self, pretty: bool = False, best: bool = False) -> InfoDict:
|
||||||
# type: (bool, bool) -> InfoDict
|
|
||||||
"""
|
"""
|
||||||
Return certain machine-readable information about the OS
|
Return certain machine-readable information about the OS
|
||||||
distribution.
|
distribution.
|
||||||
@@ -969,8 +1003,7 @@ def info(self, pretty=False, best=False):
|
|||||||
codename=self.codename(),
|
codename=self.codename(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def os_release_info(self):
|
def os_release_info(self) -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Return a dictionary containing key-value pairs for the information
|
Return a dictionary containing key-value pairs for the information
|
||||||
items from the os-release file data source of the OS distribution.
|
items from the os-release file data source of the OS distribution.
|
||||||
@@ -979,8 +1012,7 @@ def os_release_info(self):
|
|||||||
"""
|
"""
|
||||||
return self._os_release_info
|
return self._os_release_info
|
||||||
|
|
||||||
def lsb_release_info(self):
|
def lsb_release_info(self) -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Return a dictionary containing key-value pairs for the information
|
Return a dictionary containing key-value pairs for the information
|
||||||
items from the lsb_release command data source of the OS
|
items from the lsb_release command data source of the OS
|
||||||
@@ -990,8 +1022,7 @@ def lsb_release_info(self):
|
|||||||
"""
|
"""
|
||||||
return self._lsb_release_info
|
return self._lsb_release_info
|
||||||
|
|
||||||
def distro_release_info(self):
|
def distro_release_info(self) -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Return a dictionary containing key-value pairs for the information
|
Return a dictionary containing key-value pairs for the information
|
||||||
items from the distro release file data source of the OS
|
items from the distro release file data source of the OS
|
||||||
@@ -1001,8 +1032,7 @@ def distro_release_info(self):
|
|||||||
"""
|
"""
|
||||||
return self._distro_release_info
|
return self._distro_release_info
|
||||||
|
|
||||||
def uname_info(self):
|
def uname_info(self) -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Return a dictionary containing key-value pairs for the information
|
Return a dictionary containing key-value pairs for the information
|
||||||
items from the uname command data source of the OS distribution.
|
items from the uname command data source of the OS distribution.
|
||||||
@@ -1011,8 +1041,13 @@ def uname_info(self):
|
|||||||
"""
|
"""
|
||||||
return self._uname_info
|
return self._uname_info
|
||||||
|
|
||||||
def os_release_attr(self, attribute):
|
def oslevel_info(self) -> str:
|
||||||
# type: (str) -> str
|
"""
|
||||||
|
Return AIX' oslevel command output.
|
||||||
|
"""
|
||||||
|
return self._oslevel_info
|
||||||
|
|
||||||
|
def os_release_attr(self, attribute: str) -> str:
|
||||||
"""
|
"""
|
||||||
Return a single named information item from the os-release file data
|
Return a single named information item from the os-release file data
|
||||||
source of the OS distribution.
|
source of the OS distribution.
|
||||||
@@ -1021,8 +1056,7 @@ def os_release_attr(self, attribute):
|
|||||||
"""
|
"""
|
||||||
return self._os_release_info.get(attribute, "")
|
return self._os_release_info.get(attribute, "")
|
||||||
|
|
||||||
def lsb_release_attr(self, attribute):
|
def lsb_release_attr(self, attribute: str) -> str:
|
||||||
# type: (str) -> str
|
|
||||||
"""
|
"""
|
||||||
Return a single named information item from the lsb_release command
|
Return a single named information item from the lsb_release command
|
||||||
output data source of the OS distribution.
|
output data source of the OS distribution.
|
||||||
@@ -1031,8 +1065,7 @@ def lsb_release_attr(self, attribute):
|
|||||||
"""
|
"""
|
||||||
return self._lsb_release_info.get(attribute, "")
|
return self._lsb_release_info.get(attribute, "")
|
||||||
|
|
||||||
def distro_release_attr(self, attribute):
|
def distro_release_attr(self, attribute: str) -> str:
|
||||||
# type: (str) -> str
|
|
||||||
"""
|
"""
|
||||||
Return a single named information item from the distro release file
|
Return a single named information item from the distro release file
|
||||||
data source of the OS distribution.
|
data source of the OS distribution.
|
||||||
@@ -1041,8 +1074,7 @@ def distro_release_attr(self, attribute):
|
|||||||
"""
|
"""
|
||||||
return self._distro_release_info.get(attribute, "")
|
return self._distro_release_info.get(attribute, "")
|
||||||
|
|
||||||
def uname_attr(self, attribute):
|
def uname_attr(self, attribute: str) -> str:
|
||||||
# type: (str) -> str
|
|
||||||
"""
|
"""
|
||||||
Return a single named information item from the uname command
|
Return a single named information item from the uname command
|
||||||
output data source of the OS distribution.
|
output data source of the OS distribution.
|
||||||
@@ -1052,8 +1084,7 @@ def uname_attr(self, attribute):
|
|||||||
return self._uname_info.get(attribute, "")
|
return self._uname_info.get(attribute, "")
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def _os_release_info(self):
|
def _os_release_info(self) -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Get the information items from the specified os-release file.
|
Get the information items from the specified os-release file.
|
||||||
|
|
||||||
@@ -1061,13 +1092,12 @@ def _os_release_info(self):
|
|||||||
A dictionary containing all information items.
|
A dictionary containing all information items.
|
||||||
"""
|
"""
|
||||||
if os.path.isfile(self.os_release_file):
|
if os.path.isfile(self.os_release_file):
|
||||||
with open(self.os_release_file) as release_file:
|
with open(self.os_release_file, encoding="utf-8") as release_file:
|
||||||
return self._parse_os_release_content(release_file)
|
return self._parse_os_release_content(release_file)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_os_release_content(lines):
|
def _parse_os_release_content(lines: TextIO) -> Dict[str, str]:
|
||||||
# type: (TextIO) -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Parse the lines of an os-release file.
|
Parse the lines of an os-release file.
|
||||||
|
|
||||||
@@ -1084,16 +1114,6 @@ def _parse_os_release_content(lines):
|
|||||||
lexer = shlex.shlex(lines, posix=True)
|
lexer = shlex.shlex(lines, posix=True)
|
||||||
lexer.whitespace_split = True
|
lexer.whitespace_split = True
|
||||||
|
|
||||||
# The shlex module defines its `wordchars` variable using literals,
|
|
||||||
# making it dependent on the encoding of the Python source file.
|
|
||||||
# In Python 2.6 and 2.7, the shlex source file is encoded in
|
|
||||||
# 'iso-8859-1', and the `wordchars` variable is defined as a byte
|
|
||||||
# string. This causes a UnicodeDecodeError to be raised when the
|
|
||||||
# parsed content is a unicode object. The following fix resolves that
|
|
||||||
# (... but it should be fixed in shlex...):
|
|
||||||
if sys.version_info[0] == 2 and isinstance(lexer.wordchars, bytes):
|
|
||||||
lexer.wordchars = lexer.wordchars.decode("iso-8859-1")
|
|
||||||
|
|
||||||
tokens = list(lexer)
|
tokens = list(lexer)
|
||||||
for token in tokens:
|
for token in tokens:
|
||||||
# At this point, all shell-like parsing has been done (i.e.
|
# At this point, all shell-like parsing has been done (i.e.
|
||||||
@@ -1102,12 +1122,17 @@ def _parse_os_release_content(lines):
|
|||||||
# stripped, etc.), so the tokens are now either:
|
# stripped, etc.), so the tokens are now either:
|
||||||
# * variable assignments: var=value
|
# * variable assignments: var=value
|
||||||
# * commands or their arguments (not allowed in os-release)
|
# * commands or their arguments (not allowed in os-release)
|
||||||
|
# Ignore any tokens that are not variable assignments
|
||||||
if "=" in token:
|
if "=" in token:
|
||||||
k, v = token.split("=", 1)
|
k, v = token.split("=", 1)
|
||||||
props[k.lower()] = v
|
props[k.lower()] = v
|
||||||
else:
|
|
||||||
# Ignore any tokens that are not variable assignments
|
if "version" in props:
|
||||||
pass
|
# extract release codename (if any) from version attribute
|
||||||
|
match = re.search(r"\((\D+)\)|,\s*(\D+)", props["version"])
|
||||||
|
if match:
|
||||||
|
release_codename = match.group(1) or match.group(2)
|
||||||
|
props["codename"] = props["release_codename"] = release_codename
|
||||||
|
|
||||||
if "version_codename" in props:
|
if "version_codename" in props:
|
||||||
# os-release added a version_codename field. Use that in
|
# os-release added a version_codename field. Use that in
|
||||||
@@ -1118,22 +1143,11 @@ def _parse_os_release_content(lines):
|
|||||||
elif "ubuntu_codename" in props:
|
elif "ubuntu_codename" in props:
|
||||||
# Same as above but a non-standard field name used on older Ubuntus
|
# Same as above but a non-standard field name used on older Ubuntus
|
||||||
props["codename"] = props["ubuntu_codename"]
|
props["codename"] = props["ubuntu_codename"]
|
||||||
elif "version" in props:
|
|
||||||
# If there is no version_codename, parse it from the version
|
|
||||||
match = re.search(r"(\(\D+\))|,(\s+)?\D+", props["version"])
|
|
||||||
if match:
|
|
||||||
codename = match.group()
|
|
||||||
codename = codename.strip("()")
|
|
||||||
codename = codename.strip(",")
|
|
||||||
codename = codename.strip()
|
|
||||||
# codename appears within paranthese.
|
|
||||||
props["codename"] = codename
|
|
||||||
|
|
||||||
return props
|
return props
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def _lsb_release_info(self):
|
def _lsb_release_info(self) -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Get the information items from the lsb_release command output.
|
Get the information items from the lsb_release command output.
|
||||||
|
|
||||||
@@ -1142,19 +1156,17 @@ def _lsb_release_info(self):
|
|||||||
"""
|
"""
|
||||||
if not self.include_lsb:
|
if not self.include_lsb:
|
||||||
return {}
|
return {}
|
||||||
with open(os.devnull, "wb") as devnull:
|
try:
|
||||||
try:
|
cmd = ("lsb_release", "-a")
|
||||||
cmd = ("lsb_release", "-a")
|
stdout = subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
|
||||||
stdout = subprocess.check_output(cmd, stderr=devnull)
|
# Command not found or lsb_release returned error
|
||||||
# Command not found or lsb_release returned error
|
except (OSError, subprocess.CalledProcessError):
|
||||||
except (OSError, subprocess.CalledProcessError):
|
return {}
|
||||||
return {}
|
|
||||||
content = self._to_str(stdout).splitlines()
|
content = self._to_str(stdout).splitlines()
|
||||||
return self._parse_lsb_release_content(content)
|
return self._parse_lsb_release_content(content)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_lsb_release_content(lines):
|
def _parse_lsb_release_content(lines: Iterable[str]) -> Dict[str, str]:
|
||||||
# type: (Iterable[str]) -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Parse the output of the lsb_release command.
|
Parse the output of the lsb_release command.
|
||||||
|
|
||||||
@@ -1178,20 +1190,41 @@ def _parse_lsb_release_content(lines):
|
|||||||
return props
|
return props
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def _uname_info(self):
|
def _uname_info(self) -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
if not self.include_uname:
|
||||||
with open(os.devnull, "wb") as devnull:
|
return {}
|
||||||
try:
|
try:
|
||||||
cmd = ("uname", "-rs")
|
cmd = ("uname", "-rs")
|
||||||
stdout = subprocess.check_output(cmd, stderr=devnull)
|
stdout = subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
|
||||||
except OSError:
|
except OSError:
|
||||||
return {}
|
return {}
|
||||||
content = self._to_str(stdout).splitlines()
|
content = self._to_str(stdout).splitlines()
|
||||||
return self._parse_uname_content(content)
|
return self._parse_uname_content(content)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def _oslevel_info(self) -> str:
|
||||||
|
if not self.include_oslevel:
|
||||||
|
return ""
|
||||||
|
try:
|
||||||
|
stdout = subprocess.check_output("oslevel", stderr=subprocess.DEVNULL)
|
||||||
|
except (OSError, subprocess.CalledProcessError):
|
||||||
|
return ""
|
||||||
|
return self._to_str(stdout).strip()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def _debian_version(self) -> str:
|
||||||
|
try:
|
||||||
|
with open(
|
||||||
|
os.path.join(self.etc_dir, "debian_version"), encoding="ascii"
|
||||||
|
) as fp:
|
||||||
|
return fp.readline().rstrip()
|
||||||
|
except FileNotFoundError:
|
||||||
|
return ""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_uname_content(lines):
|
def _parse_uname_content(lines: Sequence[str]) -> Dict[str, str]:
|
||||||
# type: (Sequence[str]) -> Dict[str, str]
|
if not lines:
|
||||||
|
return {}
|
||||||
props = {}
|
props = {}
|
||||||
match = re.search(r"^([^\s]+)\s+([\d\.]+)", lines[0].strip())
|
match = re.search(r"^([^\s]+)\s+([\d\.]+)", lines[0].strip())
|
||||||
if match:
|
if match:
|
||||||
@@ -1208,23 +1241,12 @@ def _parse_uname_content(lines):
|
|||||||
return props
|
return props
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _to_str(text):
|
def _to_str(bytestring: bytes) -> str:
|
||||||
# type: (Union[bytes, str]) -> str
|
|
||||||
encoding = sys.getfilesystemencoding()
|
encoding = sys.getfilesystemencoding()
|
||||||
encoding = "utf-8" if encoding == "ascii" else encoding
|
return bytestring.decode(encoding)
|
||||||
|
|
||||||
if sys.version_info[0] >= 3:
|
|
||||||
if isinstance(text, bytes):
|
|
||||||
return text.decode(encoding)
|
|
||||||
else:
|
|
||||||
if isinstance(text, unicode): # noqa
|
|
||||||
return text.encode(encoding)
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def _distro_release_info(self):
|
def _distro_release_info(self) -> Dict[str, str]:
|
||||||
# type: () -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Get the information items from the specified distro release file.
|
Get the information items from the specified distro release file.
|
||||||
|
|
||||||
@@ -1241,14 +1263,14 @@ def _distro_release_info(self):
|
|||||||
# file), because we want to use what was specified as best as
|
# file), because we want to use what was specified as best as
|
||||||
# possible.
|
# possible.
|
||||||
match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename)
|
match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename)
|
||||||
if "name" in distro_info and "cloudlinux" in distro_info["name"].lower():
|
|
||||||
distro_info["id"] = "cloudlinux"
|
|
||||||
elif match:
|
|
||||||
distro_info["id"] = match.group(1)
|
|
||||||
return distro_info
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
basenames = os.listdir(self.etc_dir)
|
basenames = [
|
||||||
|
basename
|
||||||
|
for basename in os.listdir(self.etc_dir)
|
||||||
|
if basename not in _DISTRO_RELEASE_IGNORE_BASENAMES
|
||||||
|
and os.path.isfile(os.path.join(self.etc_dir, basename))
|
||||||
|
]
|
||||||
# We sort for repeatability in cases where there are multiple
|
# We sort for repeatability in cases where there are multiple
|
||||||
# distro specific files; e.g. CentOS, Oracle, Enterprise all
|
# distro specific files; e.g. CentOS, Oracle, Enterprise all
|
||||||
# containing `redhat-release` on top of their own.
|
# containing `redhat-release` on top of their own.
|
||||||
@@ -1258,41 +1280,31 @@ def _distro_release_info(self):
|
|||||||
# sure about the *-release files. Check common entries of
|
# sure about the *-release files. Check common entries of
|
||||||
# /etc for information. If they turn out to not be there the
|
# /etc for information. If they turn out to not be there the
|
||||||
# error is handled in `_parse_distro_release_file()`.
|
# error is handled in `_parse_distro_release_file()`.
|
||||||
basenames = [
|
basenames = _DISTRO_RELEASE_BASENAMES
|
||||||
"SuSE-release",
|
|
||||||
"arch-release",
|
|
||||||
"base-release",
|
|
||||||
"centos-release",
|
|
||||||
"fedora-release",
|
|
||||||
"gentoo-release",
|
|
||||||
"mageia-release",
|
|
||||||
"mandrake-release",
|
|
||||||
"mandriva-release",
|
|
||||||
"mandrivalinux-release",
|
|
||||||
"manjaro-release",
|
|
||||||
"oracle-release",
|
|
||||||
"redhat-release",
|
|
||||||
"sl-release",
|
|
||||||
"slackware-version",
|
|
||||||
]
|
|
||||||
for basename in basenames:
|
for basename in basenames:
|
||||||
if basename in _DISTRO_RELEASE_IGNORE_BASENAMES:
|
|
||||||
continue
|
|
||||||
match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename)
|
match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename)
|
||||||
if match:
|
if match is None:
|
||||||
filepath = os.path.join(self.etc_dir, basename)
|
continue
|
||||||
distro_info = self._parse_distro_release_file(filepath)
|
filepath = os.path.join(self.etc_dir, basename)
|
||||||
if "name" in distro_info:
|
distro_info = self._parse_distro_release_file(filepath)
|
||||||
# The name is always present if the pattern matches
|
# The name is always present if the pattern matches.
|
||||||
self.distro_release_file = filepath
|
if "name" not in distro_info:
|
||||||
distro_info["id"] = match.group(1)
|
continue
|
||||||
if "cloudlinux" in distro_info["name"].lower():
|
self.distro_release_file = filepath
|
||||||
distro_info["id"] = "cloudlinux"
|
break
|
||||||
return distro_info
|
else: # the loop didn't "break": no candidate.
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def _parse_distro_release_file(self, filepath):
|
if match is not None:
|
||||||
# type: (str) -> Dict[str, str]
|
distro_info["id"] = match.group(1)
|
||||||
|
|
||||||
|
# CloudLinux < 7: manually enrich info with proper id.
|
||||||
|
if "cloudlinux" in distro_info.get("name", "").lower():
|
||||||
|
distro_info["id"] = "cloudlinux"
|
||||||
|
|
||||||
|
return distro_info
|
||||||
|
|
||||||
|
def _parse_distro_release_file(self, filepath: str) -> Dict[str, str]:
|
||||||
"""
|
"""
|
||||||
Parse a distro release file.
|
Parse a distro release file.
|
||||||
|
|
||||||
@@ -1304,19 +1316,18 @@ def _parse_distro_release_file(self, filepath):
|
|||||||
A dictionary containing all information items.
|
A dictionary containing all information items.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
with open(filepath) as fp:
|
with open(filepath, encoding="utf-8") as fp:
|
||||||
# Only parse the first line. For instance, on SLES there
|
# Only parse the first line. For instance, on SLES there
|
||||||
# are multiple lines. We don't want them...
|
# are multiple lines. We don't want them...
|
||||||
return self._parse_distro_release_content(fp.readline())
|
return self._parse_distro_release_content(fp.readline())
|
||||||
except (OSError, IOError):
|
except OSError:
|
||||||
# Ignore not being able to read a specific, seemingly version
|
# Ignore not being able to read a specific, seemingly version
|
||||||
# related file.
|
# related file.
|
||||||
# See https://github.com/python-distro/distro/issues/162
|
# See https://github.com/python-distro/distro/issues/162
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_distro_release_content(line):
|
def _parse_distro_release_content(line: str) -> Dict[str, str]:
|
||||||
# type: (str) -> Dict[str, str]
|
|
||||||
"""
|
"""
|
||||||
Parse a line from a distro release file.
|
Parse a line from a distro release file.
|
||||||
|
|
||||||
@@ -1344,8 +1355,7 @@ def _parse_distro_release_content(line):
|
|||||||
_distro = LinuxDistribution()
|
_distro = LinuxDistribution()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
# type: () -> None
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
logger.addHandler(logging.StreamHandler(sys.stdout))
|
logger.addHandler(logging.StreamHandler(sys.stdout))
|
||||||
@@ -1367,7 +1377,10 @@ def main():
|
|||||||
|
|
||||||
if args.root_dir:
|
if args.root_dir:
|
||||||
dist = LinuxDistribution(
|
dist = LinuxDistribution(
|
||||||
include_lsb=False, include_uname=False, root_dir=args.root_dir
|
include_lsb=False,
|
||||||
|
include_uname=False,
|
||||||
|
include_oslevel=False,
|
||||||
|
root_dir=args.root_dir,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
dist = _distro
|
dist = _distro
|
0
lib/spack/external/_vendoring/distro/py.typed
vendored
Normal file
0
lib/spack/external/_vendoring/distro/py.typed
vendored
Normal file
45
lib/spack/external/_vendoring/jinja2/__init__.py
vendored
Normal file
45
lib/spack/external/_vendoring/jinja2/__init__.py
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
"""Jinja is a template engine written in pure Python. It provides a
|
||||||
|
non-XML syntax that supports inline expressions and an optional
|
||||||
|
sandboxed environment.
|
||||||
|
"""
|
||||||
|
from .bccache import BytecodeCache as BytecodeCache
|
||||||
|
from .bccache import FileSystemBytecodeCache as FileSystemBytecodeCache
|
||||||
|
from .bccache import MemcachedBytecodeCache as MemcachedBytecodeCache
|
||||||
|
from .environment import Environment as Environment
|
||||||
|
from .environment import Template as Template
|
||||||
|
from .exceptions import TemplateAssertionError as TemplateAssertionError
|
||||||
|
from .exceptions import TemplateError as TemplateError
|
||||||
|
from .exceptions import TemplateNotFound as TemplateNotFound
|
||||||
|
from .exceptions import TemplateRuntimeError as TemplateRuntimeError
|
||||||
|
from .exceptions import TemplatesNotFound as TemplatesNotFound
|
||||||
|
from .exceptions import TemplateSyntaxError as TemplateSyntaxError
|
||||||
|
from .exceptions import UndefinedError as UndefinedError
|
||||||
|
from .filters import contextfilter
|
||||||
|
from .filters import environmentfilter
|
||||||
|
from .filters import evalcontextfilter
|
||||||
|
from .loaders import BaseLoader as BaseLoader
|
||||||
|
from .loaders import ChoiceLoader as ChoiceLoader
|
||||||
|
from .loaders import DictLoader as DictLoader
|
||||||
|
from .loaders import FileSystemLoader as FileSystemLoader
|
||||||
|
from .loaders import FunctionLoader as FunctionLoader
|
||||||
|
from .loaders import ModuleLoader as ModuleLoader
|
||||||
|
from .loaders import PackageLoader as PackageLoader
|
||||||
|
from .loaders import PrefixLoader as PrefixLoader
|
||||||
|
from .runtime import ChainableUndefined as ChainableUndefined
|
||||||
|
from .runtime import DebugUndefined as DebugUndefined
|
||||||
|
from .runtime import make_logging_undefined as make_logging_undefined
|
||||||
|
from .runtime import StrictUndefined as StrictUndefined
|
||||||
|
from .runtime import Undefined as Undefined
|
||||||
|
from .utils import clear_caches as clear_caches
|
||||||
|
from .utils import contextfunction
|
||||||
|
from .utils import environmentfunction
|
||||||
|
from .utils import escape
|
||||||
|
from .utils import evalcontextfunction
|
||||||
|
from .utils import is_undefined as is_undefined
|
||||||
|
from .utils import Markup
|
||||||
|
from .utils import pass_context as pass_context
|
||||||
|
from .utils import pass_environment as pass_environment
|
||||||
|
from .utils import pass_eval_context as pass_eval_context
|
||||||
|
from .utils import select_autoescape as select_autoescape
|
||||||
|
|
||||||
|
__version__ = "3.0.3"
|
75
lib/spack/external/_vendoring/jinja2/async_utils.py
vendored
Normal file
75
lib/spack/external/_vendoring/jinja2/async_utils.py
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import inspect
|
||||||
|
import typing as t
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
from .utils import _PassArg
|
||||||
|
from .utils import pass_eval_context
|
||||||
|
|
||||||
|
V = t.TypeVar("V")
|
||||||
|
|
||||||
|
|
||||||
|
def async_variant(normal_func): # type: ignore
|
||||||
|
def decorator(async_func): # type: ignore
|
||||||
|
pass_arg = _PassArg.from_obj(normal_func)
|
||||||
|
need_eval_context = pass_arg is None
|
||||||
|
|
||||||
|
if pass_arg is _PassArg.environment:
|
||||||
|
|
||||||
|
def is_async(args: t.Any) -> bool:
|
||||||
|
return t.cast(bool, args[0].is_async)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
def is_async(args: t.Any) -> bool:
|
||||||
|
return t.cast(bool, args[0].environment.is_async)
|
||||||
|
|
||||||
|
@wraps(normal_func)
|
||||||
|
def wrapper(*args, **kwargs): # type: ignore
|
||||||
|
b = is_async(args)
|
||||||
|
|
||||||
|
if need_eval_context:
|
||||||
|
args = args[1:]
|
||||||
|
|
||||||
|
if b:
|
||||||
|
return async_func(*args, **kwargs)
|
||||||
|
|
||||||
|
return normal_func(*args, **kwargs)
|
||||||
|
|
||||||
|
if need_eval_context:
|
||||||
|
wrapper = pass_eval_context(wrapper)
|
||||||
|
|
||||||
|
wrapper.jinja_async_variant = True
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
_common_primitives = {int, float, bool, str, list, dict, tuple, type(None)}
|
||||||
|
|
||||||
|
|
||||||
|
async def auto_await(value: t.Union[t.Awaitable["V"], "V"]) -> "V":
|
||||||
|
# Avoid a costly call to isawaitable
|
||||||
|
if type(value) in _common_primitives:
|
||||||
|
return t.cast("V", value)
|
||||||
|
|
||||||
|
if inspect.isawaitable(value):
|
||||||
|
return await t.cast("t.Awaitable[V]", value)
|
||||||
|
|
||||||
|
return t.cast("V", value)
|
||||||
|
|
||||||
|
|
||||||
|
async def auto_aiter(
|
||||||
|
iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]",
|
||||||
|
) -> "t.AsyncIterator[V]":
|
||||||
|
if hasattr(iterable, "__aiter__"):
|
||||||
|
async for item in t.cast("t.AsyncIterable[V]", iterable):
|
||||||
|
yield item
|
||||||
|
else:
|
||||||
|
for item in t.cast("t.Iterable[V]", iterable):
|
||||||
|
yield item
|
||||||
|
|
||||||
|
|
||||||
|
async def auto_to_list(
|
||||||
|
value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]",
|
||||||
|
) -> t.List["V"]:
|
||||||
|
return [x async for x in auto_aiter(value)]
|
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""The optional bytecode cache system. This is useful if you have very
|
"""The optional bytecode cache system. This is useful if you have very
|
||||||
complex template situations and the compilation of all those templates
|
complex template situations and the compilation of all those templates
|
||||||
slows down your application too much.
|
slows down your application too much.
|
||||||
@@ -8,22 +7,30 @@
|
|||||||
"""
|
"""
|
||||||
import errno
|
import errno
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import marshal
|
||||||
import os
|
import os
|
||||||
|
import pickle
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import typing as t
|
||||||
from hashlib import sha1
|
from hashlib import sha1
|
||||||
from os import listdir
|
from io import BytesIO
|
||||||
from os import path
|
from types import CodeType
|
||||||
|
|
||||||
from ._compat import BytesIO
|
if t.TYPE_CHECKING:
|
||||||
from ._compat import marshal_dump
|
import typing_extensions as te
|
||||||
from ._compat import marshal_load
|
from .environment import Environment
|
||||||
from ._compat import pickle
|
|
||||||
from ._compat import text_type
|
|
||||||
from .utils import open_if_exists
|
|
||||||
|
|
||||||
bc_version = 4
|
class _MemcachedClient(te.Protocol):
|
||||||
|
def get(self, key: str) -> bytes:
|
||||||
|
...
|
||||||
|
|
||||||
|
def set(self, key: str, value: bytes, timeout: t.Optional[int] = None) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
bc_version = 5
|
||||||
# Magic bytes to identify Jinja bytecode cache files. Contains the
|
# Magic bytes to identify Jinja bytecode cache files. Contains the
|
||||||
# Python major and minor version to avoid loading incompatible bytecode
|
# Python major and minor version to avoid loading incompatible bytecode
|
||||||
# if a project upgrades its Python version.
|
# if a project upgrades its Python version.
|
||||||
@@ -34,7 +41,7 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Bucket(object):
|
class Bucket:
|
||||||
"""Buckets are used to store the bytecode for one template. It's created
|
"""Buckets are used to store the bytecode for one template. It's created
|
||||||
and initialized by the bytecode cache and passed to the loading functions.
|
and initialized by the bytecode cache and passed to the loading functions.
|
||||||
|
|
||||||
@@ -43,17 +50,17 @@ class Bucket(object):
|
|||||||
cache subclasses don't have to care about cache invalidation.
|
cache subclasses don't have to care about cache invalidation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, environment, key, checksum):
|
def __init__(self, environment: "Environment", key: str, checksum: str) -> None:
|
||||||
self.environment = environment
|
self.environment = environment
|
||||||
self.key = key
|
self.key = key
|
||||||
self.checksum = checksum
|
self.checksum = checksum
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def reset(self):
|
def reset(self) -> None:
|
||||||
"""Resets the bucket (unloads the bytecode)."""
|
"""Resets the bucket (unloads the bytecode)."""
|
||||||
self.code = None
|
self.code: t.Optional[CodeType] = None
|
||||||
|
|
||||||
def load_bytecode(self, f):
|
def load_bytecode(self, f: t.BinaryIO) -> None:
|
||||||
"""Loads bytecode from a file or file like object."""
|
"""Loads bytecode from a file or file like object."""
|
||||||
# make sure the magic header is correct
|
# make sure the magic header is correct
|
||||||
magic = f.read(len(bc_magic))
|
magic = f.read(len(bc_magic))
|
||||||
@@ -67,31 +74,31 @@ def load_bytecode(self, f):
|
|||||||
return
|
return
|
||||||
# if marshal_load fails then we need to reload
|
# if marshal_load fails then we need to reload
|
||||||
try:
|
try:
|
||||||
self.code = marshal_load(f)
|
self.code = marshal.load(f)
|
||||||
except (EOFError, ValueError, TypeError):
|
except (EOFError, ValueError, TypeError):
|
||||||
self.reset()
|
self.reset()
|
||||||
return
|
return
|
||||||
|
|
||||||
def write_bytecode(self, f):
|
def write_bytecode(self, f: t.BinaryIO) -> None:
|
||||||
"""Dump the bytecode into the file or file like object passed."""
|
"""Dump the bytecode into the file or file like object passed."""
|
||||||
if self.code is None:
|
if self.code is None:
|
||||||
raise TypeError("can't write empty bucket")
|
raise TypeError("can't write empty bucket")
|
||||||
f.write(bc_magic)
|
f.write(bc_magic)
|
||||||
pickle.dump(self.checksum, f, 2)
|
pickle.dump(self.checksum, f, 2)
|
||||||
marshal_dump(self.code, f)
|
marshal.dump(self.code, f)
|
||||||
|
|
||||||
def bytecode_from_string(self, string):
|
def bytecode_from_string(self, string: bytes) -> None:
|
||||||
"""Load bytecode from a string."""
|
"""Load bytecode from bytes."""
|
||||||
self.load_bytecode(BytesIO(string))
|
self.load_bytecode(BytesIO(string))
|
||||||
|
|
||||||
def bytecode_to_string(self):
|
def bytecode_to_string(self) -> bytes:
|
||||||
"""Return the bytecode as string."""
|
"""Return the bytecode as bytes."""
|
||||||
out = BytesIO()
|
out = BytesIO()
|
||||||
self.write_bytecode(out)
|
self.write_bytecode(out)
|
||||||
return out.getvalue()
|
return out.getvalue()
|
||||||
|
|
||||||
|
|
||||||
class BytecodeCache(object):
|
class BytecodeCache:
|
||||||
"""To implement your own bytecode cache you have to subclass this class
|
"""To implement your own bytecode cache you have to subclass this class
|
||||||
and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of
|
and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of
|
||||||
these methods are passed a :class:`~jinja2.bccache.Bucket`.
|
these methods are passed a :class:`~jinja2.bccache.Bucket`.
|
||||||
@@ -120,41 +127,48 @@ def dump_bytecode(self, bucket):
|
|||||||
Jinja.
|
Jinja.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def load_bytecode(self, bucket):
|
def load_bytecode(self, bucket: Bucket) -> None:
|
||||||
"""Subclasses have to override this method to load bytecode into a
|
"""Subclasses have to override this method to load bytecode into a
|
||||||
bucket. If they are not able to find code in the cache for the
|
bucket. If they are not able to find code in the cache for the
|
||||||
bucket, it must not do anything.
|
bucket, it must not do anything.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def dump_bytecode(self, bucket):
|
def dump_bytecode(self, bucket: Bucket) -> None:
|
||||||
"""Subclasses have to override this method to write the bytecode
|
"""Subclasses have to override this method to write the bytecode
|
||||||
from a bucket back to the cache. If it unable to do so it must not
|
from a bucket back to the cache. If it unable to do so it must not
|
||||||
fail silently but raise an exception.
|
fail silently but raise an exception.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def clear(self):
|
def clear(self) -> None:
|
||||||
"""Clears the cache. This method is not used by Jinja but should be
|
"""Clears the cache. This method is not used by Jinja but should be
|
||||||
implemented to allow applications to clear the bytecode cache used
|
implemented to allow applications to clear the bytecode cache used
|
||||||
by a particular environment.
|
by a particular environment.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_cache_key(self, name, filename=None):
|
def get_cache_key(
|
||||||
|
self, name: str, filename: t.Optional[t.Union[str]] = None
|
||||||
|
) -> str:
|
||||||
"""Returns the unique hash key for this template name."""
|
"""Returns the unique hash key for this template name."""
|
||||||
hash = sha1(name.encode("utf-8"))
|
hash = sha1(name.encode("utf-8"))
|
||||||
|
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
filename = "|" + filename
|
hash.update(f"|{filename}".encode())
|
||||||
if isinstance(filename, text_type):
|
|
||||||
filename = filename.encode("utf-8")
|
|
||||||
hash.update(filename)
|
|
||||||
return hash.hexdigest()
|
return hash.hexdigest()
|
||||||
|
|
||||||
def get_source_checksum(self, source):
|
def get_source_checksum(self, source: str) -> str:
|
||||||
"""Returns a checksum for the source."""
|
"""Returns a checksum for the source."""
|
||||||
return sha1(source.encode("utf-8")).hexdigest()
|
return sha1(source.encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
def get_bucket(self, environment, name, filename, source):
|
def get_bucket(
|
||||||
|
self,
|
||||||
|
environment: "Environment",
|
||||||
|
name: str,
|
||||||
|
filename: t.Optional[str],
|
||||||
|
source: str,
|
||||||
|
) -> Bucket:
|
||||||
"""Return a cache bucket for the given template. All arguments are
|
"""Return a cache bucket for the given template. All arguments are
|
||||||
mandatory but filename may be `None`.
|
mandatory but filename may be `None`.
|
||||||
"""
|
"""
|
||||||
@@ -164,7 +178,7 @@ def get_bucket(self, environment, name, filename, source):
|
|||||||
self.load_bytecode(bucket)
|
self.load_bytecode(bucket)
|
||||||
return bucket
|
return bucket
|
||||||
|
|
||||||
def set_bucket(self, bucket):
|
def set_bucket(self, bucket: Bucket) -> None:
|
||||||
"""Put the bucket into the cache."""
|
"""Put the bucket into the cache."""
|
||||||
self.dump_bytecode(bucket)
|
self.dump_bytecode(bucket)
|
||||||
|
|
||||||
@@ -187,14 +201,16 @@ class FileSystemBytecodeCache(BytecodeCache):
|
|||||||
This bytecode cache supports clearing of the cache using the clear method.
|
This bytecode cache supports clearing of the cache using the clear method.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, directory=None, pattern="__jinja2_%s.cache"):
|
def __init__(
|
||||||
|
self, directory: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache"
|
||||||
|
) -> None:
|
||||||
if directory is None:
|
if directory is None:
|
||||||
directory = self._get_default_cache_dir()
|
directory = self._get_default_cache_dir()
|
||||||
self.directory = directory
|
self.directory = directory
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
|
|
||||||
def _get_default_cache_dir(self):
|
def _get_default_cache_dir(self) -> str:
|
||||||
def _unsafe_dir():
|
def _unsafe_dir() -> "te.NoReturn":
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Cannot determine safe temp directory. You "
|
"Cannot determine safe temp directory. You "
|
||||||
"need to explicitly provide one."
|
"need to explicitly provide one."
|
||||||
@@ -209,7 +225,7 @@ def _unsafe_dir():
|
|||||||
if not hasattr(os, "getuid"):
|
if not hasattr(os, "getuid"):
|
||||||
_unsafe_dir()
|
_unsafe_dir()
|
||||||
|
|
||||||
dirname = "_jinja2-cache-%d" % os.getuid()
|
dirname = f"_jinja2-cache-{os.getuid()}"
|
||||||
actual_dir = os.path.join(tmpdir, dirname)
|
actual_dir = os.path.join(tmpdir, dirname)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -240,34 +256,30 @@ def _unsafe_dir():
|
|||||||
|
|
||||||
return actual_dir
|
return actual_dir
|
||||||
|
|
||||||
def _get_cache_filename(self, bucket):
|
def _get_cache_filename(self, bucket: Bucket) -> str:
|
||||||
return path.join(self.directory, self.pattern % bucket.key)
|
return os.path.join(self.directory, self.pattern % (bucket.key,))
|
||||||
|
|
||||||
def load_bytecode(self, bucket):
|
def load_bytecode(self, bucket: Bucket) -> None:
|
||||||
f = open_if_exists(self._get_cache_filename(bucket), "rb")
|
filename = self._get_cache_filename(bucket)
|
||||||
if f is not None:
|
|
||||||
try:
|
if os.path.exists(filename):
|
||||||
|
with open(filename, "rb") as f:
|
||||||
bucket.load_bytecode(f)
|
bucket.load_bytecode(f)
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def dump_bytecode(self, bucket):
|
def dump_bytecode(self, bucket: Bucket) -> None:
|
||||||
f = open(self._get_cache_filename(bucket), "wb")
|
with open(self._get_cache_filename(bucket), "wb") as f:
|
||||||
try:
|
|
||||||
bucket.write_bytecode(f)
|
bucket.write_bytecode(f)
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def clear(self):
|
def clear(self) -> None:
|
||||||
# imported lazily here because google app-engine doesn't support
|
# imported lazily here because google app-engine doesn't support
|
||||||
# write access on the file system and the function does not exist
|
# write access on the file system and the function does not exist
|
||||||
# normally.
|
# normally.
|
||||||
from os import remove
|
from os import remove
|
||||||
|
|
||||||
files = fnmatch.filter(listdir(self.directory), self.pattern % "*")
|
files = fnmatch.filter(os.listdir(self.directory), self.pattern % ("*",))
|
||||||
for filename in files:
|
for filename in files:
|
||||||
try:
|
try:
|
||||||
remove(path.join(self.directory, filename))
|
remove(os.path.join(self.directory, filename))
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -284,7 +296,7 @@ class MemcachedBytecodeCache(BytecodeCache):
|
|||||||
- `python-memcached <https://pypi.org/project/python-memcached/>`_
|
- `python-memcached <https://pypi.org/project/python-memcached/>`_
|
||||||
|
|
||||||
(Unfortunately the django cache interface is not compatible because it
|
(Unfortunately the django cache interface is not compatible because it
|
||||||
does not support storing binary data, only unicode. You can however pass
|
does not support storing binary data, only text. You can however pass
|
||||||
the underlying cache client to the bytecode cache which is available
|
the underlying cache client to the bytecode cache which is available
|
||||||
as `django.core.cache.cache._client`.)
|
as `django.core.cache.cache._client`.)
|
||||||
|
|
||||||
@@ -319,32 +331,34 @@ class MemcachedBytecodeCache(BytecodeCache):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
client,
|
client: "_MemcachedClient",
|
||||||
prefix="jinja2/bytecode/",
|
prefix: str = "jinja2/bytecode/",
|
||||||
timeout=None,
|
timeout: t.Optional[int] = None,
|
||||||
ignore_memcache_errors=True,
|
ignore_memcache_errors: bool = True,
|
||||||
):
|
):
|
||||||
self.client = client
|
self.client = client
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.ignore_memcache_errors = ignore_memcache_errors
|
self.ignore_memcache_errors = ignore_memcache_errors
|
||||||
|
|
||||||
def load_bytecode(self, bucket):
|
def load_bytecode(self, bucket: Bucket) -> None:
|
||||||
try:
|
try:
|
||||||
code = self.client.get(self.prefix + bucket.key)
|
code = self.client.get(self.prefix + bucket.key)
|
||||||
except Exception:
|
except Exception:
|
||||||
if not self.ignore_memcache_errors:
|
if not self.ignore_memcache_errors:
|
||||||
raise
|
raise
|
||||||
code = None
|
else:
|
||||||
if code is not None:
|
|
||||||
bucket.bytecode_from_string(code)
|
bucket.bytecode_from_string(code)
|
||||||
|
|
||||||
def dump_bytecode(self, bucket):
|
def dump_bytecode(self, bucket: Bucket) -> None:
|
||||||
args = (self.prefix + bucket.key, bucket.bytecode_to_string())
|
key = self.prefix + bucket.key
|
||||||
if self.timeout is not None:
|
value = bucket.bytecode_to_string()
|
||||||
args += (self.timeout,)
|
|
||||||
try:
|
try:
|
||||||
self.client.set(*args)
|
if self.timeout is not None:
|
||||||
|
self.client.set(key, value, self.timeout)
|
||||||
|
else:
|
||||||
|
self.client.set(key, value)
|
||||||
except Exception:
|
except Exception:
|
||||||
if not self.ignore_memcache_errors:
|
if not self.ignore_memcache_errors:
|
||||||
raise
|
raise
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#: list of lorem ipsum words used by the lipsum() helper function
|
#: list of lorem ipsum words used by the lipsum() helper function
|
||||||
LOREM_IPSUM_WORDS = u"""\
|
LOREM_IPSUM_WORDS = """\
|
||||||
a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at
|
a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at
|
||||||
auctor augue bibendum blandit class commodo condimentum congue consectetuer
|
auctor augue bibendum blandit class commodo condimentum congue consectetuer
|
||||||
consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus
|
consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus
|
@@ -1,38 +1,38 @@
|
|||||||
|
import platform
|
||||||
import sys
|
import sys
|
||||||
|
import typing as t
|
||||||
from types import CodeType
|
from types import CodeType
|
||||||
|
from types import TracebackType
|
||||||
|
|
||||||
from . import TemplateSyntaxError
|
from .exceptions import TemplateSyntaxError
|
||||||
from ._compat import PYPY
|
|
||||||
from .utils import internal_code
|
from .utils import internal_code
|
||||||
from .utils import missing
|
from .utils import missing
|
||||||
|
|
||||||
|
if t.TYPE_CHECKING:
|
||||||
|
from .runtime import Context
|
||||||
|
|
||||||
def rewrite_traceback_stack(source=None):
|
|
||||||
|
def rewrite_traceback_stack(source: t.Optional[str] = None) -> BaseException:
|
||||||
"""Rewrite the current exception to replace any tracebacks from
|
"""Rewrite the current exception to replace any tracebacks from
|
||||||
within compiled template code with tracebacks that look like they
|
within compiled template code with tracebacks that look like they
|
||||||
came from the template source.
|
came from the template source.
|
||||||
|
|
||||||
This must be called within an ``except`` block.
|
This must be called within an ``except`` block.
|
||||||
|
|
||||||
:param exc_info: A :meth:`sys.exc_info` tuple. If not provided,
|
|
||||||
the current ``exc_info`` is used.
|
|
||||||
:param source: For ``TemplateSyntaxError``, the original source if
|
:param source: For ``TemplateSyntaxError``, the original source if
|
||||||
known.
|
known.
|
||||||
:return: A :meth:`sys.exc_info` tuple that can be re-raised.
|
:return: The original exception with the rewritten traceback.
|
||||||
"""
|
"""
|
||||||
exc_type, exc_value, tb = sys.exc_info()
|
_, exc_value, tb = sys.exc_info()
|
||||||
|
exc_value = t.cast(BaseException, exc_value)
|
||||||
|
tb = t.cast(TracebackType, tb)
|
||||||
|
|
||||||
if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated:
|
if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated:
|
||||||
exc_value.translated = True
|
exc_value.translated = True
|
||||||
exc_value.source = source
|
exc_value.source = source
|
||||||
|
# Remove the old traceback, otherwise the frames from the
|
||||||
try:
|
# compiler still show up.
|
||||||
# Remove the old traceback on Python 3, otherwise the frames
|
exc_value.with_traceback(None)
|
||||||
# from the compiler still show up.
|
|
||||||
exc_value.with_traceback(None)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Outside of runtime, so the frame isn't executing template
|
# Outside of runtime, so the frame isn't executing template
|
||||||
# code, but it still needs to point at the template.
|
# code, but it still needs to point at the template.
|
||||||
tb = fake_traceback(
|
tb = fake_traceback(
|
||||||
@@ -70,10 +70,12 @@ def rewrite_traceback_stack(source=None):
|
|||||||
for tb in reversed(stack):
|
for tb in reversed(stack):
|
||||||
tb_next = tb_set_next(tb, tb_next)
|
tb_next = tb_set_next(tb, tb_next)
|
||||||
|
|
||||||
return exc_type, exc_value, tb_next
|
return exc_value.with_traceback(tb_next)
|
||||||
|
|
||||||
|
|
||||||
def fake_traceback(exc_value, tb, filename, lineno):
|
def fake_traceback( # type: ignore
|
||||||
|
exc_value: BaseException, tb: t.Optional[TracebackType], filename: str, lineno: int
|
||||||
|
) -> TracebackType:
|
||||||
"""Produce a new traceback object that looks like it came from the
|
"""Produce a new traceback object that looks like it came from the
|
||||||
template source instead of the compiled code. The filename, line
|
template source instead of the compiled code. The filename, line
|
||||||
number, and location name will point to the template, and the local
|
number, and location name will point to the template, and the local
|
||||||
@@ -100,79 +102,60 @@ def fake_traceback(exc_value, tb, filename, lineno):
|
|||||||
"__jinja_exception__": exc_value,
|
"__jinja_exception__": exc_value,
|
||||||
}
|
}
|
||||||
# Raise an exception at the correct line number.
|
# Raise an exception at the correct line number.
|
||||||
code = compile("\n" * (lineno - 1) + "raise __jinja_exception__", filename, "exec")
|
code: CodeType = compile(
|
||||||
|
"\n" * (lineno - 1) + "raise __jinja_exception__", filename, "exec"
|
||||||
|
)
|
||||||
|
|
||||||
# Build a new code object that points to the template file and
|
# Build a new code object that points to the template file and
|
||||||
# replaces the location with a block name.
|
# replaces the location with a block name.
|
||||||
try:
|
location = "template"
|
||||||
location = "template"
|
|
||||||
|
|
||||||
if tb is not None:
|
if tb is not None:
|
||||||
function = tb.tb_frame.f_code.co_name
|
function = tb.tb_frame.f_code.co_name
|
||||||
|
|
||||||
if function == "root":
|
if function == "root":
|
||||||
location = "top-level template code"
|
location = "top-level template code"
|
||||||
elif function.startswith("block_"):
|
elif function.startswith("block_"):
|
||||||
location = 'block "%s"' % function[6:]
|
location = f"block {function[6:]!r}"
|
||||||
|
|
||||||
# Collect arguments for the new code object. CodeType only
|
if sys.version_info >= (3, 8):
|
||||||
# accepts positional arguments, and arguments were inserted in
|
code = code.replace(co_name=location)
|
||||||
# new Python versions.
|
else:
|
||||||
code_args = []
|
code = CodeType(
|
||||||
|
code.co_argcount,
|
||||||
for attr in (
|
code.co_kwonlyargcount,
|
||||||
"argcount",
|
code.co_nlocals,
|
||||||
"posonlyargcount", # Python 3.8
|
code.co_stacksize,
|
||||||
"kwonlyargcount", # Python 3
|
code.co_flags,
|
||||||
"nlocals",
|
code.co_code,
|
||||||
"stacksize",
|
code.co_consts,
|
||||||
"flags",
|
code.co_names,
|
||||||
"code", # codestring
|
code.co_varnames,
|
||||||
"consts", # constants
|
code.co_filename,
|
||||||
"names",
|
location,
|
||||||
"varnames",
|
code.co_firstlineno,
|
||||||
("filename", filename),
|
code.co_lnotab,
|
||||||
("name", location),
|
code.co_freevars,
|
||||||
"firstlineno",
|
code.co_cellvars,
|
||||||
"lnotab",
|
)
|
||||||
"freevars",
|
|
||||||
"cellvars",
|
|
||||||
):
|
|
||||||
if isinstance(attr, tuple):
|
|
||||||
# Replace with given value.
|
|
||||||
code_args.append(attr[1])
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Copy original value if it exists.
|
|
||||||
code_args.append(getattr(code, "co_" + attr))
|
|
||||||
except AttributeError:
|
|
||||||
# Some arguments were added later.
|
|
||||||
continue
|
|
||||||
|
|
||||||
code = CodeType(*code_args)
|
|
||||||
except Exception:
|
|
||||||
# Some environments such as Google App Engine don't support
|
|
||||||
# modifying code objects.
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Execute the new code, which is guaranteed to raise, and return
|
# Execute the new code, which is guaranteed to raise, and return
|
||||||
# the new traceback without this frame.
|
# the new traceback without this frame.
|
||||||
try:
|
try:
|
||||||
exec(code, globals, locals)
|
exec(code, globals, locals)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
return sys.exc_info()[2].tb_next
|
return sys.exc_info()[2].tb_next # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def get_template_locals(real_locals):
|
def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any]:
|
||||||
"""Based on the runtime locals, get the context that would be
|
"""Based on the runtime locals, get the context that would be
|
||||||
available at that point in the template.
|
available at that point in the template.
|
||||||
"""
|
"""
|
||||||
# Start with the current template context.
|
# Start with the current template context.
|
||||||
ctx = real_locals.get("context")
|
ctx: "t.Optional[Context]" = real_locals.get("context")
|
||||||
|
|
||||||
if ctx:
|
if ctx is not None:
|
||||||
data = ctx.get_all().copy()
|
data: t.Dict[str, t.Any] = ctx.get_all().copy()
|
||||||
else:
|
else:
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
@@ -180,7 +163,7 @@ def get_template_locals(real_locals):
|
|||||||
# rather than pushing a context. Local variables follow the scheme
|
# rather than pushing a context. Local variables follow the scheme
|
||||||
# l_depth_name. Find the highest-depth local that has a value for
|
# l_depth_name. Find the highest-depth local that has a value for
|
||||||
# each name.
|
# each name.
|
||||||
local_overrides = {}
|
local_overrides: t.Dict[str, t.Tuple[int, t.Any]] = {}
|
||||||
|
|
||||||
for name, value in real_locals.items():
|
for name, value in real_locals.items():
|
||||||
if not name.startswith("l_") or value is missing:
|
if not name.startswith("l_") or value is missing:
|
||||||
@@ -188,8 +171,8 @@ def get_template_locals(real_locals):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_, depth, name = name.split("_", 2)
|
_, depth_str, name = name.split("_", 2)
|
||||||
depth = int(depth)
|
depth = int(depth_str)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -210,31 +193,37 @@ def get_template_locals(real_locals):
|
|||||||
|
|
||||||
if sys.version_info >= (3, 7):
|
if sys.version_info >= (3, 7):
|
||||||
# tb_next is directly assignable as of Python 3.7
|
# tb_next is directly assignable as of Python 3.7
|
||||||
def tb_set_next(tb, tb_next):
|
def tb_set_next(
|
||||||
|
tb: TracebackType, tb_next: t.Optional[TracebackType]
|
||||||
|
) -> TracebackType:
|
||||||
tb.tb_next = tb_next
|
tb.tb_next = tb_next
|
||||||
return tb
|
return tb
|
||||||
|
|
||||||
|
|
||||||
elif PYPY:
|
elif platform.python_implementation() == "PyPy":
|
||||||
# PyPy might have special support, and won't work with ctypes.
|
# PyPy might have special support, and won't work with ctypes.
|
||||||
try:
|
try:
|
||||||
import tputil
|
import tputil # type: ignore
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# Without tproxy support, use the original traceback.
|
# Without tproxy support, use the original traceback.
|
||||||
def tb_set_next(tb, tb_next):
|
def tb_set_next(
|
||||||
|
tb: TracebackType, tb_next: t.Optional[TracebackType]
|
||||||
|
) -> TracebackType:
|
||||||
return tb
|
return tb
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# With tproxy support, create a proxy around the traceback that
|
# With tproxy support, create a proxy around the traceback that
|
||||||
# returns the new tb_next.
|
# returns the new tb_next.
|
||||||
def tb_set_next(tb, tb_next):
|
def tb_set_next(
|
||||||
def controller(op):
|
tb: TracebackType, tb_next: t.Optional[TracebackType]
|
||||||
|
) -> TracebackType:
|
||||||
|
def controller(op): # type: ignore
|
||||||
if op.opname == "__getattribute__" and op.args[0] == "tb_next":
|
if op.opname == "__getattribute__" and op.args[0] == "tb_next":
|
||||||
return tb_next
|
return tb_next
|
||||||
|
|
||||||
return op.delegate()
|
return op.delegate()
|
||||||
|
|
||||||
return tputil.make_proxy(controller, obj=tb)
|
return tputil.make_proxy(controller, obj=tb) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@@ -250,7 +239,9 @@ class _CTraceback(ctypes.Structure):
|
|||||||
("tb_next", ctypes.py_object),
|
("tb_next", ctypes.py_object),
|
||||||
]
|
]
|
||||||
|
|
||||||
def tb_set_next(tb, tb_next):
|
def tb_set_next(
|
||||||
|
tb: TracebackType, tb_next: t.Optional[TracebackType]
|
||||||
|
) -> TracebackType:
|
||||||
c_tb = _CTraceback.from_address(id(tb))
|
c_tb = _CTraceback.from_address(id(tb))
|
||||||
|
|
||||||
# Clear out the old tb_next.
|
# Clear out the old tb_next.
|
@@ -1,5 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
import typing as t
|
||||||
from ._compat import range_type
|
|
||||||
from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401
|
from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401
|
||||||
from .tests import TESTS as DEFAULT_TESTS # noqa: F401
|
from .tests import TESTS as DEFAULT_TESTS # noqa: F401
|
||||||
from .utils import Cycler
|
from .utils import Cycler
|
||||||
@@ -7,6 +7,9 @@
|
|||||||
from .utils import Joiner
|
from .utils import Joiner
|
||||||
from .utils import Namespace
|
from .utils import Namespace
|
||||||
|
|
||||||
|
if t.TYPE_CHECKING:
|
||||||
|
import typing_extensions as te
|
||||||
|
|
||||||
# defaults for the parser / lexer
|
# defaults for the parser / lexer
|
||||||
BLOCK_START_STRING = "{%"
|
BLOCK_START_STRING = "{%"
|
||||||
BLOCK_END_STRING = "%}"
|
BLOCK_END_STRING = "%}"
|
||||||
@@ -14,17 +17,17 @@
|
|||||||
VARIABLE_END_STRING = "}}"
|
VARIABLE_END_STRING = "}}"
|
||||||
COMMENT_START_STRING = "{#"
|
COMMENT_START_STRING = "{#"
|
||||||
COMMENT_END_STRING = "#}"
|
COMMENT_END_STRING = "#}"
|
||||||
LINE_STATEMENT_PREFIX = None
|
LINE_STATEMENT_PREFIX: t.Optional[str] = None
|
||||||
LINE_COMMENT_PREFIX = None
|
LINE_COMMENT_PREFIX: t.Optional[str] = None
|
||||||
TRIM_BLOCKS = False
|
TRIM_BLOCKS = False
|
||||||
LSTRIP_BLOCKS = False
|
LSTRIP_BLOCKS = False
|
||||||
NEWLINE_SEQUENCE = "\n"
|
NEWLINE_SEQUENCE: "te.Literal['\\n', '\\r\\n', '\\r']" = "\n"
|
||||||
KEEP_TRAILING_NEWLINE = False
|
KEEP_TRAILING_NEWLINE = False
|
||||||
|
|
||||||
# default filters, tests and namespace
|
# default filters, tests and namespace
|
||||||
|
|
||||||
DEFAULT_NAMESPACE = {
|
DEFAULT_NAMESPACE = {
|
||||||
"range": range_type,
|
"range": range,
|
||||||
"dict": dict,
|
"dict": dict,
|
||||||
"lipsum": generate_lorem_ipsum,
|
"lipsum": generate_lorem_ipsum,
|
||||||
"cycler": Cycler,
|
"cycler": Cycler,
|
||||||
@@ -33,10 +36,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
# default policies
|
# default policies
|
||||||
DEFAULT_POLICIES = {
|
DEFAULT_POLICIES: t.Dict[str, t.Any] = {
|
||||||
"compiler.ascii_str": True,
|
"compiler.ascii_str": True,
|
||||||
"urlize.rel": "noopener",
|
"urlize.rel": "noopener",
|
||||||
"urlize.target": None,
|
"urlize.target": None,
|
||||||
|
"urlize.extra_schemes": None,
|
||||||
"truncate.leeway": 5,
|
"truncate.leeway": 5,
|
||||||
"json.dumps_function": None,
|
"json.dumps_function": None,
|
||||||
"json.dumps_kwargs": {"sort_keys": True},
|
"json.dumps_kwargs": {"sort_keys": True},
|
File diff suppressed because it is too large
Load Diff
@@ -1,44 +1,20 @@
|
|||||||
# -*- coding: utf-8 -*-
|
import typing as t
|
||||||
from ._compat import imap
|
|
||||||
from ._compat import implements_to_string
|
if t.TYPE_CHECKING:
|
||||||
from ._compat import PY2
|
from .runtime import Undefined
|
||||||
from ._compat import text_type
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateError(Exception):
|
class TemplateError(Exception):
|
||||||
"""Baseclass for all template errors."""
|
"""Baseclass for all template errors."""
|
||||||
|
|
||||||
if PY2:
|
def __init__(self, message: t.Optional[str] = None) -> None:
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
def __init__(self, message=None):
|
@property
|
||||||
if message is not None:
|
def message(self) -> t.Optional[str]:
|
||||||
message = text_type(message).encode("utf-8")
|
return self.args[0] if self.args else None
|
||||||
Exception.__init__(self, message)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def message(self):
|
|
||||||
if self.args:
|
|
||||||
message = self.args[0]
|
|
||||||
if message is not None:
|
|
||||||
return message.decode("utf-8", "replace")
|
|
||||||
|
|
||||||
def __unicode__(self):
|
|
||||||
return self.message or u""
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
def __init__(self, message=None):
|
|
||||||
Exception.__init__(self, message)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def message(self):
|
|
||||||
if self.args:
|
|
||||||
message = self.args[0]
|
|
||||||
if message is not None:
|
|
||||||
return message
|
|
||||||
|
|
||||||
|
|
||||||
@implements_to_string
|
|
||||||
class TemplateNotFound(IOError, LookupError, TemplateError):
|
class TemplateNotFound(IOError, LookupError, TemplateError):
|
||||||
"""Raised if a template does not exist.
|
"""Raised if a template does not exist.
|
||||||
|
|
||||||
@@ -47,11 +23,15 @@ class TemplateNotFound(IOError, LookupError, TemplateError):
|
|||||||
provided, an :exc:`UndefinedError` is raised.
|
provided, an :exc:`UndefinedError` is raised.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# looks weird, but removes the warning descriptor that just
|
# Silence the Python warning about message being deprecated since
|
||||||
# bogusly warns us about message being deprecated
|
# it's not valid here.
|
||||||
message = None
|
message: t.Optional[str] = None
|
||||||
|
|
||||||
def __init__(self, name, message=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: t.Optional[t.Union[str, "Undefined"]],
|
||||||
|
message: t.Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
IOError.__init__(self, name)
|
IOError.__init__(self, name)
|
||||||
|
|
||||||
if message is None:
|
if message is None:
|
||||||
@@ -66,8 +46,8 @@ def __init__(self, name, message=None):
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.templates = [name]
|
self.templates = [name]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return self.message
|
return str(self.message)
|
||||||
|
|
||||||
|
|
||||||
class TemplatesNotFound(TemplateNotFound):
|
class TemplatesNotFound(TemplateNotFound):
|
||||||
@@ -82,7 +62,11 @@ class TemplatesNotFound(TemplateNotFound):
|
|||||||
.. versionadded:: 2.2
|
.. versionadded:: 2.2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, names=(), message=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
names: t.Sequence[t.Union[str, "Undefined"]] = (),
|
||||||
|
message: t.Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
if message is None:
|
if message is None:
|
||||||
from .runtime import Undefined
|
from .runtime import Undefined
|
||||||
|
|
||||||
@@ -94,52 +78,57 @@ def __init__(self, names=(), message=None):
|
|||||||
else:
|
else:
|
||||||
parts.append(name)
|
parts.append(name)
|
||||||
|
|
||||||
message = u"none of the templates given were found: " + u", ".join(
|
parts_str = ", ".join(map(str, parts))
|
||||||
imap(text_type, parts)
|
message = f"none of the templates given were found: {parts_str}"
|
||||||
)
|
|
||||||
TemplateNotFound.__init__(self, names and names[-1] or None, message)
|
super().__init__(names[-1] if names else None, message)
|
||||||
self.templates = list(names)
|
self.templates = list(names)
|
||||||
|
|
||||||
|
|
||||||
@implements_to_string
|
|
||||||
class TemplateSyntaxError(TemplateError):
|
class TemplateSyntaxError(TemplateError):
|
||||||
"""Raised to tell the user that there is a problem with the template."""
|
"""Raised to tell the user that there is a problem with the template."""
|
||||||
|
|
||||||
def __init__(self, message, lineno, name=None, filename=None):
|
def __init__(
|
||||||
TemplateError.__init__(self, message)
|
self,
|
||||||
|
message: str,
|
||||||
|
lineno: int,
|
||||||
|
name: t.Optional[str] = None,
|
||||||
|
filename: t.Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
|
super().__init__(message)
|
||||||
self.lineno = lineno
|
self.lineno = lineno
|
||||||
self.name = name
|
self.name = name
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.source = None
|
self.source: t.Optional[str] = None
|
||||||
|
|
||||||
# this is set to True if the debug.translate_syntax_error
|
# this is set to True if the debug.translate_syntax_error
|
||||||
# function translated the syntax error into a new traceback
|
# function translated the syntax error into a new traceback
|
||||||
self.translated = False
|
self.translated = False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
# for translated errors we only return the message
|
# for translated errors we only return the message
|
||||||
if self.translated:
|
if self.translated:
|
||||||
return self.message
|
return t.cast(str, self.message)
|
||||||
|
|
||||||
# otherwise attach some stuff
|
# otherwise attach some stuff
|
||||||
location = "line %d" % self.lineno
|
location = f"line {self.lineno}"
|
||||||
name = self.filename or self.name
|
name = self.filename or self.name
|
||||||
if name:
|
if name:
|
||||||
location = 'File "%s", %s' % (name, location)
|
location = f'File "{name}", {location}'
|
||||||
lines = [self.message, " " + location]
|
lines = [t.cast(str, self.message), " " + location]
|
||||||
|
|
||||||
# if the source is set, add the line to the output
|
# if the source is set, add the line to the output
|
||||||
if self.source is not None:
|
if self.source is not None:
|
||||||
try:
|
try:
|
||||||
line = self.source.splitlines()[self.lineno - 1]
|
line = self.source.splitlines()[self.lineno - 1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
line = None
|
pass
|
||||||
if line:
|
else:
|
||||||
lines.append(" " + line.strip())
|
lines.append(" " + line.strip())
|
||||||
|
|
||||||
return u"\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
def __reduce__(self):
|
def __reduce__(self): # type: ignore
|
||||||
# https://bugs.python.org/issue1692335 Exceptions that take
|
# https://bugs.python.org/issue1692335 Exceptions that take
|
||||||
# multiple required arguments have problems with pickling.
|
# multiple required arguments have problems with pickling.
|
||||||
# Without this, raises TypeError: __init__() missing 1 required
|
# Without this, raises TypeError: __init__() missing 1 required
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user