Compare commits
2101 Commits
3.2.x-stab
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
|
abf3bdb69d | ||
|
191f7112f1 | ||
|
d4847ce802 | ||
|
850ac483cb | ||
|
186d44e51b | ||
|
e6fa229b18 | ||
|
3e9eabe9df | ||
|
c251be3ef3 | ||
|
59985eaf4e | ||
|
af71522292 | ||
|
419bedf661 | ||
|
b6b09d0bc2 | ||
|
740f1a78d8 | ||
|
ed92ad65c4 | ||
|
6964a4f5d9 | ||
|
560ad70aeb | ||
|
714a085556 | ||
|
37179801eb | ||
|
b5533caece | ||
|
20e6d1d66c | ||
|
a067e4fc4f | ||
|
a87487020a | ||
|
03c5e366ed | ||
|
9106dd9337 | ||
|
2fcc008d7b | ||
|
196f85fa2c | ||
|
ba96a39ca0 | ||
|
05019b2cad | ||
|
36d48fc624 | ||
|
0259662b67 | ||
|
d4f1cba7a1 | ||
|
2d656c4565 | ||
|
fc19b17fc7 | ||
|
6176fb4d12 | ||
|
3151eb7c82 | ||
|
8ea29c271f | ||
|
119f3fb4bd | ||
|
3969b58e32 | ||
|
9cc4cb356f | ||
|
c83aa1da70 | ||
|
6a31e30cbf | ||
|
0e88cb6c28 | ||
|
3614fd003d | ||
|
a93dc7740c | ||
|
f6e39aac52 | ||
|
d92118e13f | ||
|
10be237e10 | ||
|
5ec934d331 | ||
|
3008260bb2 | ||
|
c6f429e310 | ||
|
f6b4d6db43 | ||
|
05bc0cbb09 | ||
|
8a095504c4 | ||
|
3f4d2c8040 | ||
|
2bde5af133 | ||
|
6c33240ad0 | ||
|
0356833d63 | ||
|
72e3945d09 | ||
|
709e6c64b1 | ||
|
51c773c3f9 | ||
|
93f1090204 | ||
|
80841b1a29 | ||
|
277017dcd7 | ||
|
4cd1f0f402 | ||
|
16cb360a69 | ||
|
f4d62f0f41 | ||
|
35aa975a74 | ||
|
c68c3632cc | ||
|
4ac0529d1c | ||
|
c9e9043e9d | ||
|
206dfce409 | ||
|
d1dece4473 | ||
|
7842d03ef6 | ||
|
69e3e493de | ||
|
b485bfea07 | ||
|
1814b7fd41 | ||
|
08f34835d5 | ||
|
97cc2413ff | ||
|
8ee1da93ce | ||
|
df37ae610b | ||
|
fe124b0e1e | ||
|
cc96e65787 | ||
|
cbe39e1324 | ||
|
09a3f58800 | ||
|
e80437c9b9 | ||
|
ad4064456b | ||
|
8c8bb7a3df | ||
|
aa938285a4 | ||
|
f5c425345b | ||
|
e57aab2008 | ||
|
d398d6568e | ||
|
032fca834e | ||
|
b0fc0a0a4d | ||
|
ff23fabfe0 | ||
|
7f49b21c49 | ||
|
9a9acf0b93 | ||
|
c14ffa08e2 | ||
|
bfe2f7993f | ||
|
f38502d5ad | ||
|
5fc2b2753a | ||
|
cde6acd224 | ||
|
6498f9e0d1 | ||
|
5414e51245 | ||
|
4fea2920d7 | ||
|
783881edaa | ||
|
dc3c08a012 | ||
|
e6e10bdcec | ||
|
543ae5ae01 | ||
|
f0c8e02901 | ||
|
d72df37333 | ||
|
0ad97beed5 | ||
|
c51fa0e2f1 | ||
|
d9f807d464 | ||
|
e945af0aa3 | ||
|
7987cc5727 | ||
|
2042b338a7 | ||
|
0fa28b88ae | ||
|
c52d3d3dab | ||
|
870e41e7ed | ||
|
9b3fbe1e33 | ||
|
237e3f7066 | ||
|
96cdfd2a41 | ||
|
a9044661ae | ||
|
19430fac56 | ||
|
5f9b7890c3 | ||
|
51c39cdbee | ||
|
e4d2b27138 | ||
|
8f9c26edb6 | ||
|
d6184e5cff | ||
|
002b313e0c | ||
|
8006f2c678 | ||
|
9cd0b6bf64 | ||
|
3e885cda19 | ||
|
3a6f604232 | ||
|
13ccb51010 | ||
|
ec5272ad65 | ||
|
c34d401cc3 | ||
|
232a78bc08 | ||
|
456bb1b3eb | ||
|
6119153af3 | ||
|
ffc37872c3 | ||
|
389429cd10 | ||
|
6b3a3e2c25 | ||
|
1a6d2402cf | ||
|
acfe97aff3 | ||
|
80ef430185 | ||
|
e08bd744a8 | ||
|
6988e093b3 | ||
|
dcf8aab6e6 | ||
|
5d32d921f4 | ||
|
d43135d9a0 | ||
|
2023298764 | ||
|
bee487653a | ||
|
8720a68849 | ||
|
0da919951c | ||
|
9800edf94e | ||
|
8aec50d185 | ||
|
e52b220a69 | ||
|
6ded13a917 | ||
|
bf466e0ea4 | ||
|
98f26d9380 | ||
|
bbe015e732 | ||
|
265469c9cd | ||
|
e6de798228 | ||
|
8bb6c63931 | ||
|
091c00e4ef | ||
|
6969a5e01d | ||
|
4815bf6963 | ||
|
9e6e3da01c | ||
|
dcea48a5e1 | ||
|
d75648f326 | ||
|
b49fd32cfb | ||
|
3bbfdef1ce | ||
|
408cc5a5cf | ||
|
6048a134e2 | ||
|
ea90ca4118 | ||
|
4bba7ed893 | ||
|
a5a602c20e | ||
|
72320bf754 | ||
|
dbad8704f5 | ||
|
2756eb2573 | ||
|
ea4364b8a8 | ||
|
ea744a0c0c | ||
|
991be792c0 | ||
|
3d4b408c93 | ||
|
2e825167a3 | ||
|
52cff12c38 | ||
|
84d1599845 | ||
|
754b21ac22 | ||
|
81c82ef343 | ||
|
ad28ae08b6 | ||
|
f651fc9bff | ||
|
19b0f28f16 | ||
|
27b6a5d690 | ||
|
0d63ebf14f | ||
|
b0614bb79c | ||
|
f9f888fade | ||
|
48554cf310 | ||
|
461f011521 | ||
|
8a14ddc97c | ||
|
448633ab02 | ||
|
5d19b875a1 | ||
|
0017df327c | ||
|
02736d7ccf | ||
|
eb1e5a201f | ||
|
1caaac565b | ||
|
fb6f3a5f39 | ||
|
66e028862f | ||
|
17821c6ea1 | ||
|
5a56188a51 | ||
|
616a97f60e | ||
|
d6897d6c36 | ||
|
da2ed4728a | ||
|
e6e46f1ebd | ||
|
fd37beae8b | ||
|
1c1ade6816 | ||
|
1ead64bd5b | ||
|
366552f743 | ||
|
4440bf3bfc | ||
|
4c8e91dc70 | ||
|
d6c6b7c64b | ||
|
bdbeadcd65 | ||
|
93094948fa | ||
|
35990d9a6b | ||
|
6dc83fb277 | ||
|
8c66a558d5 | ||
|
5a90e0bc6a | ||
|
f8c6d2c487 | ||
|
246aa3e217 | ||
|
cae7b9e868 | ||
|
cf9837f48c | ||
|
a7e86e8aff | ||
|
19aa96fe54 | ||
|
00ac9a6cee | ||
|
92a5d07ed7 | ||
|
5bf787c1a5 | ||
|
011483967d | ||
|
5f293fb40b | ||
|
a6cfc79a92 | ||
|
afd3ed86d9 | ||
|
9654f487ef | ||
|
2100d273ce | ||
|
df09d7ae89 | ||
|
8408a3284b | ||
|
4625208ba2 | ||
|
09dae0437e | ||
|
cca2cd3260 | ||
|
008caa43e2 | ||
|
8469fbd2e8 | ||
|
c8c0e783c3 | ||
|
2e96184406 | ||
|
0a0e647be3 | ||
|
370e75fc71 | ||
|
bcf27aa311 | ||
|
0095e30843 | ||
|
8ff3849820 | ||
|
bf09dfc6af | ||
|
f8094bbbbb | ||
|
5ac23cd3d6 | ||
|
cc835cee6f | ||
|
30ca0bfa45 | ||
|
685e9db3f7 | ||
|
51e05241fe | ||
|
dfe07a51a3 | ||
|
0ef3842da6 | ||
|
f674214741 | ||
|
c61399bc8a | ||
|
28a10cf8c3 | ||
|
2127129227 | ||
|
d0420ea3ee | ||
|
fe68b45fc5 | ||
|
fb83ad326b | ||
|
219befacbf | ||
|
70a59d6cd1 | ||
|
131b2eded1 | ||
|
f6cd82f9a4 | ||
|
6d242b67f9 | ||
|
b4edf52198 | ||
|
b8049daa45 | ||
|
d9fceac06e | ||
|
51d6dd23ea | ||
|
1645874973 | ||
|
b78721d4b9 | ||
|
134b2c8d83 | ||
|
4406a879bc | ||
|
2c52adc8e8 | ||
|
17b72b0fd8 | ||
|
922b8aaaec | ||
|
b950f0f6d4 | ||
|
fbde737802 | ||
|
14c8893b03 | ||
|
b396f70d12 | ||
|
36485c8571 | ||
|
f0c2295606 | ||
|
8370aa7b70 | ||
|
891b56d0c7 | ||
|
2fd98c913a | ||
|
8440a6a5dd | ||
|
ec0316806f | ||
|
6b2c996d06 | ||
|
36f57463ef | ||
|
a659db1f9c | ||
|
bdd059ffa8 | ||
|
e8726111f8 | ||
|
61af4fc688 | ||
|
11cbc99768 | ||
|
2204c58b44 | ||
|
e06ea94664 | ||
|
d33d9e8dae | ||
|
408ee0338a | ||
|
60c5f3fd5a | ||
|
10acebff46 | ||
|
21842e20c7 | ||
|
38a2d6a353 | ||
|
311a125e36 | ||
|
58bbfac910 | ||
|
1ca9c7516b | ||
|
25ab3f7f03 | ||
|
012138c1f2 | ||
|
904ebe1c7e | ||
|
6cb4b25788 | ||
|
082a1c342a | ||
|
da4a3161a2 | ||
|
56cdf33b15 | ||
|
9992cf2507 | ||
|
7fd9d48a20 | ||
|
74ccb4d28b | ||
|
098bbd520e | ||
|
49afa16b1c | ||
|
a0ff63b215 | ||
|
5568d22549 | ||
|
1f3ebad92d | ||
|
91454a71d0 | ||
|
6658708576 | ||
|
c4e0456acc | ||
|
9925d6666f | ||
|
2555b5baf4 | ||
|
f57ee158b7 | ||
|
028e9e68f9 | ||
|
0f2bceb72f | ||
|
5eac7a021c | ||
|
ab3612d18d | ||
|
2fce6a3c44 | ||
|
01cbe07641 | ||
|
2697c35fc7 | ||
|
4329b824d4 | ||
|
0ced01ddc3 | ||
|
d5555eba32 | ||
|
6770f781e3 | ||
|
ae3e609024 | ||
|
4aa2c4988c | ||
|
0d9d2ac59a | ||
|
15c514326c | ||
|
b795fd82bb | ||
|
dc91255ff5 | ||
|
7379e7f28d | ||
|
633d6bda0d | ||
|
dbddeaba68 | ||
|
809d6cdda0 | ||
|
b37cf66acb | ||
|
be5ce2e60f | ||
|
34888edae1 | ||
|
7a3bff5117 | ||
|
b7e34abeaa | ||
|
8741c7ec1a | ||
|
ae47c4a64a | ||
|
d230a28a7a | ||
|
727c3e95eb | ||
|
283c1f92bb | ||
|
903fed07a9 | ||
|
9d1fec3668 | ||
|
c69e229be0 | ||
|
7d63227014 | ||
|
49f13c30a5 | ||
|
36dfedfea5 | ||
|
281f4c64bc | ||
|
7b2cf57222 | ||
|
8a5876410e | ||
|
b2ef6f9a28 | ||
|
d9d80c8caa | ||
|
54265f87b1 | ||
|
dc39791766 | ||
|
dd8af028f7 | ||
|
ecf55cb65b | ||
|
a6591fcaf3 | ||
|
84b0262f31 | ||
|
54250887e1 | ||
|
c09953e15e | ||
|
d131f51468 | ||
|
5a1428154c | ||
|
0c9b3b2f16 | ||
|
c945cca93a | ||
|
86f47acf32 | ||
|
e87b4457af | ||
|
1444d9d73a | ||
|
61126b424b | ||
|
38d78404b1 | ||
|
a5dbe793d9 | ||
|
87be4c4a81 | ||
|
cefb437324 | ||
|
4eba859236 | ||
|
d7bbfd055c | ||
|
1e59092bf5 | ||
|
d640f17ddf | ||
|
2ea5a2b5d5 | ||
|
9cea2ca7ed | ||
|
e4b9d754df | ||
|
3881737bbd | ||
|
23d203b00b | ||
|
fc2bb1ede0 | ||
|
d5f32be5e3 | ||
|
14e9da251a | ||
|
f23b4ff267 | ||
|
918e3c83e6 | ||
|
0348af22d9 | ||
|
ecd8839ac9 | ||
|
a2b21ee087 | ||
|
0dc3c5bf4a | ||
|
54dc2f00f5 | ||
|
a84555209e | ||
|
283668cb01 | ||
|
22d4bcabc7 | ||
|
4f43e8d303 | ||
|
562cae387c | ||
|
932b9a5af7 | ||
|
f5e09cd676 | ||
|
f8448e3c97 | ||
|
bb53d0cd5d | ||
|
11522fa44e | ||
|
60989290e0 | ||
|
1d996d1f9a | ||
|
22763ae970 | ||
|
84c9fd457f | ||
|
0923b54d54 | ||
|
b95392a59e | ||
|
546bedef11 | ||
|
46eaf6f450 | ||
|
7773e0bfc8 | ||
|
12892ccfe4 | ||
|
4e065b1ba9 | ||
|
25f9eaf523 | ||
|
7d7a4597c1 | ||
|
fd2610c739 | ||
|
2ea4d365f9 | ||
|
7b13d0b62f | ||
|
c9685168e0 | ||
|
e5781d9f89 | ||
|
ed540673d9 | ||
|
9899bf8cd0 | ||
|
627465a734 | ||
|
34776bb0ea | ||
|
64bb924062 | ||
|
762bd0eab1 | ||
|
2dfd3688ca | ||
|
b8047384aa | ||
|
d38f93c6ed | ||
|
ba2ef08bfa | ||
|
881347b9c2 | ||
|
94cb026ad8 | ||
|
a9e2f87868 | ||
|
f8245ebb6e | ||
|
1b655c26ef | ||
|
5583c15291 | ||
|
cc9a093f16 | ||
|
437a30fdcf | ||
|
78eeb963a3 | ||
|
db4730107d | ||
|
58117de3e3 | ||
|
d38a48e900 | ||
|
2798dee036 | ||
|
76a0b00550 | ||
|
062171a2f0 | ||
|
94bc244965 | ||
|
8a199aaaf9 | ||
|
02aa49d442 | ||
|
20f84795c5 | ||
|
f847f90842 | ||
|
fa2b96e9cc | ||
|
7971bff2da | ||
|
6cbed0f458 | ||
|
e326758900 | ||
|
ee09fd6613 | ||
|
a48a16646b | ||
|
1401f4ff21 | ||
|
6ef7d23168 | ||
|
3be99a9ac7 | ||
|
040f424931 | ||
|
93ce2daff0 | ||
|
0ac170c3de | ||
|
115f00f5cd | ||
|
e73f5fb9fe | ||
|
cd0a381a35 | ||
|
709296940c | ||
|
d562c6134e | ||
|
00821945c5 | ||
|
1d8a197242 | ||
|
8e5fbef390 | ||
|
15710ef814 | ||
|
1554424e1b | ||
|
8818a0381a | ||
|
558f045b65 | ||
|
dd848142ad | ||
|
5f897468ef | ||
|
84e66f8512 | ||
|
6b0d52ca5b | ||
|
acd0875f1d | ||
|
b2d9b20edc | ||
|
1b37eb1262 | ||
|
89348910c3 | ||
|
2f740564c6 | ||
|
e04e0260c9 | ||
|
e5ee28329d | ||
|
0eb387d6de | ||
|
0d11de4525 | ||
|
82fd10408c | ||
|
e2899ffa1d | ||
|
7e6ac140c4 | ||
|
d2214b8d2e | ||
|
4e3de90cd0 | ||
|
4262d9f051 | ||
|
a73266dc4c | ||
|
e8d0fa140a | ||
|
7fb31de183 | ||
|
1b07de6fa7 | ||
|
63ce03680b | ||
|
d5f8fa11d9 | ||
|
7a4d03e2c1 | ||
|
e582bee3f9 | ||
|
73670631c8 | ||
|
e13dbc621a | ||
|
559d19018c | ||
|
7a9a50d702 | ||
|
98d534d5dd | ||
|
26236fe63a | ||
|
a3d06e6d77 | ||
|
b37afd4269 | ||
|
01e7cf44c2 | ||
|
5809b32c98 | ||
|
8748a52c68 | ||
|
65f93168f2 | ||
|
0e2fa42b60 | ||
|
0659f6e0a5 | ||
|
5f06b321b2 | ||
|
146f549552 | ||
|
8305b6cb1a | ||
|
51a1d06c51 | ||
|
63211c86de | ||
|
c490434f02 | ||
|
de85a02f74 | ||
|
8868ae956a | ||
|
bb99e4790e | ||
|
65e0740c49 | ||
|
12413ad9e8 | ||
|
5c0b20d06a | ||
|
2ab0041180 | ||
|
ab6b7102e0 | ||
|
849ece4bb0 | ||
|
2cf2665b84 | ||
|
6b1226d5ea | ||
|
eb77b208f8 | ||
|
1e1e12fad2 | ||
|
196dd55784 | ||
|
3e758d2d5c | ||
|
45c11135b8 | ||
|
d9aeb88275 | ||
|
f07e31de29 | ||
|
13acdace42 | ||
|
37178b2273 | ||
|
85350e63ef | ||
|
eb08c3facd | ||
|
449fba03be | ||
|
b06afd9074 | ||
|
b72508546c | ||
|
2b0c41609d | ||
|
1e12ad344f | ||
|
94caa9338a | ||
|
2bd4c19a7d | ||
|
6e9dac3417 | ||
|
c506808d72 | ||
|
d0ae922439 | ||
|
45529ebdc1 | ||
|
bc45f57b48 | ||
|
ac265e6ff7 | ||
|
1051033324 | ||
|
a629e2650a | ||
|
5346008b7a | ||
|
cb42b3af6a | ||
|
bcd753c28b | ||
|
637084511e | ||
|
32f8a3cbac | ||
|
d2c3f7a326 | ||
|
b57db97412 | ||
|
cdd50681cd | ||
|
18689074a8 | ||
|
cfadf8f95a | ||
|
ce1ecdba32 | ||
|
848137390e | ||
|
194ebeba94 | ||
|
deb35d8b49 | ||
|
44d12379bd | ||
|
97da73b170 | ||
|
083b0fb1e5 | ||
|
d3a767bad8 | ||
|
f6d1d81b01 | ||
|
026d1cb5e4 | ||
|
f55161c06a | ||
|
757f8a8f9e | ||
|
a6dd49ac07 | ||
|
b7545fded3 | ||
|
8688285a25 | ||
|
741fe03969 | ||
|
82b5d50c34 | ||
|
350be92cd1 | ||
|
fe45d32ef9 | ||
|
db02ae0ce7 | ||
|
ee90fee7bb | ||
|
627cb6b90a | ||
|
27934ddaac | ||
|
8f82dc8668 | ||
|
5f011e5d19 | ||
|
e68f7b0bf3 | ||
|
c5139e62bc | ||
|
1c0559affa | ||
|
d435ddd955 | ||
|
5d1b94a708 | ||
|
f24df7ccc9 | ||
|
019450132e | ||
|
1c2480a308 | ||
|
d0bb6134ae | ||
|
dac6931e81 | ||
|
8bea736651 | ||
|
da0ce1d3d6 | ||
|
3ffa4f5bf6 | ||
|
0d3519fe79 | ||
|
ede1c29a0e | ||
|
f496570df4 | ||
|
367c434754 | ||
|
4f585b6f2e | ||
|
7790d52a4d | ||
|
6ba8d9fd7d | ||
|
8ebba4fcff | ||
|
35998066c2 | ||
|
cfc5b03264 | ||
|
01564695a6 | ||
|
7141450e37 | ||
|
8edb5f4290 | ||
|
0e9d7bc446 | ||
|
f0d13fc9c4 | ||
|
594bc5b169 | ||
|
682cbe6951 | ||
|
107def4594 | ||
|
aee0786c22 | ||
|
8bd2d684b9 | ||
|
e5c2066d28 | ||
|
f81383901d | ||
|
4297a00537 | ||
|
ff760d84a3 | ||
|
af9b41e1a9 | ||
|
b2337c82a7 | ||
|
945180e1d3 | ||
|
71d27eee8e | ||
|
5846ea384a | ||
|
a649b67880 | ||
|
aaa82386d8 | ||
|
63b0589382 | ||
|
e1747af296 | ||
|
183f88a846 | ||
|
dcce7d8a57 | ||
|
3594a64bd1 | ||
|
42172826ca | ||
|
d0dd4b765c | ||
|
995f6c8ce3 | ||
|
89ede4bcce | ||
|
ec5a4cb423 | ||
|
24de6b69c4 | ||
|
0468ff400b | ||
|
30e677a762 | ||
|
bfb23b3b84 | ||
|
dd2da734ba | ||
|
4411c54ba2 | ||
|
61f0100cd9 | ||
|
1eba9c828c | ||
|
5cad467a49 | ||
|
35ae45e3ec | ||
|
125a58f7c0 | ||
|
814f5f0ccc | ||
|
546a4d0bbb | ||
|
3a04d27455 | ||
|
74edf6aef4 | ||
|
2a314bd06e | ||
|
7e456d5a8c | ||
|
2d2436f9a5 | ||
|
7abbcd685e | ||
|
d8415cfd53 | ||
|
9bd600cab6 | ||
|
d196dde23f | ||
|
6ed627f7b7 | ||
|
7a17df6bcd | ||
|
fd10a4a4a2 | ||
|
19473f8b5d | ||
|
0ed3dd4af9 | ||
|
7f594b0069 | ||
|
2b147a2998 | ||
|
4a5e7af9a4 | ||
|
628c98becb | ||
|
e60d981e07 | ||
|
cf9f283a8e | ||
|
367c5097e0 | ||
|
e5db326a7e | ||
|
d4b0513993 | ||
|
ca76392d28 | ||
|
108b6759f7 | ||
|
215b0790fd | ||
|
ed1f4876aa | ||
|
6b61197402 | ||
|
125f54d830 | ||
|
54d0e7dc53 | ||
|
d940675445 | ||
|
d4accae21b | ||
|
309fa9718e | ||
|
fb9b20e234 | ||
|
1fb9af4823 | ||
|
add7ed3731 | ||
|
4eef62a481 | ||
|
ed2a5a7973 | ||
|
7c475e1198 | ||
|
445f1c0f56 | ||
|
74a5d76145 | ||
|
4499d7590d | ||
|
7b5a2ad68c | ||
|
0eb84acc4b | ||
|
675d17fe59 | ||
|
aef757cc20 | ||
|
6f346d635e | ||
|
3637914aea | ||
|
889d78deed | ||
|
7ece6f9d2c | ||
|
0cc8842c42 | ||
|
364e940a9a | ||
|
77d489b5e5 | ||
|
44d26beb95 | ||
|
4cb8962668 | ||
|
440f704930 | ||
|
6e8e8a3d1b | ||
|
a62f060fdd | ||
|
1efb12e332 | ||
|
eb840d4117 | ||
|
b272011b21 | ||
|
f4e3964ee5 | ||
|
641e186b7c | ||
|
a9ef587705 | ||
|
d199288034 | ||
|
47cbcbd348 | ||
|
766c28ca82 | ||
|
f4a80c1a01 | ||
|
15b476bb80 | ||
|
2b495a3781 | ||
|
f2f1052da3 | ||
|
d04f17bb72 | ||
|
8925c34ff7 | ||
|
63b7ecb97e | ||
|
472c07008e | ||
|
1b9d8b1f91 | ||
|
f3f5bd8a5d | ||
|
09ccdb4ecb | ||
|
23c4aa0aa4 | ||
|
0a0edfada0 | ||
|
0500eb54da | ||
|
60df29d734 | ||
|
c2064124b9 | ||
|
c2e4ba324f | ||
|
7f51aac81b | ||
|
57746be66e | ||
|
0d1adc0692 | ||
|
7dffabef43 | ||
|
4d00eef822 | ||
|
ea725da79b | ||
|
1ac3459afa | ||
|
1b235e56a3 | ||
|
b8dd4ef20a | ||
|
07e5a3a113 | ||
|
7c55529072 | ||
|
14419ac26f | ||
|
d4a06b4477 | ||
|
bf7983dac8 | ||
|
1a865fd2fb | ||
|
e1bb6f1eb3 | ||
|
ead610b429 | ||
|
9d324bcccd | ||
|
680d4f8dc2 | ||
|
2eff5f74a5 | ||
|
d7df1a8eca | ||
|
90fefa9382 | ||
|
7b36dfb351 | ||
|
1ca6b27afe | ||
|
07e7757c31 | ||
|
f56250624f | ||
|
e781e4eb5f | ||
|
427311f2c3 | ||
|
22bd80daac | ||
|
1b5206cb90 | ||
|
93e9990df8 | ||
|
6ffafe1c45 | ||
|
5f8b6ed437 | ||
|
e07b6c90d3 | ||
|
3173a8ee3c | ||
|
ca9006a1bc | ||
|
8a8860e75c | ||
|
1ca3ce7145 | ||
|
15027f40b2 | ||
|
4b3278058b | ||
|
30f65a0b62 | ||
|
8f836969eb | ||
|
95aa8d8127 | ||
|
246d3f243d | ||
|
30a8b337e1 | ||
|
c5929e30d1 | ||
|
2ffcfb3ddd | ||
|
e1b20fe0a9 | ||
|
8ea7c578b3 | ||
|
159eccbda0 | ||
|
bc9d5aae58 | ||
|
49d449c211 | ||
|
ad8c87e5d3 | ||
|
25250179da | ||
|
cdb2eb8b9a | ||
|
e0b820abbc | ||
|
fe8939e745 | ||
|
99d012c5ce | ||
|
27329a497a | ||
|
50f2a6ad4a | ||
|
dfb778984c | ||
|
179796d598 | ||
|
2b40ab9a5b | ||
|
b905afb169 | ||
|
953479422c | ||
|
cbdd3fc928 | ||
|
5ff9fcd59a | ||
|
e6ce29ed33 | ||
|
4b87d094fb | ||
|
a377df2e65 | ||
|
7fa8fa680c | ||
|
741c7b75d8 | ||
|
7806d264ab | ||
|
102c55d67d | ||
|
6733815269 | ||
|
b85fcff990 | ||
|
55a2d71e3e | ||
|
da7ec3f7cc | ||
|
3fc8febeea | ||
|
7157ed3854 | ||
|
6c6b7956d2 | ||
|
8d61345cd6 | ||
|
cf88ddbaa5 | ||
|
8e19d6080d | ||
|
72bad83022 | ||
|
3757fcf0bf | ||
|
dc666d29b8 | ||
|
8dfa123e81 | ||
|
ef47932deb | ||
|
f804965a8d | ||
|
66f36b2d03 | ||
|
0ddffad57c | ||
|
b5e0ebe4c9 | ||
|
3552691e57 | ||
|
d12e40bc34 | ||
|
ab8159a77f | ||
|
f0fb39edd8 | ||
|
0eb431dd2b | ||
|
a9547af8e2 | ||
|
b97a5d535c | ||
|
950e9d1d0a | ||
|
9f8b848631 | ||
|
c0396cf28b | ||
|
bf7f5c6032 | ||
|
7d6a04d3a8 | ||
|
543de65f33 | ||
|
5769c9c6da | ||
|
438e0c6575 | ||
|
3bec262d2d | ||
|
a899f76da2 | ||
|
17e1027ea2 | ||
|
8be65003ce | ||
|
6678d95a5d | ||
|
9e81d7cf21 | ||
|
25bb41f549 | ||
|
812d861307 | ||
|
f53b064296 | ||
|
c43deac0a6 | ||
|
ea8b6255e3 | ||
|
44da0b24e5 | ||
|
ab7b78e9ce | ||
|
79085b5e80 | ||
|
ec30fe1b61 | ||
|
3666e3af7b | ||
|
cc90dcf556 | ||
|
d77215c227 | ||
|
8ca841d08e | ||
|
2d0940e555 | ||
|
11e1659cad | ||
|
39e2b527eb | ||
|
cb7258249d | ||
|
e7161443d6 | ||
|
baf580f0ac | ||
|
25de501eb8 | ||
|
e78f8840ea | ||
|
f00fa429bf | ||
|
48fd148b8a | ||
|
240f18e5bd | ||
|
1cec7912de | ||
|
197cbec82c | ||
|
d6471d93e2 | ||
|
100f408dae | ||
|
f1e4bcd8e5 | ||
|
20b4cefedb | ||
|
9ef9e9b7fa | ||
|
e99d0bc081 | ||
|
73e4c46756 | ||
|
33aeabd617 | ||
|
1963dd3412 | ||
|
c4496ef86b | ||
|
1e2a51f952 | ||
|
06d6f217b5 | ||
|
63c3f68619 | ||
|
b419ce34ca | ||
|
cfa2e8d25f | ||
|
ca2e36b3f3 | ||
|
8785180a3a | ||
|
7621788fb2 | ||
|
448ebd639c | ||
|
2f6eb272c1 | ||
|
e01b45f008 | ||
|
def9bf18d3 | ||
|
5c4557e4d1 | ||
|
9a88e0ab10 | ||
|
7a67840c9b | ||
|
d662fb084d | ||
|
b2c75a1af8 | ||
|
4bf1b0fa7e | ||
|
f385c94729 | ||
|
6eff07eff2 | ||
|
29ef9e909d | ||
|
5f51d84887 | ||
|
9dfd83ab7c | ||
|
69d771ae77 | ||
|
9c2cbf7588 | ||
|
25b9e23330 | ||
|
b07f0c2857 | ||
|
3ceee01713 | ||
|
6a236f7695 | ||
|
61cc9c9791 | ||
|
2d118c7057 | ||
|
81c87dc5ac | ||
|
4f2ab856a3 | ||
|
74d30afad6 | ||
|
4844534d7d | ||
|
d35e69c8a9 | ||
|
9a75b68ed8 | ||
|
70d4512635 | ||
|
da295e00f9 | ||
|
079f608700 | ||
|
3a0cb8d1fd | ||
|
7da1b1eb32 | ||
|
f5b974984c | ||
|
ce6f498358 | ||
|
8e1bd367c4 | ||
|
c296f67356 | ||
|
5513ffcd1c | ||
|
0038751106 | ||
|
719c6f2ff1 | ||
|
6c25be670d | ||
|
ce9250acb5 | ||
|
92a208104b | ||
|
59fd4ee082 | ||
|
bbc9d90888 | ||
|
d448be1077 | ||
|
48f61be73a | ||
|
8ca6b56f56 | ||
|
b7af2dd77d | ||
|
1855e4f61e | ||
|
d88d2ce92e | ||
|
2f8ef8fdf3 | ||
|
d45819d552 | ||
|
f156fc3562 | ||
|
400dc6cbcc | ||
|
9050566bdb | ||
|
cea2b1e8d8 | ||
|
ba33908f9f | ||
|
c54ce69e67 | ||
|
ab51a2ea03 | ||
|
ad0656953e | ||
|
35e7474284 | ||
|
a1c9dedc37 | ||
|
8080adbce2 | ||
|
35cc54a6b9 | ||
|
e97d3134d6 | ||
|
77e1407c51 | ||
|
79d796a437 | ||
|
cc2a458bce | ||
|
a5ae67f93c | ||
|
81c316efd1 | ||
|
46a28543b9 | ||
|
f142710fee | ||
|
f1f903ef9f | ||
|
d8a03bb34b | ||
|
871651c0c1 | ||
|
9647973983 | ||
|
117e2fecf9 | ||
|
a307d7d5c1 | ||
|
a8131c2be2 | ||
|
bf77a94721 | ||
|
5670c459ca | ||
|
672cbc3d1a | ||
|
a3518e88d3 | ||
|
56fafb8769 | ||
|
40b7274c85 | ||
|
61ce22338a | ||
|
93a24b65a9 | ||
|
b022555198 | ||
|
2ea11d4d63 | ||
|
152895b48c | ||
|
bca38907e6 | ||
|
8b29acfc59 | ||
|
8c8f2a14b6 | ||
|
859569e156 | ||
|
9c3f576cd2 | ||
|
a45f6a316e | ||
|
bd3a1c5e2e | ||
|
2ae02bedf8 | ||
|
5ef1af5aef | ||
|
8f72d2541f | ||
|
5c95bc49af | ||
|
1ee2a2a364 | ||
|
a4afddc4e1 | ||
|
6fd1c90f23 | ||
|
7a00a68ab4 | ||
|
d13561e1c7 | ||
|
336a57fdf4 | ||
|
26a9ca7a86 | ||
|
cbb01f70e7 | ||
|
089d3086cc | ||
|
1b96832bf7 | ||
|
5a10c58c35 | ||
|
596113c80f | ||
|
703cbb7bf3 | ||
|
f31056faae | ||
|
db20b79ac0 | ||
|
3344bf9439 | ||
|
2b7cc8088d | ||
|
831cfb57b4 | ||
|
f2ba0929d7 | ||
|
5c87452b67 | ||
|
f75b599e2a | ||
|
b00a2ede79 | ||
|
b08573a500 | ||
|
06ab34c068 | ||
|
9def0cb66f | ||
|
ddf65a2437 | ||
|
4ced8279c6 | ||
|
625693ac50 | ||
|
1821eb1b39 | ||
|
d1664f3502 | ||
|
6235e04ded | ||
|
9191748d82 | ||
|
26166e8f51 | ||
|
f9f4c6f36e | ||
|
f16da0fde7 | ||
|
abdfeaa96c | ||
|
3d986c95ea | ||
|
7e737977cb | ||
|
a741663b20 | ||
|
c0672d11c6 | ||
|
842b0925fe | ||
|
90d159a868 | ||
|
130d26ce0a | ||
|
bef731b9b9 | ||
|
b0bd6245fa | ||
|
54e19af0c5 | ||
|
0e9cf861f4 | ||
|
7876cdc71a | ||
|
065647154e | ||
|
6558cd5150 | ||
|
c939fbce96 | ||
|
c34ee74d08 | ||
|
66cc1a74ec | ||
|
8de565f269 | ||
|
c3f366ce9e | ||
|
7a262362df | ||
|
9a4d992778 | ||
|
fb3112b75d | ||
|
3540121449 | ||
|
a422fd80d9 | ||
|
6cbf2d7e32 | ||
|
40527ffd4e | ||
|
eb242168bf | ||
|
cfb8ef9f65 | ||
|
a988298a65 | ||
|
78e216fedb | ||
|
115f493676 | ||
|
16dc879080 | ||
|
e9f011b686 | ||
|
8c873e0f49 | ||
|
af045ab8b2 | ||
|
42386c520d | ||
|
fd56b5bdc4 | ||
|
be54cd24de | ||
|
ba96f7ddc2 | ||
|
8a43ed99ed | ||
|
84c0da2186 | ||
|
d52d1bfeee | ||
|
73628b13ea | ||
|
8cefb59efb | ||
|
908928b41c | ||
|
97cbebc0f7 | ||
|
04e93f513c | ||
|
eef3bb19d3 | ||
|
64eed3a40c | ||
|
10da2c257d | ||
|
c49d520d3d | ||
|
650bddae63 | ||
|
250678627a | ||
|
56e37d0abb | ||
|
bb0a2d3bd4 | ||
|
eccfdbd986 | ||
|
3360ad612e | ||
|
fb620464d7 | ||
|
ab813b607f | ||
|
0e6d70c395 | ||
|
27c187084b | ||
|
781ced1a59 | ||
|
8f3ac6e00b | ||
|
24652abe8a | ||
|
6e950cf49c | ||
|
4935da8fe4 | ||
|
170a5a8697 | ||
|
18a3092aa1 | ||
|
d7e35d2ad2 | ||
|
f53f83be56 | ||
|
42f4cdd40c | ||
|
f5891e1c8c | ||
|
2322f12b59 | ||
|
c03850a302 | ||
|
66002f375c | ||
|
3d901637d1 | ||
|
a7b3ccf198 | ||
|
f8a845d996 | ||
|
273941f451 | ||
|
010ab08384 | ||
|
2d9d65f33c | ||
|
b4c23b8b70 | ||
|
6a9d9700d4 | ||
|
0688c7f4e7 | ||
|
f42f2514cb | ||
|
09ed07b0c8 | ||
|
f30d568f10 | ||
|
0c79418393 | ||
|
b0f86d9fb6 | ||
|
3b08ace966 | ||
|
ee848e2367 | ||
|
9d593a2a90 | ||
|
208e7736e6 | ||
|
bb05deca33 | ||
|
cdbc7fffca | ||
|
d797aea311 | ||
|
873d5e3522 | ||
|
ef4980448a | ||
|
1c7c0b9af8 | ||
|
5a14c3c76f | ||
|
c826e8e78a | ||
|
96fb97d53a | ||
|
20d96f9ea3 | ||
|
36df20eb0e | ||
|
86d3932a16 | ||
|
784f591dee | ||
|
e80764a01e | ||
|
3b9aa272f7 | ||
|
1d1aff5622 | ||
|
464a9ac503 | ||
|
136ec3df58 | ||
|
d9b4562076 | ||
|
3a0b75a006 | ||
|
f4fb495488 | ||
|
0257c9d31e | ||
|
e4729b8dc3 | ||
|
2696bd5b44 | ||
|
9cfbb4106b | ||
|
8461571fbd | ||
|
4342b244ba | ||
|
2f3fb4a387 | ||
|
57d978b82d | ||
|
7ccd7aa4e5 | ||
|
42f9f07a07 | ||
|
9f91b50553 | ||
|
f8dd3ea133 | ||
|
0fd0e9a1af | ||
|
26751f2acd | ||
|
849b831ca4 | ||
|
4d10629acf | ||
|
341fecd3ff | ||
|
056a5c29cb | ||
|
a20ab6f0c6 | ||
|
70b83f5ca6 | ||
|
9ca763127d | ||
|
9fdae8c76f | ||
|
0141e681df | ||
|
f5c58c8065 | ||
|
3645f99259 | ||
|
105159a285 | ||
|
f958a3c2f7 | ||
|
d4a776e759 | ||
|
1ae79fe58c | ||
|
687d44859f | ||
|
2c07463ac6 | ||
|
7356961f52 | ||
|
e6d72cb23b | ||
|
dc699db5f5 | ||
|
c9be4c744f | ||
|
916b87e62e | ||
|
425901fb98 | ||
|
3b55b65a34 | ||
|
b763087e11 | ||
|
e27c57f8a6 | ||
|
821a62ffbb | ||
|
72240d0d59 | ||
|
d12d830b4d | ||
|
bd4be95754 | ||
|
c781599c0d | ||
|
8120d2ae6c | ||
|
969965f171 | ||
|
2a42084af4 | ||
|
66682b3e84 | ||
|
0d3e5e1c26 | ||
|
52e2c8c262 | ||
|
a9df841770 | ||
|
7096ee760e | ||
|
880c367d64 | ||
|
704e250664 | ||
|
928b46f18e | ||
|
f42924a9ca | ||
|
9196f696ea | ||
|
824d706a20 | ||
|
f4e9b3689d | ||
|
bbeba5c9ab | ||
|
0678957def | ||
|
85c67113b7 | ||
|
21aa608ce2 | ||
|
ed9155bfd8 | ||
|
4713f0be42 | ||
|
8407d39109 | ||
|
1f7b2a3d2d | ||
|
a7cf1b18ce | ||
|
f26ff07046 | ||
|
1c3817ad65 | ||
|
a7d3630e42 | ||
|
992d2d3be0 | ||
|
ee1232b10a | ||
|
d5a79180e7 | ||
|
f302bd8854 | ||
|
eefe65ad0e | ||
|
d7459e2bfe | ||
|
53926b8bbe | ||
|
5e80dddc82 | ||
|
585d06494e | ||
|
62de4eb8bf | ||
|
ab0a33ceae | ||
|
e15e57600e | ||
|
d02afa20b8 | ||
|
d70d1ebfcd | ||
|
eb5be9cd34 | ||
|
a3bd0d8091 | ||
|
03f755d168 | ||
|
47016765b3 | ||
|
217e4ab4f7 | ||
|
b129cb0786 | ||
|
e102e2630e | ||
|
7650795f48 | ||
|
e5036da084 | ||
|
07f4ec529b | ||
|
0b2af86ec9 | ||
|
8b917ace4d | ||
|
ab1c78ca23 | ||
|
3679bb45f0 | ||
|
1101b0dc82 | ||
|
15b4660d3e | ||
|
e457d099d8 | ||
|
7686b89cd6 | ||
|
e757639669 | ||
|
7b22546b14 | ||
|
7db14cb5cf | ||
|
83c5ceaa9c | ||
|
87ff7ae0da | ||
|
58306de28a | ||
|
56c27c4255 | ||
|
9084d746af | ||
|
18fef8dfe5 | ||
|
7e5df42fc0 | ||
|
e11a0ee448 | ||
|
18f8633dd9 | ||
|
497422e72c | ||
|
78a8993f38 | ||
|
1f7dd2fcd5 | ||
|
2ccd59e90b | ||
|
3bd610a838 | ||
|
5060a66d4e | ||
|
3c5ac535f1 | ||
|
82d721f455 | ||
|
bef6b2fffd | ||
|
fac8662387 | ||
|
15dc47555a | ||
|
171a597355 | ||
|
022f04355a | ||
|
9786614917 | ||
|
e351b1dafa | ||
|
075185547a | ||
|
514b728449 | ||
|
9a3d9feb30 | ||
|
fcb893cd12 | ||
|
e79f29dc0e | ||
|
11d7870d68 | ||
|
fc653adcc0 | ||
|
ee925492d4 | ||
|
6348309936 | ||
|
a9e098b0b4 | ||
|
8f5c3fa302 | ||
|
cbd4bd9bbe | ||
|
f4117881cd | ||
|
f6b65b3b93 | ||
|
bbea67ecb4 | ||
|
d76dd2f8e0 | ||
|
334b7fc219 | ||
|
f923dedc3f | ||
|
576f244d2d | ||
|
d03a8acc9d | ||
|
2c0d9396e2 | ||
|
bb278c7ba9 | ||
|
3bf0a93b86 | ||
|
82b5ca8bfc | ||
|
f64938cb3f | ||
|
9b0ef5fce5 | ||
|
8ce92d450c | ||
|
982f9c8458 | ||
|
f888cb87d1 | ||
|
97031ea3e6 | ||
|
a303efb174 | ||
|
029bb3efdd | ||
|
4545470f2d | ||
|
99b19b9539 | ||
|
aedb55ea36 | ||
|
49c56add7d | ||
|
17b97a48b8 | ||
|
0c71520fc6 | ||
|
65a0ce2b8b | ||
|
85393d52ad | ||
|
827d06df85 | ||
|
107afcff27 | ||
|
1793c627cd | ||
|
8f7de7a272 | ||
|
03291fb726 | ||
|
0be88f1453 | ||
|
a59c45d869 | ||
|
7f14aa6bf1 | ||
|
c7cc599a19 | ||
|
3b55c2805a | ||
|
cf097850de | ||
|
b167d8da03 | ||
|
e507a23795 | ||
|
5160fdc26a | ||
|
8f769006d6 | ||
|
d98027ad2f | ||
|
2bf43ffbf2 | ||
|
0c7f06137a | ||
|
a352bd946e | ||
|
d1e4740e70 | ||
|
3e130c3e36 | ||
|
e3bf37c261 | ||
|
5b483ab26f | ||
|
3e1bc6cb22 | ||
|
bb1d3022e0 | ||
|
a50ffa74e1 | ||
|
03f2e45605 | ||
|
ba0bcc8cd2 | ||
|
24a881ad75 | ||
|
fb630d722e | ||
|
d557fdd6c8 | ||
|
1a1c1eb6dd | ||
|
9a2fd457ba | ||
|
b7763f0427 | ||
|
e4a3b66024 | ||
|
1667d75a70 | ||
|
ce23efae99 | ||
|
38a9da5ae7 | ||
|
fe2d8f3262 | ||
|
deac7b545c | ||
|
bd4bed1438 | ||
|
fad0503696 | ||
|
21641bd2a2 | ||
|
3fba6cf57e | ||
|
23f6b25cfc | ||
|
8e959105c6 | ||
|
dde55471ba | ||
|
e36df22323 | ||
|
0fbdaa5756 | ||
|
97eea9bde2 | ||
|
682d3b087f | ||
|
b5f8e30093 | ||
|
9d9cd44617 | ||
|
c1f7a2c855 | ||
|
e0f40cb4a4 | ||
|
04e927e67f | ||
|
33643b5c6b | ||
|
605ad788d0 | ||
|
bcde8b87b1 | ||
|
cb3b2422a9 | ||
|
60cc8696e3 | ||
|
ca4dbabf70 | ||
|
c1e1e6c3a4 | ||
|
abfda4fc57 | ||
|
b09fefc4a6 | ||
|
217780bec0 | ||
|
cf6c930df5 | ||
|
03d8e5e68c | ||
|
52ef084c31 | ||
|
e1df2a2450 | ||
|
bd3f89fb57 | ||
|
f9dc932f62 | ||
|
4b08aebe7f | ||
|
1fe27effe5 | ||
|
453e760709 | ||
|
0ad9242ab7 | ||
|
5da736466c | ||
|
df256b608a | ||
|
1f5bdef96e | ||
|
261c3587a5 | ||
|
a6ba3dfce0 | ||
|
1bd5628256 | ||
|
714605ebaa | ||
|
5975ff9e42 | ||
|
a27b72e893 | ||
|
396746acc1 | ||
|
adc3af0345 | ||
|
5a82c8123b | ||
|
8ab1a4fb30 | ||
|
72701aae21 | ||
|
419be4df25 | ||
|
3966239635 | ||
|
8ae76edd88 | ||
|
46b0a933c2 | ||
|
25b2f89d31 | ||
|
7a4cd9cdcc | ||
|
8e28547f2c | ||
|
58cafbd988 | ||
|
16de7a0715 | ||
|
16c6e2c6d3 | ||
|
538e7561b0 | ||
|
0769a541d5 | ||
|
e0d1d253da | ||
|
dbdf5fabe7 | ||
|
90ee4cdb4c | ||
|
c57eedd4e7 | ||
|
e575d188c7 | ||
|
9c30ebfed2 | ||
|
02c1fbd791 | ||
|
72257e1766 | ||
|
ed29278fd0 | ||
|
7a15c3af57 | ||
|
8fa681a16b | ||
|
9e92f5d032 | ||
|
3cc67489fa | ||
|
b47e25155e | ||
|
9ee5e2cbde | ||
|
40263b09f8 | ||
|
4e72924893 | ||
|
0f64491b9a | ||
|
644825311c | ||
|
2331c50159 | ||
|
589afbea30 | ||
|
9d8e9a6c7d | ||
|
4f6c4391fc | ||
|
61178724af | ||
|
c64f7821ef | ||
|
45063938df | ||
|
2077e58fd7 | ||
|
4edbbecdb3 | ||
|
332de4bb78 | ||
|
484a038e68 | ||
|
7e631e34df | ||
|
6a962f044e | ||
|
7dbc44ff7f | ||
|
a96483a28b | ||
|
5aee4d195d | ||
|
3fd088b338 | ||
|
1657cd8af2 | ||
|
a8230a6411 | ||
|
d5bf1db06e | ||
|
561bc0d10c | ||
|
3ad469d9b5 | ||
|
19b48c3c82 | ||
|
216caf9130 | ||
|
06b8b33a9e | ||
|
b8c3d15994 | ||
|
9a4475d779 | ||
|
49c17942d0 | ||
|
717ccf9193 | ||
|
61496e72fa | ||
|
5de9ede750 | ||
|
3081be948a | ||
|
fb8e69ca6c | ||
|
6ef31e1622 | ||
|
160f8c2aea | ||
|
d51bf842e1 | ||
|
8d314d2d56 | ||
|
f431863593 | ||
|
67d0565e64 | ||
|
b64e8c831d | ||
|
96251ed1c3 | ||
|
0dd93810ac | ||
|
4d654b71e3 | ||
|
7778518afd | ||
|
261ab35b9c | ||
|
ae32a41082 | ||
|
a063390de9 | ||
|
b250c748a8 | ||
|
2557cc23cd | ||
|
8b6d605d55 | ||
|
963e2f46b8 | ||
|
e3816fa138 | ||
|
76f29dcddd | ||
|
276195c2ba | ||
|
af4a7086df | ||
|
b88e5589ed | ||
|
252802870f | ||
|
6af4da1db3 | ||
|
c52aeb3856 | ||
|
42b065b1fc | ||
|
94bf3af04d | ||
|
5764d9672e | ||
|
f9878e7fcb | ||
|
1cc9f61ba7 | ||
|
cdbd9eb8eb | ||
|
ee99e34e25 | ||
|
93f20fb656 | ||
|
cf7c0900b6 | ||
|
cb1a24bf06 | ||
|
c50726de2d | ||
|
90e7e82078 | ||
|
039940a131 | ||
|
f0ab3a46de | ||
|
7477a4da8e | ||
|
830cc1b4d2 | ||
|
7333a925b4 | ||
|
70f370f0d3 | ||
|
5a42657ff3 | ||
|
d23712da4e | ||
|
792be6a8d8 | ||
|
2ec1cd7ee1 | ||
|
9c59e98f89 | ||
|
45f1522561 | ||
|
d47544e1e3 | ||
|
f7ed4f3220 | ||
|
26f006bd32 | ||
|
fb3240046d | ||
|
14aba17cc3 | ||
|
d385752155 | ||
|
93883ef27f | ||
|
0e6c414150 | ||
|
5b6bc48429 | ||
|
a9d9a19e35 | ||
|
7ba07d8f75 | ||
|
5989d6aa5a | ||
|
d790e2489e | ||
|
473fa63cfa | ||
|
ceb7663242 | ||
|
38294a61ea | ||
|
29548f70a8 | ||
|
62c13e6eaf | ||
|
fcda9f3e68 | ||
|
e1618f20a1 | ||
|
718f24b826 | ||
|
212e0d8f46 | ||
|
71d26e85e1 | ||
|
a2a47826d4 | ||
|
bba3ce09cd | ||
|
e797bb0dc5 | ||
|
250093d9f0 | ||
|
703640f7c2 | ||
|
ff9483c2bd | ||
|
a927a9f6a2 | ||
|
42d6322ce3 | ||
|
4e5f5eaf48 | ||
|
91b32f9c5a | ||
|
1b2af1c635 | ||
|
f95aa970e9 | ||
|
2797322f0b | ||
|
7e302bda96 | ||
|
37750cb9f4 | ||
|
a9732a71ae | ||
|
d8e76719a9 | ||
|
3f101bcdb7 | ||
|
ab986233c3 | ||
|
71828d8274 | ||
|
746d7f6af7 | ||
|
07dd0e832f | ||
|
43820c920e | ||
|
b700eea6f9 | ||
|
a1014f7656 | ||
|
5c94a7b15d | ||
|
96783d2a55 | ||
|
dce9b215af | ||
|
25db582a0a | ||
|
0d74bd3689 | ||
|
332c8801da | ||
|
8255966384 | ||
|
d5653c0215 | ||
|
e635454ebd | ||
|
76d79d8cd0 | ||
|
d0a64e1736 | ||
|
51ec85fdd5 | ||
|
ac5c2a041d | ||
|
5a433e22ac | ||
|
1d8938cc28 | ||
|
0da1cce660 | ||
|
147e6fb580 | ||
|
d0531c8beb | ||
|
26c1f01b87 | ||
|
a7feb620d1 | ||
|
19f24a61bf | ||
|
e7e25a11e7 | ||
|
3f20295760 | ||
|
258eb36432 | ||
|
5cabeee80d | ||
|
92d256ae06 | ||
|
a0b330863b | ||
|
7bc8781d16 | ||
|
d07b529c92 | ||
|
da8f45ae18 | ||
|
c29c3f610d | ||
|
7afb2443d5 | ||
|
945cc0ef23 | ||
|
719812ffd6 | ||
|
6fd9088b97 | ||
|
b2533793c7 | ||
|
1af2ee7fab | ||
|
36ce87e1dc | ||
|
353005a924 | ||
|
6cf365e11d | ||
|
52541c786b | ||
|
b58bc964c3 | ||
|
e23c92de5e | ||
|
5329b77df6 | ||
|
c7aa9ba056 | ||
|
3fb500344c | ||
|
3d9ddf7d7b | ||
|
c848867797 | ||
|
b144449cfe | ||
|
f364ee5660 | ||
|
26578f849e | ||
|
4929a26e89 | ||
|
4b96a4ab24 | ||
|
ce4d0e6aea | ||
|
c55e426fd9 | ||
|
afa70e1944 | ||
|
3f70007410 | ||
|
54a7f31433 | ||
|
870d9200e8 | ||
|
9baebce7fd | ||
|
2b32e1ac5c | ||
|
067ca16112 | ||
|
25d1022c4c | ||
|
7e471444d6 | ||
|
42f8bc50f8 | ||
|
ae53c6ba84 | ||
|
2e47911369 | ||
|
d38db49bc9 | ||
|
e28dfc2358 | ||
|
64e8295f82 | ||
|
404cfc451d | ||
|
a33cd43d09 | ||
|
961b603f78 | ||
|
07fe2aef4f | ||
|
af3ffa855e | ||
|
7c6ff1a367 | ||
|
5dd2673714 | ||
|
70ebf4dd96 | ||
|
4c73fc0f53 | ||
|
009c96b2ea | ||
|
f6557c5fe5 | ||
|
5a92312cf2 | ||
|
8c36035aa0 | ||
|
09bd05dfef | ||
|
1cbeefbf50 | ||
|
fb8e1ad6cd | ||
|
85fcf11804 | ||
|
a8a3171401 | ||
|
7bd99940b8 | ||
|
fe171b84bf | ||
|
69d86ce2cf | ||
|
6bca9b3e6e | ||
|
040c5cdf67 | ||
|
42c05c8ac3 | ||
|
2e6dd6a075 | ||
|
d39bd34baf | ||
|
4f8309d41c | ||
|
b48a026061 | ||
|
e9f3c88844 | ||
|
b4ca18177f | ||
|
1f52bfac4e | ||
|
b7d993d211 | ||
|
c89a55fc83 | ||
|
8a2c5c1727 | ||
|
8814ebd8a9 | ||
|
5c6ae3f1b0 | ||
|
cf55b16914 | ||
|
6e81d0fe3a | ||
|
84659674cd | ||
|
0c29aa2df8 | ||
|
d4d9aaf1c6 | ||
|
7ba794f484 | ||
|
391913cce3 | ||
|
d0488b7d0c | ||
|
da89f461bd | ||
|
87726c641e | ||
|
d133175a5c | ||
|
83c397620c | ||
|
a1af1655b4 | ||
|
46e53997a8 | ||
|
271a1ffa86 | ||
|
c8eec9e5f0 | ||
|
627161258f | ||
|
73faaeae2f | ||
|
15eaff15fb | ||
|
62e065c52f | ||
|
c5c48bafa0 | ||
|
92f2461337 | ||
|
5f78d49777 | ||
|
c652970f02 | ||
|
518a944884 | ||
|
e31cb0a77b | ||
|
2b4a087f39 | ||
|
001d6cf9d3 | ||
|
6f4dff78a7 | ||
|
96e04b1285 | ||
|
454636624c | ||
|
13bf2ba42f | ||
|
b8fd5bdeae | ||
|
29acd744b8 | ||
|
031416a1de | ||
|
3a54f44886 | ||
|
6590a06d93 | ||
|
567c5f3326 | ||
|
bff6890358 | ||
|
c857568b7a | ||
|
1e019b18ec | ||
|
5bc59ed489 | ||
|
587c8b82a9 | ||
|
7c88deedc8 | ||
|
138fd82a8c | ||
|
63f126d98f | ||
|
47a9a57b76 | ||
|
31c4d934ad | ||
|
c1ffc18738 | ||
|
d9348971a7 | ||
|
fc49a1a8b6 | ||
|
e6e172db90 | ||
|
978bc2a4ef | ||
|
f131c96c0b | ||
|
345c398be9 | ||
|
5cbc2273de | ||
|
04a8454fff | ||
|
243d7c5e29 | ||
|
4b4bd83a39 | ||
|
1396e215c9 | ||
|
ee9860dc35 | ||
|
3275a33827 | ||
|
929d302f4d | ||
|
69c0125db5 | ||
|
6c2b3cfbdd | ||
|
de81e06efc | ||
|
cd379d131d | ||
|
28931b32b5 | ||
|
8a10f5565b | ||
|
769be16fc6 | ||
|
35983e9e5f | ||
|
c61f662c86 | ||
|
88172bf1b3 | ||
|
c1aff3631f | ||
|
99fd0b76c2 | ||
|
79ae0c5130 | ||
|
7acdbcdac5 | ||
|
5df04e5a13 | ||
|
feb2601607 | ||
|
283b2f9b8f | ||
|
417ff583a2 | ||
|
da24829bba | ||
|
34100f9b94 | ||
|
95f6ec5da2 | ||
|
2a15fdff05 | ||
|
2a327a91e3 | ||
|
07e84bf315 | ||
|
5ad6958888 | ||
|
76693e6a1f | ||
|
c2aed163bc | ||
|
8d1a6b524d | ||
|
709a9e9078 | ||
|
a1e1c66f1d | ||
|
09f11a4091 | ||
|
cf1c4bd7ae | ||
|
4b19c677b3 | ||
|
779f602df7 | ||
|
66c36446fa | ||
|
e761ae9008 | ||
|
f37c8627a6 | ||
|
1d737d0ff8 | ||
|
5eb07fe901 | ||
|
1a8af0e660 | ||
|
f5ad4b12b2 | ||
|
c2ec6467d7 | ||
|
ba50c166f8 | ||
|
b3143d057c | ||
|
67987fa29b | ||
|
af89d58647 | ||
|
61f63cfa5c | ||
|
4c7dbad755 | ||
|
2d1ab745e3 | ||
|
ad683fb117 | ||
|
8ccbbb2f2d | ||
|
d22d28dc48 | ||
|
08423f0d5a | ||
|
3afc94d68e | ||
|
c7bc6a17a0 | ||
|
9b9789d299 | ||
|
4c33e9a16a | ||
|
b7ce68897d | ||
|
21c2b15b8e | ||
|
5e2c6b87d5 | ||
|
0ad9ae9432 | ||
|
8d4a98d5f9 | ||
|
acb0a6aeba | ||
|
a5b7426f6b | ||
|
491789bb05 | ||
|
0407a699ea | ||
|
9c3ada3e88 | ||
|
60a19afeed | ||
|
db931e15bd | ||
|
7997265ce9 | ||
|
3a45d658ca | ||
|
48fe6af82b | ||
|
c18298f8ea | ||
|
d7c9c7fa20 | ||
|
6bb046fad6 | ||
|
e9e8b47c06 | ||
|
160ad68007 | ||
|
9694ca2f27 | ||
|
3c1d85dadb | ||
|
fccb7ef647 | ||
|
d93ab0fb8c | ||
|
d1f3c2d73b | ||
|
dd25323a08 | ||
|
a6016c63aa | ||
|
e7dd377e27 | ||
|
c0c573d40c | ||
|
88b33d3830 | ||
|
e6c4efbb11 | ||
|
56b21bbb20 | ||
|
f16890ac36 | ||
|
dd8bf404e8 | ||
|
d8bd2b22a7 | ||
|
3725c46a3c | ||
|
c36641aa0a | ||
|
69d2f5ddc3 | ||
|
77b839748f | ||
|
55b56b4b5d | ||
|
de8fbc3f9d | ||
|
f4fddc4268 | ||
|
7499e44046 | ||
|
31470eabde | ||
|
93e46baa4a | ||
|
0440765680 | ||
|
170b6cadc2 | ||
|
368101a73e | ||
|
87e4e3c4a0 | ||
|
a57b08c200 | ||
|
cc307ae6ab | ||
|
a49b4713a4 | ||
|
6cb208966a | ||
|
4ba0026b88 | ||
|
a2264bcc2b | ||
|
2dc14dae8e | ||
|
554ebcdff4 | ||
|
5392615053 | ||
|
64ca3857c3 | ||
|
03c2b7f526 | ||
|
f9db712033 | ||
|
5571bc0efa | ||
|
f11d932d4b | ||
|
cb2ef737f0 | ||
|
f57955d8c0 | ||
|
82571a3ab9 | ||
|
4570bc24e7 | ||
|
db3f7af489 | ||
|
6bfa27ec00 | ||
|
3e6001f098 | ||
|
82243914de | ||
|
c07654e3df | ||
|
6c941fc4c9 | ||
|
e6c1125988 | ||
|
fbe90c22af | ||
|
1727d2f267 | ||
|
c29bca3fe0 | ||
|
a65f57cfc9 | ||
|
47600ea6d1 | ||
|
edade9423f | ||
|
742deb1203 | ||
|
2082fff1d2 | ||
|
32402eeafa | ||
|
ed42185927 | ||
|
297cf45bba | ||
|
213c65676e | ||
|
188b9efd79 | ||
|
a9e4315665 | ||
|
f73171ac4c | ||
|
56fbec7b55 | ||
|
6d0965ef3f | ||
|
44368db30a | ||
|
9afa2935cd | ||
|
39c9f82c9c | ||
|
2d980c2af6 | ||
|
a0b76fa594 | ||
|
dae0f1078d | ||
|
8b0d27bd18 | ||
|
6093042863 | ||
|
0053721896 | ||
|
2914b3ea1b | ||
|
ff86874d66 | ||
|
8882a477be | ||
|
9bff57a60d | ||
|
66c578fa8d | ||
|
32039bd388 | ||
|
04a2681ba9 | ||
|
49afe4bc8e | ||
|
026fa922d2 | ||
|
07de427aab | ||
|
163cf52900 | ||
|
cdf77c8a0d | ||
|
07fd7135e3 | ||
|
bbba9e60ee | ||
|
254583dd64 | ||
|
a8fe13a6d4 | ||
|
8b2986c80a | ||
|
0bd31b0404 | ||
|
4666a96b56 | ||
|
ec44f2e4f4 | ||
|
b6e0e226a1 | ||
|
041db6e3d7 | ||
|
423c7b57e3 | ||
|
e0c5e81b5b | ||
|
84b96b4f18 | ||
|
846a4a19ae | ||
|
c7d390f864 | ||
|
88d6989c8f | ||
|
8f68f9bdef | ||
|
e3d7180932 | ||
|
8e2b041498 | ||
|
c0b7b0bc27 | ||
|
45e7363dfb | ||
|
8d93c34031 | ||
|
555f0ba6cf | ||
|
b513a892af | ||
|
2aedea7d5f | ||
|
d852999cba | ||
|
b04dcdc42f | ||
|
b95503065f | ||
|
433d6ded6d | ||
|
d698b98988 | ||
|
2e9fe3f185 | ||
|
e21338d81e | ||
|
c8f1134196 | ||
|
bbef3d8abc | ||
|
77ea82baee | ||
|
e91be5bd12 | ||
|
35f098e04a | ||
|
2bc12b80cc | ||
|
d4bdef0be3 | ||
|
f43c600adc | ||
|
b7c121de9c | ||
|
09f6392173 | ||
|
0b4f015d3a | ||
|
0ceadc2b95 | ||
|
e2f26467ab | ||
|
5bbb71e90e | ||
|
f42e904dba | ||
|
4752f70809 | ||
|
095e5317cb | ||
|
ff7cf9b9ec | ||
|
7264c9dcbf | ||
|
27602cf832 | ||
|
9ae4755b1c | ||
|
206a89e06c | ||
|
19e41a3c71 | ||
|
a2c7256406 | ||
|
381f3e9bb3 | ||
|
5e81ddecad | ||
|
9a643431dd | ||
|
c61e53edf7 | ||
|
37df041b9c | ||
|
b293f0320d | ||
|
f71602ec6c | ||
|
811b1422e9 | ||
|
e1d72552db | ||
|
9d2291b74e | ||
|
a279eaf4fa | ||
|
e0dc6e03fd | ||
|
f5793a760d | ||
|
4a88223f6d | ||
|
4a7c469f96 | ||
|
cd76aa599f | ||
|
af8b0e84a4 | ||
|
3f614ee3a6 | ||
|
3a5cb47081 | ||
|
c0898c308b | ||
|
4a35035396 | ||
|
93ecf0d44d | ||
|
601f61fefa | ||
|
645ba95989 | ||
|
b1169dc48c | ||
|
b935c7db79 | ||
|
1b8b5aab13 | ||
|
87006eaa20 | ||
|
9d18fb1ece | ||
|
b8bd65d69b | ||
|
499fd513b4 | ||
|
eb6bb49d5a | ||
|
17c0dd08c7 | ||
|
7e59fa9e40 | ||
|
f78cd25fe9 | ||
|
dbdc50b8a8 | ||
|
fef4832a65 | ||
|
ebfa1e2838 | ||
|
130eb43b26 | ||
|
9a5221bbd8 | ||
|
fce053439c | ||
|
a1b2a71267 | ||
|
0956ea5dec | ||
|
c9946117cd | ||
|
7a24975654 | ||
|
a5b4e3f518 | ||
|
0153c47e29 | ||
|
b042506ac9 | ||
|
b6f8d6ae92 | ||
|
3edf1bb162 | ||
|
2a74fc423f | ||
|
431e6b8c03 | ||
|
11dd15f123 | ||
|
36a96fedfb | ||
|
a37896da49 | ||
|
97b06e3101 | ||
|
9fe9320555 | ||
|
c06903e168 | ||
|
b4a63ecb28 | ||
|
5eb56733b8 | ||
|
18f4b6e50c | ||
|
74c2090ebc | ||
|
4ed06d4fe3 | ||
|
ec2094d768 | ||
|
a1c4c23051 | ||
|
027ba074ed | ||
|
b6811c65e8 | ||
|
cb6f9ae576 | ||
|
94916f59e0 | ||
|
8a3047f1ab | ||
|
b593682c0c | ||
|
1917844338 | ||
|
2b00d28de2 | ||
|
8632c3d609 | ||
|
d935b7df68 | ||
|
021e3b20c6 | ||
|
dcea99e278 | ||
|
9dfbc54fda | ||
|
94b8ad3b6e | ||
|
77fb264129 | ||
|
0c29233062 | ||
|
cc4ab32350 | ||
|
5610e274ba | ||
|
c70e91fa9a | ||
|
ac43d43409 | ||
|
7dfac7b5bf | ||
|
8627f291ca | ||
|
045ec0408d | ||
|
fe92450e7b | ||
|
7ed780014d | ||
|
06facb22cb | ||
|
6927ca6439 | ||
|
29392f24ee | ||
|
f03195150b | ||
|
5adf8775fa | ||
|
cda9e2f0c1 | ||
|
ff8be85b08 | ||
|
d50a27cb4c | ||
|
587681b14c | ||
|
d7c8ff5a45 | ||
|
6b44320bfd | ||
|
295cf12b9a |
@ -22,6 +22,7 @@ Cpp11BracedListStyle: "false"
|
|||||||
FixNamespaceComments: "true"
|
FixNamespaceComments: "true"
|
||||||
IncludeBlocks: Preserve
|
IncludeBlocks: Preserve
|
||||||
IndentWidth: "4"
|
IndentWidth: "4"
|
||||||
|
InsertBraces: "true"
|
||||||
MaxEmptyLinesToKeep: "2"
|
MaxEmptyLinesToKeep: "2"
|
||||||
NamespaceIndentation: None
|
NamespaceIndentation: None
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
|
10
.gersemirc
Normal file
10
.gersemirc
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# SPDX-FileCopyrightText: no
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
#
|
||||||
|
# Gersemi configuration
|
||||||
|
color: false
|
||||||
|
definitions: [ CMakeModules/CalamaresAddTest.cmake ]
|
||||||
|
line_length: 120
|
||||||
|
quiet: false
|
||||||
|
unsafe: false
|
||||||
|
|
14
.github/workflows/issues.yml
vendored
14
.github/workflows/issues.yml
vendored
@ -8,20 +8,6 @@ jobs:
|
|||||||
notify:
|
notify:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: "notify: new"
|
|
||||||
if: github.event.issue.state == 'open'
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: "OPENED ${{ github.event.issue.html_url }} by ${{ github.actor }} ${{ github.event.issue.title }}"
|
|
||||||
- name: "notify: closed"
|
|
||||||
if: github.event.issue.state != 'open'
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: "CLOSED ${{ github.event.issue.html_url }} by ${{ github.actor }} ${{ github.event.issue.title }}"
|
|
||||||
- name: "remove in-progress label"
|
- name: "remove in-progress label"
|
||||||
if: github.event.issue.state != 'open'
|
if: github.event.issue.state != 'open'
|
||||||
run: |
|
run: |
|
||||||
|
40
.github/workflows/nightly-debian.yml
vendored
40
.github/workflows/nightly-debian.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: nightly-debian-10
|
name: nightly-debian-11
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
@ -9,38 +9,28 @@ env:
|
|||||||
BUILDDIR: /build
|
BUILDDIR: /build
|
||||||
SRCDIR: ${{ github.workspace }}
|
SRCDIR: ${{ github.workspace }}
|
||||||
CMAKE_ARGS: |
|
CMAKE_ARGS: |
|
||||||
-DWEBVIEW_FORCE_WEBKIT=1
|
|
||||||
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
||||||
-DWITH_PYTHONQT=OFF"
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
-DBUILD_APPSTREAM=ON
|
||||||
|
-DBUILD_APPDATA=ON
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: docker://debian:10
|
image: docker://debian:11
|
||||||
options: --tmpfs /build:rw --user 0:0
|
options: --tmpfs /build:rw --user 0:0
|
||||||
steps:
|
steps:
|
||||||
- name: "prepare env"
|
- name: "prepare git"
|
||||||
uses: calamares/actions/prepare-debian@v4
|
shell: bash
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install git-core jq curl
|
||||||
- name: "prepare source"
|
- name: "prepare source"
|
||||||
uses: calamares/actions/generic-checkout@v4
|
uses: calamares/actions/generic-checkout@v5
|
||||||
|
- name: "install dependencies"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/deps-debian11.sh
|
||||||
- name: "build"
|
- name: "build"
|
||||||
id: build
|
shell: bash
|
||||||
uses: calamares/actions/generic-build@v4
|
run: ./ci/build.sh
|
||||||
- name: "notify: ok"
|
|
||||||
if: ${{ success() && github.repository == 'calamares/calamares' }}
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: |
|
|
||||||
OK ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
|
|
||||||
- name: "notify: fail"
|
|
||||||
if: ${{ failure() && github.repository == 'calamares/calamares' }}
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: |
|
|
||||||
FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
|
|
||||||
|
36
.github/workflows/nightly-fedora-qt6-boost.yml
vendored
Normal file
36
.github/workflows/nightly-fedora-qt6-boost.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: nightly-fedora-qt6-boost
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "52 2 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILDDIR: /build
|
||||||
|
SRCDIR: ${{ github.workspace }}
|
||||||
|
CMAKE_ARGS: |
|
||||||
|
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
-DWITH_QT6=ON
|
||||||
|
-DBUILD_APPSTREAM=ON
|
||||||
|
-DBUILD_APPDATA=ON
|
||||||
|
-DWITH_PYBIND11=OFF
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: docker://registry.fedoraproject.org/fedora:40
|
||||||
|
options: --tmpfs /build:rw --user 0:0
|
||||||
|
steps:
|
||||||
|
- name: "prepare git"
|
||||||
|
shell: bash
|
||||||
|
run: yum install -y git-core jq curl
|
||||||
|
- name: "prepare source"
|
||||||
|
uses: calamares/actions/generic-checkout@v5
|
||||||
|
- name: "install dependencies"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/deps-fedora-qt6-boost.sh
|
||||||
|
- name: "build"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/build.sh
|
35
.github/workflows/nightly-fedora-qt6.yml
vendored
Normal file
35
.github/workflows/nightly-fedora-qt6.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
name: nightly-fedora-qt6
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "52 2 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILDDIR: /build
|
||||||
|
SRCDIR: ${{ github.workspace }}
|
||||||
|
CMAKE_ARGS: |
|
||||||
|
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
-DWITH_QT6=ON
|
||||||
|
-DBUILD_APPSTREAM=ON
|
||||||
|
-DBUILD_APPDATA=ON
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: docker://registry.fedoraproject.org/fedora:40
|
||||||
|
options: --tmpfs /build:rw --user 0:0
|
||||||
|
steps:
|
||||||
|
- name: "prepare git"
|
||||||
|
shell: bash
|
||||||
|
run: yum install -y git-core jq curl
|
||||||
|
- name: "prepare source"
|
||||||
|
uses: calamares/actions/generic-checkout@v5
|
||||||
|
- name: "install dependencies"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/deps-fedora-qt6.sh
|
||||||
|
- name: "build"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/build.sh
|
58
.github/workflows/nightly-neon.yml
vendored
58
.github/workflows/nightly-neon.yml
vendored
@ -1,58 +0,0 @@
|
|||||||
name: nightly-neon
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "52 23 * * *"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
BUILDDIR: /build
|
|
||||||
SRCDIR: ${{ github.workspace }}
|
|
||||||
CMAKE_ARGS: |
|
|
||||||
-DWEBVIEW_FORCE_WEBKIT=1
|
|
||||||
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
|
||||||
-DWITH_PYTHONQT=OFF"
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: docker://kdeneon/plasma:user
|
|
||||||
options: --tmpfs /build:rw --user 0:0
|
|
||||||
steps:
|
|
||||||
- name: "prepare env"
|
|
||||||
uses: calamares/actions/prepare-neon@v4
|
|
||||||
- name: "prepare source"
|
|
||||||
uses: calamares/actions/generic-checkout@v4
|
|
||||||
- name: "build"
|
|
||||||
id: build
|
|
||||||
uses: calamares/actions/generic-build@v4
|
|
||||||
- name: "notify: ok"
|
|
||||||
if: ${{ success() && github.repository == 'calamares/calamares' }}
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: |
|
|
||||||
OK ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
|
|
||||||
- name: "notify: fail"
|
|
||||||
if: ${{ failure() && github.repository == 'calamares/calamares' }}
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: |
|
|
||||||
FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
|
|
||||||
- name: "Calamares: archive"
|
|
||||||
working-directory: ${{ env.BUILDDIR }}
|
|
||||||
run: |
|
|
||||||
make install DESTDIR=${{ env.BUILDDIR }}/stage
|
|
||||||
tar czf calamares.tar.gz stage
|
|
||||||
- name: "Calamares: upload"
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: calamares-tarball
|
|
||||||
path: ${{ env.BUILDDIR }}/calamares.tar.gz
|
|
||||||
if-no-files-found: error
|
|
||||||
retention-days: 7
|
|
39
.github/workflows/nightly-opensuse.yml
vendored
39
.github/workflows/nightly-opensuse.yml
vendored
@ -9,38 +9,29 @@ env:
|
|||||||
BUILDDIR: /build
|
BUILDDIR: /build
|
||||||
SRCDIR: ${{ github.workspace }}
|
SRCDIR: ${{ github.workspace }}
|
||||||
CMAKE_ARGS: |
|
CMAKE_ARGS: |
|
||||||
-DWEBVIEW_FORCE_WEBKIT=1
|
|
||||||
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
||||||
-DWITH_PYTHONQT=OFF"
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
-DBUILD_SCHEMA_TESTING=ON
|
||||||
|
-DBUILD_TESTING=ON
|
||||||
|
-DBUILD_APPSTREAM=ON
|
||||||
|
-DBUILD_APPDATA=ON
|
||||||
|
-DWITH_QT6=ON
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: docker://opensuse/leap
|
image: docker://opensuse/tumbleweed
|
||||||
options: --tmpfs /build:rw --user 0:0
|
options: --tmpfs /build:rw --user 0:0
|
||||||
steps:
|
steps:
|
||||||
- name: "prepare env"
|
- name: "prepare git"
|
||||||
uses: calamares/actions/prepare-opensuse@v4
|
shell: bash
|
||||||
|
run: zypper --non-interactive in git-core jq curl
|
||||||
- name: "prepare source"
|
- name: "prepare source"
|
||||||
uses: calamares/actions/generic-checkout@v4
|
uses: calamares/actions/generic-checkout@v5
|
||||||
|
- name: "install dependencies"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/deps-opensuse-qt6.sh
|
||||||
- name: "build"
|
- name: "build"
|
||||||
id: build
|
shell: bash
|
||||||
uses: calamares/actions/generic-build@v4
|
run: ./ci/build.sh
|
||||||
- name: "notify: ok"
|
|
||||||
if: ${{ success() && github.repository == 'calamares/calamares' }}
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: |
|
|
||||||
OK ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
|
|
||||||
- name: "notify: fail"
|
|
||||||
if: ${{ failure() && github.repository == 'calamares/calamares' }}
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: |
|
|
||||||
FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
|
|
||||||
|
36
.github/workflows/nightly-ubuntu.yml
vendored
Normal file
36
.github/workflows/nightly-ubuntu.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: nightly-ubuntu
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "12 23 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILDDIR: /build
|
||||||
|
SRCDIR: ${{ github.workspace }}
|
||||||
|
CMAKE_ARGS: |
|
||||||
|
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
-DBUILD_APPSTREAM=ON
|
||||||
|
-DBUILD_APPDATA=ON
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: docker://ubuntu:devel
|
||||||
|
options: --tmpfs /build:rw --user 0:0
|
||||||
|
steps:
|
||||||
|
- name: "prepare git"
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install git-core jq curl ninja-build
|
||||||
|
- name: "prepare source"
|
||||||
|
uses: calamares/actions/generic-checkout@v5
|
||||||
|
- name: "install dependencies"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/deps-ubuntu.sh
|
||||||
|
- name: "build"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/build.sh
|
44
.github/workflows/push.yml
vendored
44
.github/workflows/push.yml
vendored
@ -3,7 +3,7 @@ name: ci-push
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 3.2.x-stable
|
- calamares
|
||||||
pull_request:
|
pull_request:
|
||||||
types:
|
types:
|
||||||
- opened
|
- opened
|
||||||
@ -15,41 +15,29 @@ env:
|
|||||||
BUILDDIR: /build
|
BUILDDIR: /build
|
||||||
SRCDIR: ${{ github.workspace }}
|
SRCDIR: ${{ github.workspace }}
|
||||||
CMAKE_ARGS: |
|
CMAKE_ARGS: |
|
||||||
-DWEBVIEW_FORCE_WEBKIT=1
|
|
||||||
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
||||||
-DWITH_PYTHONQT=OFF"
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
-DWITH_QT6=ON
|
||||||
|
-DBUILD_APPSTREAM=ON
|
||||||
|
-DBUILD_APPDATA=ON
|
||||||
|
|
||||||
|
GIT_HASH: ${{ github.event.head_commit.id }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: docker://kdeneon/plasma:user
|
image: docker://registry.fedoraproject.org/fedora:40
|
||||||
options: --tmpfs /build:rw --user 0:0
|
options: --tmpfs /build:rw --user 0:0
|
||||||
steps:
|
steps:
|
||||||
- name: "prepare env"
|
- name: "prepare git"
|
||||||
uses: calamares/actions/prepare-neon@v4
|
shell: bash
|
||||||
|
run: yum install -y git-core jq curl
|
||||||
- name: "prepare source"
|
- name: "prepare source"
|
||||||
uses: calamares/actions/generic-checkout@v4
|
uses: calamares/actions/generic-checkout@v5
|
||||||
|
- name: "install dependencies"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/deps-fedora-qt6.sh
|
||||||
- name: "build"
|
- name: "build"
|
||||||
id: build
|
shell: bash
|
||||||
uses: calamares/actions/generic-build@v4
|
run: ./ci/build.sh
|
||||||
- name: "notify: ok"
|
|
||||||
if: ${{ success() && github.repository == 'calamares/calamares' }}
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: |
|
|
||||||
OK ${{ github.workflow }} in ${{ github.repository }} by ${{ github.actor }} on ${{ github.event.ref }}
|
|
||||||
.. ${{ steps.build.outputs.git-summary }}
|
|
||||||
- name: "notify: fail"
|
|
||||||
if: ${{ failure() && github.repository == 'calamares/calamares' }}
|
|
||||||
uses: calamares/actions/matrix-notify@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.MATRIX_TOKEN }}
|
|
||||||
room: ${{ secrets.MATRIX_ROOM }}
|
|
||||||
message: |
|
|
||||||
FAIL ${{ github.workflow }} in ${{ github.repository }} by ${{ github.actor }} on ${{ github.event.ref }}
|
|
||||||
.. ${{ steps.build.outputs.git-summary }}
|
|
||||||
.. ${{ github.event.compare }}
|
|
||||||
|
47
.github/workflows/weekly-debian.yml
vendored
Normal file
47
.github/workflows/weekly-debian.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
name: weekly-debian-11
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "12 11 * * 3"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILDDIR: /build
|
||||||
|
SRCDIR: ${{ github.workspace }}
|
||||||
|
CMAKE_ARGS: |
|
||||||
|
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
-DBUILD_APPSTREAM=ON
|
||||||
|
-DBUILD_APPDATA=ON
|
||||||
|
-DBUILD_TESTING=ON
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: docker://debian:11
|
||||||
|
options: --tmpfs /build:rw --user 0:0
|
||||||
|
steps:
|
||||||
|
- name: "prepare git"
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install git-core jq curl
|
||||||
|
apt-get -y install pylint python3-pylint-common
|
||||||
|
- name: "prepare source (core)"
|
||||||
|
uses: calamares/actions/generic-checkout@v5
|
||||||
|
- name: "prepare source (extensions)"
|
||||||
|
shell: bash
|
||||||
|
run: git clone https://github.com/calamares/calamares-extensions.git ${SRCDIR}/calamares-extensions
|
||||||
|
- name: "install dependencies"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/deps-debian11.sh
|
||||||
|
- name: "build (core)"
|
||||||
|
shell: bash
|
||||||
|
run: ./ci/build.sh
|
||||||
|
- name: "build (extensions)"
|
||||||
|
shell: bash
|
||||||
|
run: BUILDDIR=/build/calamares-extensions SRCDIR=${SRCDIR}/calamares-extensions ./ci/build.sh
|
||||||
|
- name: "test (core)"
|
||||||
|
shell: bash
|
||||||
|
run: ctest --test-dir /build -V
|
18
.reuse/dep5
18
.reuse/dep5
@ -15,6 +15,10 @@ Files: man/calamares.8
|
|||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
Copyright: 2017 Jonathan Carter <jcarter@linux.com>
|
Copyright: 2017 Jonathan Carter <jcarter@linux.com>
|
||||||
|
|
||||||
|
Files: 3rdparty/kdsingleapplication/*
|
||||||
|
License: MIT
|
||||||
|
Copyright: Copyright (C) 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@ kdab.com
|
||||||
|
|
||||||
### BUILD ARTIFACTS / NOT SOURCE
|
### BUILD ARTIFACTS / NOT SOURCE
|
||||||
#
|
#
|
||||||
# QRC Files are basically build artifacts
|
# QRC Files are basically build artifacts
|
||||||
@ -50,6 +54,13 @@ Files: data/example-root/usr/share/zoneinfo/Zulu data/example-root/usr/share/zon
|
|||||||
License: CC0-1.0
|
License: CC0-1.0
|
||||||
Copyright: no
|
Copyright: no
|
||||||
|
|
||||||
|
# Test data
|
||||||
|
#
|
||||||
|
# These first files are mere lists of locale identifiers
|
||||||
|
Files: src/modules/locale/tests/locale-data-neon src/modules/locale/tests/locale-data-freebsd
|
||||||
|
License: CC0-1.0
|
||||||
|
Copyright: no
|
||||||
|
|
||||||
### TRANSLATIONS
|
### TRANSLATIONS
|
||||||
#
|
#
|
||||||
# .desktop files and template change only with translation
|
# .desktop files and template change only with translation
|
||||||
@ -81,10 +92,3 @@ Files: lang/python/*/LC_MESSAGES/python.po
|
|||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
Copyright: 2020 Calamares authors and translators
|
Copyright: 2020 Calamares authors and translators
|
||||||
|
|
||||||
Files: src/modules/dummypythonqt/lang/dummypythonqt.pot
|
|
||||||
License: GPL-3.0-or-later
|
|
||||||
Copyright: 2020 Calamares authors and translators
|
|
||||||
|
|
||||||
Files: src/modules/dummypythonqt/lang/*/LC_MESSAGES/dummypythonqt.po
|
|
||||||
License: GPL-3.0-or-later
|
|
||||||
Copyright: 2020 Calamares authors and translators
|
|
||||||
|
23
.travis.yml
Normal file
23
.travis.yml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# SPDX-FileCopyrightText: no
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
#
|
||||||
|
language: cpp
|
||||||
|
|
||||||
|
python:
|
||||||
|
- 3.5
|
||||||
|
|
||||||
|
sudo: required
|
||||||
|
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
irc:
|
||||||
|
- "chat.freenode.net#manjaro"
|
||||||
|
|
||||||
|
install:
|
||||||
|
- docker build -t calamares .
|
||||||
|
|
||||||
|
script:
|
||||||
|
- docker run -v $PWD:/src --tmpfs /build:rw,size=112M -e SRCDIR=/src -e BUILDDIR=/build calamares "/src/ci/travis.sh"
|
||||||
|
|
@ -2,21 +2,21 @@
|
|||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
[main]
|
[main]
|
||||||
host = https://www.transifex.com
|
host = https://app.transifex.com
|
||||||
|
|
||||||
[calamares.calamares]
|
[o:calamares:p:calamares:r:calamares]
|
||||||
file_filter = lang/calamares_<lang>.ts
|
file_filter = lang/calamares_<lang>.ts
|
||||||
source_file = lang/calamares_en.ts
|
source_file = lang/calamares_en.ts
|
||||||
source_lang = en
|
source_lang = en
|
||||||
type = QT
|
type = QT
|
||||||
|
|
||||||
[calamares.fdo]
|
[o:calamares:p:calamares:r:fdo]
|
||||||
file_filter = lang/desktop_<lang>.desktop
|
file_filter = lang/desktop_<lang>.desktop
|
||||||
source_file = calamares.desktop
|
source_file = calamares.desktop
|
||||||
source_lang = en
|
source_lang = en
|
||||||
type = DESKTOP
|
type = DESKTOP
|
||||||
|
|
||||||
[calamares.python]
|
[o:calamares:p:calamares:r:python]
|
||||||
file_filter = lang/python/<lang>/LC_MESSAGES/python.po
|
file_filter = lang/python/<lang>/LC_MESSAGES/python.po
|
||||||
source_file = lang/python.pot
|
source_file = lang/python.pot
|
||||||
source_lang = en
|
source_lang = en
|
||||||
|
26
3rdparty/kdsingleapplication/CMakeLists.txt
vendored
Normal file
26
3rdparty/kdsingleapplication/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
set(KDSINGLEAPPLICATION_STATIC ON)
|
||||||
|
|
||||||
|
set(KDSINGLEAPPLICATION_SRCS kdsingleapplication.cpp kdsingleapplication_localsocket.cpp)
|
||||||
|
|
||||||
|
set(KDSINGLEAPPLICATION_INSTALLABLE_INCLUDES kdsingleapplication.h kdsingleapplication_lib.h)
|
||||||
|
|
||||||
|
set(KDSINGLEAPPLICATION_NON_INSTALLABLE_INCLUDES kdsingleapplication_localsocket_p.h)
|
||||||
|
|
||||||
|
if(KDSINGLEAPPLICATION_STATIC)
|
||||||
|
add_library(kdsingleapplication STATIC ${KDSINGLEAPPLICATION_INSTALLABLE_INCLUDES} ${KDSINGLEAPPLICATION_SRCS})
|
||||||
|
target_compile_definitions(kdsingleapplication PUBLIC KDSINGLEAPPLICATION_STATIC_BUILD)
|
||||||
|
else()
|
||||||
|
add_library(kdsingleapplication SHARED ${KDSINGLEAPPLICATION_INSTALLABLE_INCLUDES} ${KDSINGLEAPPLICATION_SRCS})
|
||||||
|
target_compile_definitions(kdsingleapplication PRIVATE KDSINGLEAPPLICATION_SHARED_BUILD)
|
||||||
|
endif()
|
||||||
|
set_target_properties( kdsingleapplication PROPERTIES AUTOMOC TRUE )
|
||||||
|
|
||||||
|
set(KDSINGLEAPPLICATION_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/kdsingleapplication)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
kdsingleapplication
|
||||||
|
PUBLIC $<INSTALL_INTERFACE:${KDSINGLEAPPLICATION_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(kdsingleapplication ${qtname}::Core ${qtname}::Network)
|
22
3rdparty/kdsingleapplication/LICENSE.MIT.txt
vendored
Normal file
22
3rdparty/kdsingleapplication/LICENSE.MIT.txt
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||||
|
|
||||||
|
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, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
123
3rdparty/kdsingleapplication/kdsingleapplication.cpp
vendored
Normal file
123
3rdparty/kdsingleapplication/kdsingleapplication.cpp
vendored
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||||
|
|
||||||
|
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, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kdsingleapplication.h"
|
||||||
|
|
||||||
|
#include <QtCore/QCoreApplication>
|
||||||
|
#include <QtCore/QFileInfo>
|
||||||
|
|
||||||
|
// TODO: make this pluggable.
|
||||||
|
#include "kdsingleapplication_localsocket_p.h"
|
||||||
|
|
||||||
|
// Avoiding dragging in Qt private APIs for now, so this does not inherit
|
||||||
|
// from QObjectPrivate.
|
||||||
|
class KDSingleApplicationPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit KDSingleApplicationPrivate(const QString &name, KDSingleApplication *q);
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
QString name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isPrimaryInstance() const
|
||||||
|
{
|
||||||
|
return m_impl.isPrimaryInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sendMessage(const QByteArray &message, int timeout)
|
||||||
|
{
|
||||||
|
return m_impl.sendMessage(message, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DECLARE_PUBLIC(KDSingleApplication)
|
||||||
|
|
||||||
|
KDSingleApplication *q_ptr;
|
||||||
|
QString m_name;
|
||||||
|
|
||||||
|
KDSingleApplicationLocalSocket m_impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
KDSingleApplicationPrivate::KDSingleApplicationPrivate(const QString &name, KDSingleApplication *q)
|
||||||
|
: q_ptr(q)
|
||||||
|
, m_name(name)
|
||||||
|
, m_impl(name)
|
||||||
|
{
|
||||||
|
if (Q_UNLIKELY(name.isEmpty()))
|
||||||
|
qFatal("KDSingleApplication requires a non-empty application name");
|
||||||
|
|
||||||
|
if (isPrimaryInstance()) {
|
||||||
|
QObject::connect(&m_impl, &KDSingleApplicationLocalSocket::messageReceived,
|
||||||
|
q, &KDSingleApplication::messageReceived);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString extractExecutableName(const QString &applicationFilePath)
|
||||||
|
{
|
||||||
|
return QFileInfo(applicationFilePath).fileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
KDSingleApplication::KDSingleApplication(QObject *parent)
|
||||||
|
: KDSingleApplication(extractExecutableName(QCoreApplication::applicationFilePath()), parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
KDSingleApplication::KDSingleApplication(const QString &name, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, d_ptr(new KDSingleApplicationPrivate(name, this))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KDSingleApplication::name() const
|
||||||
|
{
|
||||||
|
Q_D(const KDSingleApplication);
|
||||||
|
return d->name();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDSingleApplication::isPrimaryInstance() const
|
||||||
|
{
|
||||||
|
Q_D(const KDSingleApplication);
|
||||||
|
return d->isPrimaryInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDSingleApplication::sendMessage(const QByteArray &message)
|
||||||
|
{
|
||||||
|
return sendMessageWithTimeout(message, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDSingleApplication::sendMessageWithTimeout(const QByteArray &message, int timeout)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!isPrimaryInstance());
|
||||||
|
|
||||||
|
Q_D(KDSingleApplication);
|
||||||
|
return d->sendMessage(message, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KDSingleApplication::~KDSingleApplication() = default;
|
||||||
|
|
62
3rdparty/kdsingleapplication/kdsingleapplication.h
vendored
Normal file
62
3rdparty/kdsingleapplication/kdsingleapplication.h
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||||
|
|
||||||
|
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, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
#ifndef KDSINGLEAPPLICATION_H
|
||||||
|
#define KDSINGLEAPPLICATION_H
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "kdsingleapplication_lib.h"
|
||||||
|
|
||||||
|
class KDSingleApplicationPrivate;
|
||||||
|
|
||||||
|
class KDSINGLEAPPLICATION_EXPORT KDSingleApplication : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString name READ name CONSTANT)
|
||||||
|
Q_PROPERTY(bool isPrimaryInstance READ isPrimaryInstance CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit KDSingleApplication(QObject *parent = nullptr);
|
||||||
|
explicit KDSingleApplication(const QString &name, QObject *parent = nullptr);
|
||||||
|
~KDSingleApplication();
|
||||||
|
|
||||||
|
QString name() const;
|
||||||
|
bool isPrimaryInstance() const;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
// avoid default arguments and overloads, as they don't mix with connections
|
||||||
|
bool sendMessage(const QByteArray &message);
|
||||||
|
bool sendMessageWithTimeout(const QByteArray &message, int timeout);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void messageReceived(const QByteArray &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DECLARE_PRIVATE(KDSingleApplication)
|
||||||
|
std::unique_ptr<KDSingleApplicationPrivate> d_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KDSINGLEAPPLICATION_H
|
37
3rdparty/kdsingleapplication/kdsingleapplication_lib.h
vendored
Normal file
37
3rdparty/kdsingleapplication/kdsingleapplication_lib.h
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||||
|
|
||||||
|
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, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
#ifndef KDSINGLEAPPLICATION_LIB_H
|
||||||
|
#define KDSINGLEAPPLICATION_LIB_H
|
||||||
|
|
||||||
|
#include <QtCore/QtGlobal>
|
||||||
|
|
||||||
|
#if defined(KDSINGLEAPPLICATION_STATIC_BUILD)
|
||||||
|
#define KDSINGLEAPPLICATION_EXPORT
|
||||||
|
#elif defined(KDSINGLEAPPLICATION_SHARED_BUILD)
|
||||||
|
#define KDSINGLEAPPLICATION_EXPORT Q_DECL_EXPORT
|
||||||
|
#else
|
||||||
|
#define KDSINGLEAPPLICATION_EXPORT Q_DECL_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // KDSINGLEAPPLICATION_LIB_H
|
304
3rdparty/kdsingleapplication/kdsingleapplication_localsocket.cpp
vendored
Normal file
304
3rdparty/kdsingleapplication/kdsingleapplication_localsocket.cpp
vendored
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||||
|
|
||||||
|
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, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kdsingleapplication_localsocket_p.h"
|
||||||
|
|
||||||
|
#include <QtCore/QDir>
|
||||||
|
#include <QtCore/QDeadlineTimer>
|
||||||
|
#include <QtCore/QTimer>
|
||||||
|
#include <QtCore/QLockFile>
|
||||||
|
#include <QtCore/QDataStream>
|
||||||
|
|
||||||
|
#include <QtCore/QtDebug>
|
||||||
|
#include <QtCore/QLoggingCategory>
|
||||||
|
|
||||||
|
#include <QtNetwork/QLocalServer>
|
||||||
|
#include <QtNetwork/QLocalSocket>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#if defined(Q_OS_UNIX)
|
||||||
|
// for ::getuid()
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
#include <qt_windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const auto LOCALSOCKET_CONNECTION_TIMEOUT = std::chrono::seconds(5);
|
||||||
|
static const char LOCALSOCKET_PROTOCOL_VERSION = 2;
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(kdsaLocalSocket, "kdsingleapplication.localsocket", QtWarningMsg);
|
||||||
|
|
||||||
|
KDSingleApplicationLocalSocket::KDSingleApplicationLocalSocket(const QString &name, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_UNIX)
|
||||||
|
m_socketName = QStringLiteral("kdsingleapp-%1-%2-%3")
|
||||||
|
.arg(::getuid())
|
||||||
|
.arg(qEnvironmentVariable("XDG_SESSION_ID"), name);
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
// I'm not sure of a "global session identifier" on Windows; are
|
||||||
|
// multiple logins from the same user a possibility? For now, following this:
|
||||||
|
// https://docs.microsoft.com/en-us/windows/desktop/devnotes/getting-the-session-id-of-the-current-process
|
||||||
|
|
||||||
|
DWORD sessionId;
|
||||||
|
BOOL haveSessionId = ProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
|
||||||
|
|
||||||
|
m_socketName = QString::fromUtf8("kdsingleapp-%1-%2")
|
||||||
|
.arg(haveSessionId ? sessionId : 0)
|
||||||
|
.arg(name);
|
||||||
|
#else
|
||||||
|
#error "KDSingleApplication has not been ported to this platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const QString lockFilePath =
|
||||||
|
QDir::tempPath() + QLatin1Char('/') + m_socketName + QLatin1String(".lock");
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Socket name is" << m_socketName;
|
||||||
|
qCDebug(kdsaLocalSocket) << "Lock file path is" << lockFilePath;
|
||||||
|
|
||||||
|
std::unique_ptr<QLockFile> lockFile(new QLockFile(lockFilePath));
|
||||||
|
lockFile->setStaleLockTime(0);
|
||||||
|
|
||||||
|
if (!lockFile->tryLock()) {
|
||||||
|
// someone else has the lock => we're secondary
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<QLocalServer> server = std::make_unique<QLocalServer>();
|
||||||
|
if (!server->listen(m_socketName)) {
|
||||||
|
// maybe the primary crashed, leaving a stale socket; delete it and try again
|
||||||
|
QLocalServer::removeServer(m_socketName);
|
||||||
|
if (!server->listen(m_socketName)) {
|
||||||
|
// TODO: better error handling.
|
||||||
|
qWarning("KDSingleApplication: unable to make the primary instance listen on %ls: %ls",
|
||||||
|
qUtf16Printable(m_socketName),
|
||||||
|
qUtf16Printable(server->errorString()));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(server.get(), &QLocalServer::newConnection,
|
||||||
|
this, &KDSingleApplicationLocalSocket::handleNewConnection);
|
||||||
|
|
||||||
|
m_lockFile = std::move(lockFile);
|
||||||
|
m_localServer = std::move(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
KDSingleApplicationLocalSocket::~KDSingleApplicationLocalSocket() = default;
|
||||||
|
|
||||||
|
bool KDSingleApplicationLocalSocket::isPrimaryInstance() const
|
||||||
|
{
|
||||||
|
return m_localServer != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDSingleApplicationLocalSocket::sendMessage(const QByteArray &message, int timeout)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!isPrimaryInstance());
|
||||||
|
QLocalSocket socket;
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Preparing to send message" << message << "with timeout" << timeout;
|
||||||
|
|
||||||
|
QDeadlineTimer deadline(timeout);
|
||||||
|
|
||||||
|
// There is an inherent race here with the setup of the server side.
|
||||||
|
// Even if the socket lock is held by the server, the server may not
|
||||||
|
// be listening yet. So this connection may fail; keep retrying
|
||||||
|
// until we hit the timeout.
|
||||||
|
do {
|
||||||
|
socket.connectToServer(m_socketName);
|
||||||
|
if (socket.waitForConnected(deadline.remainingTime()))
|
||||||
|
break;
|
||||||
|
} while (!deadline.hasExpired());
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Socket state:" << socket.state() << "Timer remaining" << deadline.remainingTime() << "Expired?" << deadline.hasExpired();
|
||||||
|
|
||||||
|
if (deadline.hasExpired())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
socket.write(&LOCALSOCKET_PROTOCOL_VERSION, 1);
|
||||||
|
|
||||||
|
{
|
||||||
|
QByteArray encodedMessage;
|
||||||
|
QDataStream ds(&encodedMessage, QIODevice::WriteOnly);
|
||||||
|
ds << message;
|
||||||
|
socket.write(encodedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Wrote message in the socket" << "Timer remaining" << deadline.remainingTime() << "Expired?" << deadline.hasExpired();
|
||||||
|
|
||||||
|
// There is no acknowledgement mechanism here.
|
||||||
|
// Should there be one?
|
||||||
|
|
||||||
|
while (socket.bytesToWrite() > 0) {
|
||||||
|
if (!socket.waitForBytesWritten(deadline.remainingTime()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Bytes written, now disconnecting" << "Timer remaining" << deadline.remainingTime() << "Expired?" << deadline.hasExpired();
|
||||||
|
|
||||||
|
socket.disconnectFromServer();
|
||||||
|
|
||||||
|
if (socket.state() == QLocalSocket::UnconnectedState)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!socket.waitForDisconnected(deadline.remainingTime()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Disconnected -- success!";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDSingleApplicationLocalSocket::handleNewConnection()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_localServer);
|
||||||
|
|
||||||
|
QLocalSocket *socket = m_localServer->nextPendingConnection();
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Got new connection on" << m_socketName << "state" << socket->state();
|
||||||
|
|
||||||
|
Connection c(socket);
|
||||||
|
|
||||||
|
c.readDataConnection = QObjectConnectionHolder(
|
||||||
|
connect(c.socket.get(), &QLocalSocket::readyRead,
|
||||||
|
this, &KDSingleApplicationLocalSocket::readDataFromSecondary));
|
||||||
|
|
||||||
|
c.secondaryDisconnectedConnection = QObjectConnectionHolder(
|
||||||
|
connect(c.socket.get(), &QLocalSocket::disconnected,
|
||||||
|
this, &KDSingleApplicationLocalSocket::secondaryDisconnected));
|
||||||
|
|
||||||
|
c.abortConnection = QObjectConnectionHolder(
|
||||||
|
connect(c.timeoutTimer.get(), &QTimer::timeout,
|
||||||
|
this, &KDSingleApplicationLocalSocket::abortConnectionToSecondary));
|
||||||
|
|
||||||
|
m_clients.push_back(std::move(c));
|
||||||
|
|
||||||
|
// Note that by the time we get here, the socket could've already been closed,
|
||||||
|
// and no signals emitted (hello, Windows!). Read what's already in the socket.
|
||||||
|
if (readDataFromSecondarySocket(socket))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (socket->state() == QLocalSocket::UnconnectedState)
|
||||||
|
secondarySocketDisconnected(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
static auto findConnectionBySocket(Container &container, QLocalSocket *socket)
|
||||||
|
{
|
||||||
|
auto i = std::find_if(container.begin(),
|
||||||
|
container.end(),
|
||||||
|
[socket](const auto &c) { return c.socket.get() == socket; });
|
||||||
|
Q_ASSERT(i != container.end());
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
static auto findConnectionByTimer(Container &container, QTimer *timer)
|
||||||
|
{
|
||||||
|
auto i = std::find_if(container.begin(),
|
||||||
|
container.end(),
|
||||||
|
[timer](const auto &c) { return c.timeoutTimer.get() == timer; });
|
||||||
|
Q_ASSERT(i != container.end());
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDSingleApplicationLocalSocket::readDataFromSecondary()
|
||||||
|
{
|
||||||
|
QLocalSocket *socket = static_cast<QLocalSocket *>(sender());
|
||||||
|
readDataFromSecondarySocket(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDSingleApplicationLocalSocket::readDataFromSecondarySocket(QLocalSocket *socket)
|
||||||
|
{
|
||||||
|
auto i = findConnectionBySocket(m_clients, socket);
|
||||||
|
Connection &c = *i;
|
||||||
|
c.readData.append(socket->readAll());
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Got more data from a secondary. Data read so far:" << c.readData;
|
||||||
|
|
||||||
|
const QByteArray &data = c.readData;
|
||||||
|
|
||||||
|
if (data.size() >= 1) {
|
||||||
|
if (data[0] != LOCALSOCKET_PROTOCOL_VERSION) {
|
||||||
|
qCDebug(kdsaLocalSocket) << "Got an invalid protocol version";
|
||||||
|
m_clients.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream ds(data);
|
||||||
|
ds.skipRawData(1);
|
||||||
|
|
||||||
|
ds.startTransaction();
|
||||||
|
QByteArray message;
|
||||||
|
ds >> message;
|
||||||
|
|
||||||
|
if (ds.commitTransaction()) {
|
||||||
|
qCDebug(kdsaLocalSocket) << "Got a complete message:" << message;
|
||||||
|
Q_EMIT messageReceived(message);
|
||||||
|
m_clients.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDSingleApplicationLocalSocket::secondaryDisconnected()
|
||||||
|
{
|
||||||
|
QLocalSocket *socket = static_cast<QLocalSocket *>(sender());
|
||||||
|
secondarySocketDisconnected(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDSingleApplicationLocalSocket::secondarySocketDisconnected(QLocalSocket *socket)
|
||||||
|
{
|
||||||
|
auto i = findConnectionBySocket(m_clients, socket);
|
||||||
|
Connection c = std::move(*i);
|
||||||
|
m_clients.erase(i);
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Secondary disconnected. Data read:" << c.readData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDSingleApplicationLocalSocket::abortConnectionToSecondary()
|
||||||
|
{
|
||||||
|
QTimer *timer = static_cast<QTimer *>(sender());
|
||||||
|
|
||||||
|
auto i = findConnectionByTimer(m_clients, timer);
|
||||||
|
Connection c = std::move(*i);
|
||||||
|
m_clients.erase(i);
|
||||||
|
|
||||||
|
qCDebug(kdsaLocalSocket) << "Secondary timed out. Data read:" << c.readData;
|
||||||
|
}
|
||||||
|
|
||||||
|
KDSingleApplicationLocalSocket::Connection::Connection(QLocalSocket *socket)
|
||||||
|
: socket(socket)
|
||||||
|
, timeoutTimer(new QTimer)
|
||||||
|
{
|
||||||
|
timeoutTimer->start(LOCALSOCKET_CONNECTION_TIMEOUT);
|
||||||
|
}
|
133
3rdparty/kdsingleapplication/kdsingleapplication_localsocket_p.h
vendored
Normal file
133
3rdparty/kdsingleapplication/kdsingleapplication_localsocket_p.h
vendored
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||||
|
|
||||||
|
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, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KDSINGLEAPPLICATION_LOCALSOCKET_P_H
|
||||||
|
#define KDSINGLEAPPLICATION_LOCALSOCKET_P_H
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
#include <QtCore/QByteArray>
|
||||||
|
#include <QtCore/QString>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QLockFile;
|
||||||
|
class QLocalServer;
|
||||||
|
class QLocalSocket;
|
||||||
|
class QTimer;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct QObjectDeleteLater
|
||||||
|
{
|
||||||
|
void operator()(QObject *o) { o->deleteLater(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class QObjectConnectionHolder
|
||||||
|
{
|
||||||
|
Q_DISABLE_COPY(QObjectConnectionHolder)
|
||||||
|
QMetaObject::Connection c;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QObjectConnectionHolder() {}
|
||||||
|
|
||||||
|
explicit QObjectConnectionHolder(QMetaObject::Connection c)
|
||||||
|
: c(std::move(c))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~QObjectConnectionHolder()
|
||||||
|
{
|
||||||
|
QObject::disconnect(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
QObjectConnectionHolder(QObjectConnectionHolder &&other) noexcept
|
||||||
|
: c(std::exchange(other.c, {}))
|
||||||
|
{}
|
||||||
|
|
||||||
|
QObjectConnectionHolder &operator=(QObjectConnectionHolder &&other) noexcept
|
||||||
|
{
|
||||||
|
QObjectConnectionHolder moved(std::move(other));
|
||||||
|
swap(moved);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(QObjectConnectionHolder &other) noexcept
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(c, other.c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class KDSingleApplicationLocalSocket : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit KDSingleApplicationLocalSocket(const QString &name,
|
||||||
|
QObject *parent = nullptr);
|
||||||
|
~KDSingleApplicationLocalSocket();
|
||||||
|
|
||||||
|
bool isPrimaryInstance() const;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
bool sendMessage(const QByteArray &message, int timeout);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void messageReceived(const QByteArray &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handleNewConnection();
|
||||||
|
void readDataFromSecondary();
|
||||||
|
bool readDataFromSecondarySocket(QLocalSocket *socket);
|
||||||
|
void secondaryDisconnected();
|
||||||
|
void secondarySocketDisconnected(QLocalSocket *socket);
|
||||||
|
void abortConnectionToSecondary();
|
||||||
|
|
||||||
|
QString m_socketName;
|
||||||
|
|
||||||
|
std::unique_ptr<QLockFile> m_lockFile; // protects m_localServer
|
||||||
|
std::unique_ptr<QLocalServer> m_localServer;
|
||||||
|
|
||||||
|
struct Connection {
|
||||||
|
explicit Connection(QLocalSocket *s);
|
||||||
|
|
||||||
|
std::unique_ptr<QLocalSocket, QObjectDeleteLater> socket;
|
||||||
|
std::unique_ptr<QTimer, QObjectDeleteLater> timeoutTimer;
|
||||||
|
QByteArray readData;
|
||||||
|
|
||||||
|
// socket/timeoutTimer are deleted via deleteLater (as we delete them
|
||||||
|
// in slots connected to their signals). Before the deleteLater is acted upon,
|
||||||
|
// they may emit further signals, triggering logic that it's not supposed
|
||||||
|
// to be triggered (as the Connection has already been destroyed).
|
||||||
|
// Use this Holder to break the connections.
|
||||||
|
QObjectConnectionHolder readDataConnection;
|
||||||
|
QObjectConnectionHolder secondaryDisconnectedConnection;
|
||||||
|
QObjectConnectionHolder abortConnection;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Connection> m_clients;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KDSINGLEAPPLICATION_LOCALSOCKET_P_H
|
20
3rdparty/kdsingleapplication/src.pro
vendored
Normal file
20
3rdparty/kdsingleapplication/src.pro
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
include(../common.pri)
|
||||||
|
|
||||||
|
TEMPLATE = lib
|
||||||
|
TARGET = kdsingleapplication
|
||||||
|
QT = core network
|
||||||
|
CONFIG += static
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
kdsingleapplication.cpp \
|
||||||
|
kdsingleapplication_localsocket.cpp \
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
kdsingleapplication.h \
|
||||||
|
kdsingleapplication_lib.h \
|
||||||
|
kdsingleapplication_localsocket_p.h \
|
||||||
|
|
||||||
|
DEFINES += \
|
||||||
|
KDSINGLEAPPLICATION_BUILD
|
||||||
|
|
||||||
|
win32:LIBS += -lkernel32
|
488
3rdparty/kdsingleapplicationguard/LICENSE.LGPL.txt
vendored
488
3rdparty/kdsingleapplicationguard/LICENSE.LGPL.txt
vendored
@ -1,488 +0,0 @@
|
|||||||
|
|
||||||
The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
|
|
||||||
You may use, distribute and copy the KD Tools Library under the terms of
|
|
||||||
GNU Library General Public License version 2, which is displayed below.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
[This is the first released version of the library GPL. It is
|
|
||||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
Licenses are intended to guarantee your freedom to share and change
|
|
||||||
free software--to make sure the software is free for all its users.
|
|
||||||
|
|
||||||
This license, the Library General Public License, applies to some
|
|
||||||
specially designated Free Software Foundation software, and to any
|
|
||||||
other libraries whose authors decide to use it. You can use it for
|
|
||||||
your libraries, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if
|
|
||||||
you distribute copies of the library, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of the library, whether gratis
|
|
||||||
or for a fee, you must give the recipients all the rights that we gave
|
|
||||||
you. You must make sure that they, too, receive or can get the source
|
|
||||||
code. If you link a program with the library, you must provide
|
|
||||||
complete object files to the recipients so that they can relink them
|
|
||||||
with the library, after making changes to the library and recompiling
|
|
||||||
it. And you must show them these terms so they know their rights.
|
|
||||||
|
|
||||||
Our method of protecting your rights has two steps: (1) copyright
|
|
||||||
the library, and (2) offer you this license which gives you legal
|
|
||||||
permission to copy, distribute and/or modify the library.
|
|
||||||
|
|
||||||
Also, for each distributor's protection, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
library. If the library is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original
|
|
||||||
version, so that any problems introduced by others will not reflect on
|
|
||||||
the original authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that companies distributing free
|
|
||||||
software will individually obtain patent licenses, thus in effect
|
|
||||||
transforming the program into proprietary software. To prevent this,
|
|
||||||
we have made it clear that any patent must be licensed for everyone's
|
|
||||||
free use or not licensed at all.
|
|
||||||
|
|
||||||
Most GNU software, including some libraries, is covered by the ordinary
|
|
||||||
GNU General Public License, which was designed for utility programs. This
|
|
||||||
license, the GNU Library General Public License, applies to certain
|
|
||||||
designated libraries. This license is quite different from the ordinary
|
|
||||||
one; be sure to read it in full, and don't assume that anything in it is
|
|
||||||
the same as in the ordinary license.
|
|
||||||
|
|
||||||
The reason we have a separate public license for some libraries is that
|
|
||||||
they blur the distinction we usually make between modifying or adding to a
|
|
||||||
program and simply using it. Linking a program with a library, without
|
|
||||||
changing the library, is in some sense simply using the library, and is
|
|
||||||
analogous to running a utility program or application program. However, in
|
|
||||||
a textual and legal sense, the linked executable is a combined work, a
|
|
||||||
derivative of the original library, and the ordinary General Public License
|
|
||||||
treats it as such.
|
|
||||||
|
|
||||||
Because of this blurred distinction, using the ordinary General
|
|
||||||
Public License for libraries did not effectively promote software
|
|
||||||
sharing, because most developers did not use the libraries. We
|
|
||||||
concluded that weaker conditions might promote sharing better.
|
|
||||||
|
|
||||||
However, unrestricted linking of non-free programs would deprive the
|
|
||||||
users of those programs of all benefit from the free status of the
|
|
||||||
libraries themselves. This Library General Public License is intended to
|
|
||||||
permit developers of non-free programs to use free libraries, while
|
|
||||||
preserving your freedom as a user of such programs to change the free
|
|
||||||
libraries that are incorporated in them. (We have not seen how to achieve
|
|
||||||
this as regards changes in header files, but we have achieved it as regards
|
|
||||||
changes in the actual functions of the Library.) The hope is that this
|
|
||||||
will lead to faster development of free libraries.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow. Pay close attention to the difference between a
|
|
||||||
"work based on the library" and a "work that uses the library". The
|
|
||||||
former contains code derived from the library, while the latter only
|
|
||||||
works together with the library.
|
|
||||||
|
|
||||||
Note that it is possible for a library to be covered by the ordinary
|
|
||||||
General Public License rather than by this special one.
|
|
||||||
|
|
||||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License Agreement applies to any software library which
|
|
||||||
contains a notice placed by the copyright holder or other authorized
|
|
||||||
party saying it may be distributed under the terms of this Library
|
|
||||||
General Public License (also called "this License"). Each licensee is
|
|
||||||
addressed as "you".
|
|
||||||
|
|
||||||
A "library" means a collection of software functions and/or data
|
|
||||||
prepared so as to be conveniently linked with application programs
|
|
||||||
(which use some of those functions and data) to form executables.
|
|
||||||
|
|
||||||
The "Library", below, refers to any such software library or work
|
|
||||||
which has been distributed under these terms. A "work based on the
|
|
||||||
Library" means either the Library or any derivative work under
|
|
||||||
copyright law: that is to say, a work containing the Library or a
|
|
||||||
portion of it, either verbatim or with modifications and/or translated
|
|
||||||
straightforwardly into another language. (Hereinafter, translation is
|
|
||||||
included without limitation in the term "modification".)
|
|
||||||
|
|
||||||
"Source code" for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For a library, complete source code means
|
|
||||||
all the source code for all modules it contains, plus any associated
|
|
||||||
interface definition files, plus the scripts used to control compilation
|
|
||||||
and installation of the library.
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running a program using the Library is not restricted, and output from
|
|
||||||
such a program is covered only if its contents constitute a work based
|
|
||||||
on the Library (independent of the use of the Library in a tool for
|
|
||||||
writing it). Whether that is true depends on what the Library does
|
|
||||||
and what the program that uses the Library does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Library's
|
|
||||||
complete source code as you receive it, in any medium, provided that
|
|
||||||
you conspicuously and appropriately publish on each copy an
|
|
||||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
|
||||||
all the notices that refer to this License and to the absence of any
|
|
||||||
warranty; and distribute a copy of this License along with the
|
|
||||||
Library.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy,
|
|
||||||
and you may at your option offer warranty protection in exchange for a
|
|
||||||
fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Library or any portion
|
|
||||||
of it, thus forming a work based on the Library, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The modified work must itself be a software library.
|
|
||||||
|
|
||||||
b) You must cause the files modified to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
c) You must cause the whole of the work to be licensed at no
|
|
||||||
charge to all third parties under the terms of this License.
|
|
||||||
|
|
||||||
d) If a facility in the modified Library refers to a function or a
|
|
||||||
table of data to be supplied by an application program that uses
|
|
||||||
the facility, other than as an argument passed when the facility
|
|
||||||
is invoked, then you must make a good faith effort to ensure that,
|
|
||||||
in the event an application does not supply such function or
|
|
||||||
table, the facility still operates, and performs whatever part of
|
|
||||||
its purpose remains meaningful.
|
|
||||||
|
|
||||||
(For example, a function in a library to compute square roots has
|
|
||||||
a purpose that is entirely well-defined independent of the
|
|
||||||
application. Therefore, Subsection 2d requires that any
|
|
||||||
application-supplied function or table used by this function must
|
|
||||||
be optional: if the application does not supply it, the square
|
|
||||||
root function must still compute square roots.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Library,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Library, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote
|
|
||||||
it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Library.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Library
|
|
||||||
with the Library (or with a work based on the Library) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
|
||||||
License instead of this License to a given copy of the Library. To do
|
|
||||||
this, you must alter all the notices that refer to this License, so
|
|
||||||
that they refer to the ordinary GNU General Public License, version 2,
|
|
||||||
instead of to this License. (If a newer version than version 2 of the
|
|
||||||
ordinary GNU General Public License has appeared, then you can specify
|
|
||||||
that version instead if you wish.) Do not make any other change in
|
|
||||||
these notices.
|
|
||||||
|
|
||||||
Once this change is made in a given copy, it is irreversible for
|
|
||||||
that copy, so the ordinary GNU General Public License applies to all
|
|
||||||
subsequent copies and derivative works made from that copy.
|
|
||||||
|
|
||||||
This option is useful when you wish to copy part of the code of
|
|
||||||
the Library into a program that is not a library.
|
|
||||||
|
|
||||||
4. You may copy and distribute the Library (or a portion or
|
|
||||||
derivative of it, under Section 2) in object code or executable form
|
|
||||||
under the terms of Sections 1 and 2 above provided that you accompany
|
|
||||||
it with the complete corresponding machine-readable source code, which
|
|
||||||
must be distributed under the terms of Sections 1 and 2 above on a
|
|
||||||
medium customarily used for software interchange.
|
|
||||||
|
|
||||||
If distribution of object code is made by offering access to copy
|
|
||||||
from a designated place, then offering equivalent access to copy the
|
|
||||||
source code from the same place satisfies the requirement to
|
|
||||||
distribute the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
5. A program that contains no derivative of any portion of the
|
|
||||||
Library, but is designed to work with the Library by being compiled or
|
|
||||||
linked with it, is called a "work that uses the Library". Such a
|
|
||||||
work, in isolation, is not a derivative work of the Library, and
|
|
||||||
therefore falls outside the scope of this License.
|
|
||||||
|
|
||||||
However, linking a "work that uses the Library" with the Library
|
|
||||||
creates an executable that is a derivative of the Library (because it
|
|
||||||
contains portions of the Library), rather than a "work that uses the
|
|
||||||
library". The executable is therefore covered by this License.
|
|
||||||
Section 6 states terms for distribution of such executables.
|
|
||||||
|
|
||||||
When a "work that uses the Library" uses material from a header file
|
|
||||||
that is part of the Library, the object code for the work may be a
|
|
||||||
derivative work of the Library even though the source code is not.
|
|
||||||
Whether this is true is especially significant if the work can be
|
|
||||||
linked without the Library, or if the work is itself a library. The
|
|
||||||
threshold for this to be true is not precisely defined by law.
|
|
||||||
|
|
||||||
If such an object file uses only numerical parameters, data
|
|
||||||
structure layouts and accessors, and small macros and small inline
|
|
||||||
functions (ten lines or less in length), then the use of the object
|
|
||||||
file is unrestricted, regardless of whether it is legally a derivative
|
|
||||||
work. (Executables containing this object code plus portions of the
|
|
||||||
Library will still fall under Section 6.)
|
|
||||||
|
|
||||||
Otherwise, if the work is a derivative of the Library, you may
|
|
||||||
distribute the object code for the work under the terms of Section 6.
|
|
||||||
Any executables containing that work also fall under Section 6,
|
|
||||||
whether or not they are linked directly with the Library itself.
|
|
||||||
|
|
||||||
6. As an exception to the Sections above, you may also compile or
|
|
||||||
link a "work that uses the Library" with the Library to produce a
|
|
||||||
work containing portions of the Library, and distribute that work
|
|
||||||
under terms of your choice, provided that the terms permit
|
|
||||||
modification of the work for the customer's own use and reverse
|
|
||||||
engineering for debugging such modifications.
|
|
||||||
|
|
||||||
You must give prominent notice with each copy of the work that the
|
|
||||||
Library is used in it and that the Library and its use are covered by
|
|
||||||
this License. You must supply a copy of this License. If the work
|
|
||||||
during execution displays copyright notices, you must include the
|
|
||||||
copyright notice for the Library among them, as well as a reference
|
|
||||||
directing the user to the copy of this License. Also, you must do one
|
|
||||||
of these things:
|
|
||||||
|
|
||||||
a) Accompany the work with the complete corresponding
|
|
||||||
machine-readable source code for the Library including whatever
|
|
||||||
changes were used in the work (which must be distributed under
|
|
||||||
Sections 1 and 2 above); and, if the work is an executable linked
|
|
||||||
with the Library, with the complete machine-readable "work that
|
|
||||||
uses the Library", as object code and/or source code, so that the
|
|
||||||
user can modify the Library and then relink to produce a modified
|
|
||||||
executable containing the modified Library. (It is understood
|
|
||||||
that the user who changes the contents of definitions files in the
|
|
||||||
Library will not necessarily be able to recompile the application
|
|
||||||
to use the modified definitions.)
|
|
||||||
|
|
||||||
b) Accompany the work with a written offer, valid for at
|
|
||||||
least three years, to give the same user the materials
|
|
||||||
specified in Subsection 6a, above, for a charge no more
|
|
||||||
than the cost of performing this distribution.
|
|
||||||
|
|
||||||
c) If distribution of the work is made by offering access to copy
|
|
||||||
from a designated place, offer equivalent access to copy the above
|
|
||||||
specified materials from the same place.
|
|
||||||
|
|
||||||
d) Verify that the user has already received a copy of these
|
|
||||||
materials or that you have already sent this user a copy.
|
|
||||||
|
|
||||||
For an executable, the required form of the "work that uses the
|
|
||||||
Library" must include any data and utility programs needed for
|
|
||||||
reproducing the executable from it. However, as a special exception,
|
|
||||||
the source code distributed need not include anything that is normally
|
|
||||||
distributed (in either source or binary form) with the major
|
|
||||||
components (compiler, kernel, and so on) of the operating system on
|
|
||||||
which the executable runs, unless that component itself accompanies
|
|
||||||
the executable.
|
|
||||||
|
|
||||||
It may happen that this requirement contradicts the license
|
|
||||||
restrictions of other proprietary libraries that do not normally
|
|
||||||
accompany the operating system. Such a contradiction means you cannot
|
|
||||||
use both them and the Library together in an executable that you
|
|
||||||
distribute.
|
|
||||||
|
|
||||||
7. You may place library facilities that are a work based on the
|
|
||||||
Library side-by-side in a single library together with other library
|
|
||||||
facilities not covered by this License, and distribute such a combined
|
|
||||||
library, provided that the separate distribution of the work based on
|
|
||||||
the Library and of the other library facilities is otherwise
|
|
||||||
permitted, and provided that you do these two things:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work
|
|
||||||
based on the Library, uncombined with any other library
|
|
||||||
facilities. This must be distributed under the terms of the
|
|
||||||
Sections above.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library of the fact
|
|
||||||
that part of it is a work based on the Library, and explaining
|
|
||||||
where to find the accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
8. You may not copy, modify, sublicense, link with, or distribute
|
|
||||||
the Library except as expressly provided under this License. Any
|
|
||||||
attempt otherwise to copy, modify, sublicense, link with, or
|
|
||||||
distribute the Library is void, and will automatically terminate your
|
|
||||||
rights under this License. However, parties who have received copies,
|
|
||||||
or rights, from you under this License will not have their licenses
|
|
||||||
terminated so long as such parties remain in full compliance.
|
|
||||||
|
|
||||||
9. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Library or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Library (or any work based on the
|
|
||||||
Library), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Library or works based on it.
|
|
||||||
|
|
||||||
10. Each time you redistribute the Library (or any work based on the
|
|
||||||
Library), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute, link with or modify the Library
|
|
||||||
subject to these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
11. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Library at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Library by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Library.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under any
|
|
||||||
particular circumstance, the balance of the section is intended to apply,
|
|
||||||
and the section as a whole is intended to apply in other circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
12. If the distribution and/or use of the Library is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Library under this License may add
|
|
||||||
an explicit geographical distribution limitation excluding those countries,
|
|
||||||
so that distribution is permitted only in or among countries not thus
|
|
||||||
excluded. In such case, this License incorporates the limitation as if
|
|
||||||
written in the body of this License.
|
|
||||||
|
|
||||||
13. The Free Software Foundation may publish revised and/or new
|
|
||||||
versions of the Library General Public License from time to time.
|
|
||||||
Such new versions will be similar in spirit to the present version,
|
|
||||||
but may differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Library
|
|
||||||
specifies a version number of this License which applies to it and
|
|
||||||
"any later version", you have the option of following the terms and
|
|
||||||
conditions either of that version or of any later version published by
|
|
||||||
the Free Software Foundation. If the Library does not specify a
|
|
||||||
license version number, you may choose any version ever published by
|
|
||||||
the Free Software Foundation.
|
|
||||||
|
|
||||||
14. If you wish to incorporate parts of the Library into other free
|
|
||||||
programs whose distribution conditions are incompatible with these,
|
|
||||||
write to the author to ask for permission. For software which is
|
|
||||||
copyrighted by the Free Software Foundation, write to the Free
|
|
||||||
Software Foundation; we sometimes make exceptions for this. Our
|
|
||||||
decision will be guided by the two goals of preserving the free status
|
|
||||||
of all derivatives of our free software and of promoting the sharing
|
|
||||||
and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
|
||||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
|
||||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
|
||||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
|
||||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
|
||||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
|
||||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
|
||||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
|
||||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
|
||||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
|
||||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
|
||||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
|
||||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
|
||||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
|
||||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|
||||||
DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Libraries
|
|
||||||
|
|
||||||
If you develop a new library, and you want it to be of the greatest
|
|
||||||
possible use to the public, we recommend making it free software that
|
|
||||||
everyone can redistribute and change. You can do so by permitting
|
|
||||||
redistribution under these terms (or, alternatively, under the terms of the
|
|
||||||
ordinary General Public License).
|
|
||||||
|
|
||||||
To apply these terms, attach the following notices to the library. It is
|
|
||||||
safest to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least the
|
|
||||||
"copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the library's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
|
||||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1990
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
That's all there is to it!
|
|
@ -1,481 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-only
|
|
||||||
*
|
|
||||||
* The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
*/
|
|
||||||
#include "kdlockedsharedmemorypointer.h"
|
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN )
|
|
||||||
#ifndef QT_NO_SHAREDMEMORY
|
|
||||||
|
|
||||||
namespace kdtools
|
|
||||||
{
|
|
||||||
}
|
|
||||||
using namespace kdtools;
|
|
||||||
|
|
||||||
KDLockedSharedMemoryPointerBase::KDLockedSharedMemoryPointerBase( QSharedMemory * m )
|
|
||||||
: locker( m ),
|
|
||||||
mem( m )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KDLockedSharedMemoryPointerBase::KDLockedSharedMemoryPointerBase( QSharedMemory & m )
|
|
||||||
: locker( &m ),
|
|
||||||
mem( &m )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KDLockedSharedMemoryPointerBase::~KDLockedSharedMemoryPointerBase() {}
|
|
||||||
|
|
||||||
void * KDLockedSharedMemoryPointerBase::get() {
|
|
||||||
return mem ? mem->data() : 0 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
const void * KDLockedSharedMemoryPointerBase::get() const {
|
|
||||||
return mem ? mem->data() : 0 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t KDLockedSharedMemoryPointerBase::byteSize() const {
|
|
||||||
return mem ? mem->size() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class KDLockedSharedMemoryPointer
|
|
||||||
\ingroup core raii smartptr
|
|
||||||
\brief Locking pointer for Qt shared memory segments
|
|
||||||
\since_c 2.1
|
|
||||||
|
|
||||||
(The exception safety of this class has not been evaluated yet.)
|
|
||||||
|
|
||||||
KDLockedSharedMemoryPointer is a smart immutable pointer, which gives convenient and safe access to a QSharedMemory data segment.
|
|
||||||
The content of a KDLockedSharedMemoryPointer cannot be changed during it's lifetime.
|
|
||||||
|
|
||||||
You can use this class like a normal pointer to the shared memory segment and be sure it's locked while accessing it.
|
|
||||||
\note You can only put simple types/structs/classes into it. structs and classes shall not contain any other pointers. See the
|
|
||||||
documentation of QSharedMemory for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryPointer::KDLockedSharedMemoryPointer( QSharedMemory * mem )
|
|
||||||
|
|
||||||
Constructor. Constructs a KDLockedSharedMemory pointer which points to the data segment of \a mem.
|
|
||||||
The constructor locks \a mem. If the memory segment is already locked by another process, this constructor
|
|
||||||
blocks until the lock is released.
|
|
||||||
|
|
||||||
\post data() == mem->data() and the memory segment has been locked
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryPointer::KDLockedSharedMemoryPointer( QSharedMemory & mem )
|
|
||||||
|
|
||||||
\overload
|
|
||||||
|
|
||||||
\post data() == mem.data() and the memory segment has been locked
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryPointer::~KDLockedSharedMemoryPointer()
|
|
||||||
|
|
||||||
Destructor. Unlocks the shared memory segment.
|
|
||||||
|
|
||||||
\post The shared memory segment has been unlocked
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T * KDLockedSharedMemoryPointer::get()
|
|
||||||
|
|
||||||
\returns a pointer to the contained object.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T * KDLockedSharedMemoryPointer::get() const
|
|
||||||
|
|
||||||
\returns a const pointer to the contained object
|
|
||||||
\overload
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T * KDLockedSharedMemoryPointer::data()
|
|
||||||
|
|
||||||
Equivalent to get(), provided for consistency with Qt naming conventions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T * KDLockedSharedMemoryPointer::data() const
|
|
||||||
|
|
||||||
\overload
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T & KDLockedSharedMemoryPointer::operator*()
|
|
||||||
|
|
||||||
Dereference operator. Returns \link get() *get()\endlink.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T & KDLockedSharedMemoryPointer::operator*() const
|
|
||||||
|
|
||||||
Dereference operator. Returns \link get() *get()\endlink.
|
|
||||||
\overload
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T * KDLockedSharedMemoryPointer::operator->()
|
|
||||||
|
|
||||||
Member-by-pointer operator. Returns get().
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T * KDLockedSharedMemoryPointer::operator->() const
|
|
||||||
|
|
||||||
Member-by-pointer operator. Returns get().
|
|
||||||
\overload
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class KDLockedSharedMemoryArray
|
|
||||||
\ingroup core raii smartptr
|
|
||||||
\brief Locking array pointer to Qt shared memory segments
|
|
||||||
\since_c 2.1
|
|
||||||
|
|
||||||
(The exception safety of this class has not been evaluated yet.)
|
|
||||||
|
|
||||||
KDLockedSharedMemoryArray is a smart immutable pointer, which gives convenient and safe access to array data stored in a QSharedMemory
|
|
||||||
data segment.
|
|
||||||
The content of a KDLockedSharedMemoryArray cannot be changed during it's lifetime.
|
|
||||||
|
|
||||||
You can use this class like a normal pointer to the shared memory segment and be sure it's locked while accessing it.
|
|
||||||
\note You can only put arrays of simple types/structs/classes into it. structs and classes shall not contain any other pointers. See the
|
|
||||||
documentation of QSharedMemory for details.
|
|
||||||
|
|
||||||
\sa KDLockedSharedMemoryPointer
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::KDLockedSharedMemoryArray( QSharedMemory* mem )
|
|
||||||
Constructor. Constructs a KDLockedSharedMemoryArray which points to the data segment of \a mem. The constructor locks \a mem. If the memory
|
|
||||||
segment is already locked by another process, this constructor blocks until the lock is release.
|
|
||||||
|
|
||||||
\post get() == mem->data() and the memory segment has been locked
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::KDLockedSharedMemoryArray( QSharedMemory& mem )
|
|
||||||
\overload
|
|
||||||
|
|
||||||
\post get() == mem->data() and the memory segment has been locked
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\typedef KDLockedSharedMemoryArray::size_type
|
|
||||||
Typedef for std::size_t. Provided for STL compatibility.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\typedef KDLockedSharedMemoryArray::difference_type
|
|
||||||
Typedef for std::ptrdiff_t. Provided for STL compatibility.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\typedef KDLockedSharedMemoryArray::iterator
|
|
||||||
Typedef for T*. Provided for STL compatibility.
|
|
||||||
\since_t 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\typedef KDLockedSharedMemoryArray::const_iterator
|
|
||||||
Typedef for const T*. Provided for STL compatibility.
|
|
||||||
\since_t 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\typedef KDLockedSharedMemoryArray::reverse_iterator
|
|
||||||
Typedef for std::reverse_iterator< \link KDLockedSharedMemoryArray::iterator iterator\endlink >. Provided for STL compatibility.
|
|
||||||
\since_t 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\typedef KDLockedSharedMemoryArray::const_reverse_iterator
|
|
||||||
Typedef for std::reverse_iterator< \link KDLockedSharedMemoryArray::const_iterator const_iterator\endlink >. Provided for STL compatibility.
|
|
||||||
\since_t 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::iterator KDLockedSharedMemoryArray::begin()
|
|
||||||
Returns an \link KDLockedSharedMemoryArray::iterator iterator\endlink pointing to the first item of the array.
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::const_iterator KDLockedSharedMemoryArray::begin() const
|
|
||||||
\overload
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::iterator KDLockedSharedMemoryArray::end()
|
|
||||||
Returns an \link KDLockedSharedMemoryArray::iterator iterator\endlink pointing to the item after the last item of the array.
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::const_iterator KDLockedSharedMemoryArray::end() const
|
|
||||||
\overload
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::reverse_iterator KDLockedSharedMemoryArray::rbegin()
|
|
||||||
Returns an \link KDLockedSharedMemoryArray::reverse_iterator reverse_iterator\endlink pointing to the item after the last item of the array.
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::const_reverse_iterator KDLockedSharedMemoryArray::rbegin() const
|
|
||||||
\overload
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::reverse_iterator KDLockedSharedMemoryArray::rend()
|
|
||||||
Returns an \link KDLockedSharedMemoryArray::reverse_iterator reverse_iterator\endlink pointing to the first item of the array.
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::const_reverse_iterator KDLockedSharedMemoryArray::rend() const
|
|
||||||
\overload
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn KDLockedSharedMemoryArray::size_type KDLockedSharedMemoryArray::size() const
|
|
||||||
Returns the size of this array. The size is calculated from the storage size of T and
|
|
||||||
the size of the shared memory segment.
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T& KDLockedSharedMemoryArray::operator[]( difference_type n )
|
|
||||||
Array access operator. Returns a reference to the item at index position \a n.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T& KDLockedSharedMemoryArray::operator[]( difference_type n ) const
|
|
||||||
\overload
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T& KDLockedSharedMemoryArray::front()
|
|
||||||
Returns a reference to the first item in the array. This is the same as operator[](0).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T& KDLockedSharedMemoryArray::front() const
|
|
||||||
\overload
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T& KDLockedSharedMemoryArray::back()
|
|
||||||
Returns a reference to the last item in the array. This is the same as operator[](size()-1).
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T& KDLockedSharedMemoryArray::back() const
|
|
||||||
\overload
|
|
||||||
\since_f 2.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef eKDTOOLSCORE_UNITTESTS
|
|
||||||
|
|
||||||
#include <KDUnitTest/Test>
|
|
||||||
|
|
||||||
#include <QThread>
|
|
||||||
#include <QUuid>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct TestStruct
|
|
||||||
{
|
|
||||||
TestStruct( uint nn = 0 )
|
|
||||||
: n( nn ),
|
|
||||||
f( 0.0 ),
|
|
||||||
c( '\0' ),
|
|
||||||
b( false )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
uint n;
|
|
||||||
double f;
|
|
||||||
char c;
|
|
||||||
bool b;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool operator==( const TestStruct& lhs, const TestStruct& rhs )
|
|
||||||
{
|
|
||||||
return lhs.n == rhs.n && lhs.f == rhs.f && lhs.c == rhs.c && lhs.b == rhs.b;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestThread : public QThread
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TestThread( const QString& key )
|
|
||||||
: mem( key )
|
|
||||||
{
|
|
||||||
mem.attach();
|
|
||||||
}
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
while( true )
|
|
||||||
{
|
|
||||||
msleep( 100 );
|
|
||||||
kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
|
|
||||||
if( !p->b )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
p->n = 5;
|
|
||||||
p->f = 3.14;
|
|
||||||
p->c = 'A';
|
|
||||||
p->b = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedMemory mem;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool isConst( TestStruct* )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isConst( const TestStruct* )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KDAB_UNITTEST_SIMPLE( KDLockedSharedMemoryPointer, "kdcoretools" ) {
|
|
||||||
|
|
||||||
const QString key = QUuid::createUuid();
|
|
||||||
QSharedMemory mem( key );
|
|
||||||
const bool created = mem.create( sizeof( TestStruct ) );
|
|
||||||
assertTrue( created );
|
|
||||||
if ( !created )
|
|
||||||
return; // don't execute tests if shm coulnd't be created
|
|
||||||
|
|
||||||
// On Windows, shared mem is only available in increments of page
|
|
||||||
// size (4k), so don't fail if the segment is larger:
|
|
||||||
const unsigned long mem_size = mem.size();
|
|
||||||
assertGreaterOrEqual( mem_size, sizeof( TestStruct ) );
|
|
||||||
|
|
||||||
{
|
|
||||||
kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
|
|
||||||
assertTrue( p );
|
|
||||||
*p = TestStruct();
|
|
||||||
assertEqual( p->n, 0u );
|
|
||||||
assertEqual( p->f, 0.0 );
|
|
||||||
assertEqual( p->c, '\0' );
|
|
||||||
assertFalse( p->b );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
TestThread thread( key );
|
|
||||||
assertEqual( thread.mem.key().toStdString(), key.toStdString() );
|
|
||||||
assertEqual( static_cast< unsigned long >( thread.mem.size() ), mem_size );
|
|
||||||
thread.start();
|
|
||||||
|
|
||||||
assertTrue( thread.isRunning() );
|
|
||||||
thread.wait( 2000 );
|
|
||||||
assertTrue( thread.isRunning() );
|
|
||||||
|
|
||||||
{
|
|
||||||
kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
|
|
||||||
p->b = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
thread.wait( 2000 );
|
|
||||||
assertFalse( thread.isRunning() );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
|
|
||||||
assertEqual( p->n, 5u );
|
|
||||||
assertEqual( p->f, 3.14 );
|
|
||||||
assertEqual( p->c, 'A' );
|
|
||||||
assertFalse( p->b );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
kdtools::KDLockedSharedMemoryPointer< TestStruct > p( mem );
|
|
||||||
assertEqual( mem.data(), p.get() );
|
|
||||||
assertEqual( p.get(), p.operator->() );
|
|
||||||
assertEqual( p.get(), &(*p) );
|
|
||||||
assertEqual( p.get(), p.data() );
|
|
||||||
assertFalse( isConst( p.get() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
|
|
||||||
assertEqual( mem.data(), p.get() );
|
|
||||||
assertEqual( p.get(), p.operator->() );
|
|
||||||
assertEqual( p.get(), &(*p) );
|
|
||||||
assertEqual( p.get(), p.data() );
|
|
||||||
assertTrue( isConst( p.get() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
QSharedMemory mem2( key + key );
|
|
||||||
const bool created2 = mem2.create( 16 * sizeof( TestStruct ) );
|
|
||||||
assertTrue( created2 );
|
|
||||||
if ( !created2 )
|
|
||||||
return; // don't execute tests if shm coulnd't be created
|
|
||||||
|
|
||||||
kdtools::KDLockedSharedMemoryArray<TestStruct> a( mem2 );
|
|
||||||
assertTrue( a );
|
|
||||||
assertEqual( a.get(), mem2.data() );
|
|
||||||
assertEqual( &a[0], a.get() );
|
|
||||||
|
|
||||||
a[1] = a[0];
|
|
||||||
assertTrue( a[0] == a[1] );
|
|
||||||
|
|
||||||
TestStruct ts;
|
|
||||||
ts.n = 5;
|
|
||||||
ts.f = 3.14;
|
|
||||||
a[0] = ts;
|
|
||||||
assertFalse( a[0] == a[1] );
|
|
||||||
assertEqual( a.front().n, ts.n );
|
|
||||||
assertEqual( a[0].f, ts.f );
|
|
||||||
a[0].n = 10;
|
|
||||||
assertEqual( a.front().n, 10u );
|
|
||||||
ts = a[0];
|
|
||||||
assertEqual( ts.n, 10u );
|
|
||||||
|
|
||||||
std::vector< TestStruct > v;
|
|
||||||
for( uint i = 0; i < a.size(); ++i )
|
|
||||||
v.push_back( TestStruct( i ) );
|
|
||||||
|
|
||||||
std::copy( v.begin(), v.end(), a.begin() );
|
|
||||||
for( uint i = 0; i < a.size(); ++i )
|
|
||||||
assertEqual( a[ i ].n, i );
|
|
||||||
assertEqual( a.front().n, 0u );
|
|
||||||
assertEqual( a.back().n, a.size() - 1 );
|
|
||||||
|
|
||||||
std::copy( v.begin(), v.end(), a.rbegin() );
|
|
||||||
for( uint i = 0; i < a.size(); ++i )
|
|
||||||
assertEqual( a[ i ].n, a.size() - 1 - i );
|
|
||||||
assertEqual( a.front().n, a.size() - 1 );
|
|
||||||
assertEqual( a.back().n, 0u );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif // KDTOOLSCORE_UNITTESTS
|
|
||||||
#endif // QT_NO_SHAREDMEMORY
|
|
||||||
#endif // QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN )
|
|
@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-only
|
|
||||||
*
|
|
||||||
* The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
*/
|
|
||||||
#ifndef __KDTOOLS__CORE__KDLOCKEDSHAREDMEMORYPOINTER_H__
|
|
||||||
#define __KDTOOLS__CORE__KDLOCKEDSHAREDMEMORYPOINTER_H__
|
|
||||||
|
|
||||||
#include <QtCore/QtGlobal>
|
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN )
|
|
||||||
#ifndef QT_NO_SHAREDMEMORY
|
|
||||||
|
|
||||||
#include "kdsharedmemorylocker.h"
|
|
||||||
#include <QtCore/QSharedMemory>
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_RUN
|
|
||||||
namespace kdtools {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class KDLockedSharedMemoryPointerBase {
|
|
||||||
protected:
|
|
||||||
explicit KDLockedSharedMemoryPointerBase( QSharedMemory * mem );
|
|
||||||
explicit KDLockedSharedMemoryPointerBase( QSharedMemory & mem );
|
|
||||||
~KDLockedSharedMemoryPointerBase();
|
|
||||||
|
|
||||||
// PENDING(marc) do we really want const propagation here? I
|
|
||||||
// usually declare all my RAII objects const...
|
|
||||||
void * get();
|
|
||||||
const void * get() const;
|
|
||||||
|
|
||||||
KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( get() )
|
|
||||||
|
|
||||||
size_t byteSize() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
KDSharedMemoryLocker locker;
|
|
||||||
QSharedMemory * const mem;
|
|
||||||
};
|
|
||||||
|
|
||||||
template< typename T>
|
|
||||||
class MAKEINCLUDES_EXPORT KDLockedSharedMemoryPointer : KDLockedSharedMemoryPointerBase {
|
|
||||||
KDAB_DISABLE_COPY( KDLockedSharedMemoryPointer );
|
|
||||||
public:
|
|
||||||
explicit KDLockedSharedMemoryPointer( QSharedMemory * m )
|
|
||||||
: KDLockedSharedMemoryPointerBase( m ) {}
|
|
||||||
explicit KDLockedSharedMemoryPointer( QSharedMemory & m )
|
|
||||||
: KDLockedSharedMemoryPointerBase( m ) {}
|
|
||||||
|
|
||||||
T * get() { return static_cast<T*>( KDLockedSharedMemoryPointerBase::get() ); }
|
|
||||||
const T * get() const { return static_cast<const T*>( KDLockedSharedMemoryPointerBase::get() ); }
|
|
||||||
|
|
||||||
T * data() { return static_cast<T*>( get() ); }
|
|
||||||
const T * data() const { return static_cast<const T*>( get() ); }
|
|
||||||
|
|
||||||
T & operator*() { assert( get() ); return *get(); }
|
|
||||||
const T & operator*() const { assert( get() ); return *get(); }
|
|
||||||
|
|
||||||
T * operator->() { return get(); }
|
|
||||||
const T * operator->() const { return get(); }
|
|
||||||
|
|
||||||
KDAB_USING_SAFE_BOOL_OPERATOR( KDLockedSharedMemoryPointerBase )
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class MAKEINCLUDES_EXPORT KDLockedSharedMemoryArray : KDLockedSharedMemoryPointerBase {
|
|
||||||
KDAB_DISABLE_COPY( KDLockedSharedMemoryArray );
|
|
||||||
public:
|
|
||||||
explicit KDLockedSharedMemoryArray( QSharedMemory * m )
|
|
||||||
: KDLockedSharedMemoryPointerBase( m ) {}
|
|
||||||
explicit KDLockedSharedMemoryArray( QSharedMemory & m )
|
|
||||||
: KDLockedSharedMemoryPointerBase( m ) {}
|
|
||||||
|
|
||||||
typedef std::size_t size_type;
|
|
||||||
typedef std::ptrdiff_t difference_type;
|
|
||||||
typedef T* iterator;
|
|
||||||
typedef const T* const_iterator;
|
|
||||||
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
|
|
||||||
typedef std::reverse_iterator< iterator > reverse_iterator;
|
|
||||||
|
|
||||||
iterator begin() { return get(); }
|
|
||||||
const_iterator begin() const { return get(); }
|
|
||||||
|
|
||||||
iterator end() { return begin() + size(); }
|
|
||||||
const_iterator end() const { return begin() + size(); }
|
|
||||||
|
|
||||||
reverse_iterator rbegin() { return reverse_iterator( end() ); }
|
|
||||||
const_reverse_iterator rbegin() const { return reverse_iterator( end() ); }
|
|
||||||
|
|
||||||
reverse_iterator rend() { return reverse_iterator( begin() ); }
|
|
||||||
const_reverse_iterator rend() const { return const_reverse_iterator( begin() ); }
|
|
||||||
|
|
||||||
size_type size() const { return byteSize() / sizeof( T ); }
|
|
||||||
|
|
||||||
T * get() { return static_cast<T*>( KDLockedSharedMemoryPointerBase::get() ); }
|
|
||||||
const T * get() const { return static_cast<const T*>( KDLockedSharedMemoryPointerBase::get() ); }
|
|
||||||
|
|
||||||
T & operator[]( difference_type n ) { assert( get() ); return *(get()+n); }
|
|
||||||
const T & operator[]( difference_type n ) const { assert( get() ); return *(get()+n); }
|
|
||||||
|
|
||||||
T & front() { assert( get() ); return *get(); }
|
|
||||||
const T & front() const { assert( get() ); return *get(); }
|
|
||||||
|
|
||||||
T & back() { assert( get() ); return *( get() + size() - 1 ); }
|
|
||||||
const T & back() const { assert( get() ); return *( get() + size() - 1 ); }
|
|
||||||
|
|
||||||
KDAB_USING_SAFE_BOOL_OPERATOR( KDLockedSharedMemoryPointerBase )
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_RUN
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* QT_NO_SHAREDMEMORY */
|
|
||||||
|
|
||||||
#endif /* QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN ) */
|
|
||||||
|
|
||||||
#endif /* __KDTOOLS__CORE__KDLOCKEDSHAREDMEMORYPOINTER_H__ */
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-only
|
|
||||||
*
|
|
||||||
* The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
*/
|
|
||||||
#include "kdsharedmemorylocker.h"
|
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN )
|
|
||||||
|
|
||||||
#include <QSharedMemory>
|
|
||||||
|
|
||||||
using namespace kdtools;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class KDSharedMemoryLocker
|
|
||||||
\ingroup raii core
|
|
||||||
\brief Exception-safe and convenient wrapper around QSharedMemory::lock()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor. Locks the shared memory segment \a mem.
|
|
||||||
* If another process has locking the segment, this constructor blocks
|
|
||||||
* until the lock is released. The memory segments needs to be properly created or attached.
|
|
||||||
*/
|
|
||||||
KDSharedMemoryLocker::KDSharedMemoryLocker( QSharedMemory* mem )
|
|
||||||
: mem( mem )
|
|
||||||
{
|
|
||||||
mem->lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor. Unlocks the shared memory segment associated with this
|
|
||||||
* KDSharedMemoryLocker.
|
|
||||||
*/
|
|
||||||
KDSharedMemoryLocker::~KDSharedMemoryLocker()
|
|
||||||
{
|
|
||||||
mem->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef KDAB_EVAL
|
|
||||||
#include KDAB_EVAL
|
|
||||||
static const EvalDialogChecker evalChecker( "KD Tools", false );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-only
|
|
||||||
*
|
|
||||||
* The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
*/
|
|
||||||
#ifndef __KDTOOLS__CORE__KDSHAREDMEMORYLOCKER_H
|
|
||||||
#define __KDTOOLS__CORE__KDSHAREDMEMORYLOCKER_H
|
|
||||||
|
|
||||||
#include "kdtoolsglobal.h"
|
|
||||||
|
|
||||||
#if QT_VERSION < 0x040400 && !defined( DOXYGEN_RUN )
|
|
||||||
#ifdef Q_CC_GNU
|
|
||||||
#warning "Can't use KDTools KDSharedMemoryLocker with Qt versions prior to 4.4"
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
|
|
||||||
class QSharedMemory;
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_RUN
|
|
||||||
namespace kdtools
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class KDTOOLSCORE_EXPORT KDSharedMemoryLocker
|
|
||||||
{
|
|
||||||
Q_DISABLE_COPY( KDSharedMemoryLocker )
|
|
||||||
public:
|
|
||||||
KDSharedMemoryLocker( QSharedMemory* mem );
|
|
||||||
~KDSharedMemoryLocker();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QSharedMemory* const mem;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_RUN
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
@ -1,147 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-only
|
|
||||||
*
|
|
||||||
* The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
*/
|
|
||||||
#ifndef KDTOOLSCORE_KDSINGLEAPPLICATIONGUARD_H
|
|
||||||
#define KDTOOLSCORE_KDSINGLEAPPLICATIONGUARD_H
|
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
|
||||||
|
|
||||||
#ifndef QT_NO_SHAREDMEMORY
|
|
||||||
|
|
||||||
#include <QtCore/QStringList>
|
|
||||||
#include <QtCore/QMetaType>
|
|
||||||
|
|
||||||
#include "pimpl_ptr.h"
|
|
||||||
#include "DllMacro.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
template <typename T> class QVector;
|
|
||||||
class QCoreApplication;
|
|
||||||
|
|
||||||
class DLLEXPORT KDSingleApplicationGuard : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_ENUMS( Policy )
|
|
||||||
Q_PROPERTY( bool operational READ isOperational )
|
|
||||||
Q_PROPERTY( bool exitRequested READ isExitRequested )
|
|
||||||
Q_PROPERTY( bool primaryInstance READ isPrimaryInstance NOTIFY becamePrimaryInstance )
|
|
||||||
Q_PROPERTY( Policy policy READ policy WRITE setPolicy NOTIFY policyChanged )
|
|
||||||
public:
|
|
||||||
enum Policy
|
|
||||||
{
|
|
||||||
NoPolicy = 0,
|
|
||||||
AutoKillOtherInstances = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit KDSingleApplicationGuard( QObject * parent=nullptr );
|
|
||||||
explicit KDSingleApplicationGuard( Policy policy, QObject * parent=nullptr );
|
|
||||||
explicit KDSingleApplicationGuard( const QStringList & arguments, QObject * parent=nullptr );
|
|
||||||
explicit KDSingleApplicationGuard( const QStringList & arguments, Policy policy, QObject * parent=nullptr );
|
|
||||||
~KDSingleApplicationGuard() override;
|
|
||||||
|
|
||||||
bool isOperational() const;
|
|
||||||
|
|
||||||
bool isExitRequested() const;
|
|
||||||
|
|
||||||
bool isPrimaryInstance() const;
|
|
||||||
|
|
||||||
Policy policy() const;
|
|
||||||
void setPolicy( Policy policy );
|
|
||||||
|
|
||||||
class Instance;
|
|
||||||
|
|
||||||
QVector<Instance> instances() const;
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void instanceStarted( const KDSingleApplicationGuard::Instance & instance );
|
|
||||||
void instanceExited( const KDSingleApplicationGuard::Instance & instance );
|
|
||||||
void exitRequested();
|
|
||||||
void raiseRequested();
|
|
||||||
void becamePrimaryInstance();
|
|
||||||
void becameSecondaryInstance();
|
|
||||||
void policyChanged( KDSingleApplicationGuard::Policy policy );
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void shutdownOtherInstances();
|
|
||||||
void killOtherInstances();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/*! \reimp */ bool event( QEvent * event ) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
#ifndef Q_WS_WIN
|
|
||||||
static void SIGINT_handler( int );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend struct ProcessInfo;
|
|
||||||
|
|
||||||
class Private;
|
|
||||||
kdtools::pimpl_ptr< Private > d;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DLLEXPORT KDSingleApplicationGuard::Instance {
|
|
||||||
friend class ::KDSingleApplicationGuard;
|
|
||||||
friend class ::KDSingleApplicationGuard::Private;
|
|
||||||
Instance( const QStringList &, bool, qint64 );
|
|
||||||
public:
|
|
||||||
Instance();
|
|
||||||
Instance( const Instance & other );
|
|
||||||
~Instance();
|
|
||||||
|
|
||||||
void swap( Instance & other ) {
|
|
||||||
std::swap( d, other.d );
|
|
||||||
}
|
|
||||||
|
|
||||||
Instance & operator=( Instance other ) {
|
|
||||||
swap( other );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() const { return !d; }
|
|
||||||
bool isValid() const;
|
|
||||||
|
|
||||||
bool areArgumentsTruncated() const;
|
|
||||||
|
|
||||||
const QStringList & arguments() const;
|
|
||||||
qint64 pid() const;
|
|
||||||
|
|
||||||
void shutdown();
|
|
||||||
void kill();
|
|
||||||
void raise();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Private;
|
|
||||||
Private * d;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <>
|
|
||||||
inline void swap( KDSingleApplicationGuard::Instance & lhs,
|
|
||||||
KDSingleApplicationGuard::Instance & rhs )
|
|
||||||
{
|
|
||||||
lhs.swap( rhs );
|
|
||||||
}
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline void qSwap( KDSingleApplicationGuard::Instance & lhs,
|
|
||||||
KDSingleApplicationGuard::Instance & rhs )
|
|
||||||
{
|
|
||||||
lhs.swap( rhs );
|
|
||||||
}
|
|
||||||
Q_DECLARE_METATYPE( KDSingleApplicationGuard::Instance )
|
|
||||||
Q_DECLARE_TYPEINFO( KDSingleApplicationGuard::Instance, Q_MOVABLE_TYPE );
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
|
|
||||||
#endif // QT_NO_SHAREDMEMORY
|
|
||||||
|
|
||||||
#endif /* KDTOOLSCORE_KDSINGLEAPPLICATIONGUARD_H */
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-only
|
|
||||||
*
|
|
||||||
* The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
*/
|
|
||||||
#include "kdtoolsglobal.h"
|
|
||||||
|
|
||||||
#include <QByteArray>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct Version {
|
|
||||||
unsigned char v[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline bool operator<( const Version & lhs, const Version & rhs ) {
|
|
||||||
return std::lexicographical_compare( lhs.v, lhs.v + 3, rhs.v, rhs.v + 3 );
|
|
||||||
}
|
|
||||||
static inline bool operator==( const Version & lhs, const Version & rhs ) {
|
|
||||||
return std::equal( lhs.v, lhs.v + 3, rhs.v );
|
|
||||||
}
|
|
||||||
KDTOOLS_MAKE_RELATION_OPERATORS( Version, static inline )
|
|
||||||
}
|
|
||||||
|
|
||||||
static Version kdParseQtVersion( const char * const version ) {
|
|
||||||
if ( !version || qstrlen( version ) < 5 || version[1] != '.' || version[3] != '.' || ( version[5] != 0 && version[5] != '.' && version[5] != '-' ) )
|
|
||||||
return Version(); // parse error
|
|
||||||
const Version result = { { static_cast< unsigned char >( version[0] - '0' ),
|
|
||||||
static_cast< unsigned char >( version[2] - '0' ),
|
|
||||||
static_cast< unsigned char >( version[4] - '0' ) } };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _kdCheckQtVersion_impl( unsigned int major, unsigned int minor, unsigned int patchlevel ) {
|
|
||||||
static const Version actual = kdParseQtVersion( qVersion() ); // do this only once each run...
|
|
||||||
const Version requested = { { static_cast< unsigned char >( major ),
|
|
||||||
static_cast< unsigned char >( minor ),
|
|
||||||
static_cast< unsigned char >( patchlevel ) } };
|
|
||||||
return actual >= requested;
|
|
||||||
}
|
|
120
3rdparty/kdsingleapplicationguard/kdtoolsglobal.h
vendored
120
3rdparty/kdsingleapplicationguard/kdtoolsglobal.h
vendored
@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-only
|
|
||||||
*
|
|
||||||
* The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
*/
|
|
||||||
#ifndef KDTOOLS_KDTOOLSGLOBAL_H
|
|
||||||
#define KDTOOLS_KDTOOLSGLOBAL_H
|
|
||||||
|
|
||||||
#include <QtCore/QtGlobal>
|
|
||||||
|
|
||||||
#define KDAB_DISABLE_COPY( x ) private: x( const x & ); x & operator=( const x & )
|
|
||||||
|
|
||||||
#ifdef KDTOOLS_SHARED
|
|
||||||
# ifdef BUILD_SHARED_KDTOOLSCORE
|
|
||||||
# define KDTOOLSCORE_EXPORT Q_DECL_EXPORT
|
|
||||||
# else
|
|
||||||
# define KDTOOLSCORE_EXPORT Q_DECL_IMPORT
|
|
||||||
# endif
|
|
||||||
# ifdef BUILD_SHARED_KDTOOLSGUI
|
|
||||||
# define KDTOOLSGUI_EXPORT Q_DECL_EXPORT
|
|
||||||
# else
|
|
||||||
# define KDTOOLSGUI_EXPORT Q_DECL_IMPORT
|
|
||||||
# endif
|
|
||||||
# ifdef BUILD_SHARED_KDTOOLSXML
|
|
||||||
# define KDTOOLSXML_EXPORT Q_DECL_EXPORT
|
|
||||||
# else
|
|
||||||
# define KDTOOLSXML_EXPORT Q_DECL_IMPORT
|
|
||||||
# endif
|
|
||||||
# ifdef BUILD_SHARED_KDUPDATER
|
|
||||||
# define KDTOOLS_UPDATER_EXPORT Q_DECL_EXPORT
|
|
||||||
# else
|
|
||||||
# define KDTOOLS_UPDATER_EXPORT Q_DECL_IMPORT
|
|
||||||
# endif
|
|
||||||
#else // KDTOOLS_SHARED
|
|
||||||
# define KDTOOLSCORE_EXPORT
|
|
||||||
# define KDTOOLSGUI_EXPORT
|
|
||||||
# define KDTOOLSXML_EXPORT
|
|
||||||
# define KDTOOLS_UPDATER_EXPORT
|
|
||||||
#endif // KDTOOLS_SHARED
|
|
||||||
|
|
||||||
#define MAKEINCLUDES_EXPORT
|
|
||||||
|
|
||||||
#define DOXYGEN_PROPERTY( x )
|
|
||||||
#ifdef DOXYGEN_RUN
|
|
||||||
# define KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( func ) operator unspecified_bool_type() const { return func; }
|
|
||||||
# define KDAB_USING_SAFE_BOOL_OPERATOR( Class ) operator unspecified_bool_type() const;
|
|
||||||
#else
|
|
||||||
# define KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( func ) \
|
|
||||||
private: \
|
|
||||||
struct __safe_bool_dummy__ { void nonnull() {} }; \
|
|
||||||
public: \
|
|
||||||
typedef void ( __safe_bool_dummy__::*unspecified_bool_type )(); \
|
|
||||||
operator unspecified_bool_type() const { \
|
|
||||||
return ( func ) ? &__safe_bool_dummy__::nonnull : 0 ; \
|
|
||||||
}
|
|
||||||
#define KDAB_USING_SAFE_BOOL_OPERATOR( Class ) \
|
|
||||||
using Class::operator Class::unspecified_bool_type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define KDTOOLS_MAKE_RELATION_OPERATORS( Class, linkage ) \
|
|
||||||
linkage bool operator>( const Class & lhs, const Class & rhs ) { \
|
|
||||||
return operator<( rhs, lhs ); \
|
|
||||||
} \
|
|
||||||
linkage bool operator!=( const Class & lhs, const Class & rhs ) { \
|
|
||||||
return !operator==( lhs, rhs ); \
|
|
||||||
} \
|
|
||||||
linkage bool operator<=( const Class & lhs, const Class & rhs ) { \
|
|
||||||
return !operator>( lhs, rhs ); \
|
|
||||||
} \
|
|
||||||
linkage bool operator>=( const Class & lhs, const Class & rhs ) { \
|
|
||||||
return !operator<( lhs, rhs ); \
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T & __kdtools__dereference_for_methodcall( T & o ) {
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T & __kdtools__dereference_for_methodcall( T * o ) {
|
|
||||||
return *o;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define KDAB_SET_OBJECT_NAME( x ) __kdtools__dereference_for_methodcall( x ).setObjectName( QLatin1String( #x ) )
|
|
||||||
|
|
||||||
KDTOOLSCORE_EXPORT bool _kdCheckQtVersion_impl( unsigned int major, unsigned int minor=0, unsigned int patchlevel=0 );
|
|
||||||
static inline bool kdCheckQtVersion( unsigned int major, unsigned int minor=0, unsigned int patchlevel=0 ) {
|
|
||||||
return (major<<16|minor<<8|patchlevel) <= static_cast<unsigned int>(QT_VERSION)
|
|
||||||
|| _kdCheckQtVersion_impl( major, minor, patchlevel );
|
|
||||||
}
|
|
||||||
|
|
||||||
#define KDTOOLS_DECLARE_PRIVATE_BASE( Class ) \
|
|
||||||
protected: \
|
|
||||||
class Private; \
|
|
||||||
Private * d_func() { return _d; } \
|
|
||||||
const Private * d_func() const { return _d; } \
|
|
||||||
Class( Private * _d_, bool b ) : _d( _d_ ) { init(b); } \
|
|
||||||
private: \
|
|
||||||
void init(bool); \
|
|
||||||
private: \
|
|
||||||
Private * _d
|
|
||||||
|
|
||||||
#define KDTOOLS_DECLARE_PRIVATE_DERIVED( Class, Base ) \
|
|
||||||
protected: \
|
|
||||||
class Private; \
|
|
||||||
Private * d_func() { \
|
|
||||||
return reinterpret_cast<Private*>( Base::d_func() ); \
|
|
||||||
} \
|
|
||||||
const Private * d_func() const { \
|
|
||||||
return reinterpret_cast<const Private*>( Base::d_func() ); \
|
|
||||||
} \
|
|
||||||
Class( Private * _d_, bool b ) \
|
|
||||||
: Base( reinterpret_cast<Base::Private*>(_d_), b ) { init(b); } \
|
|
||||||
private: \
|
|
||||||
void init(bool)
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* KDTOOLS_KDTOOLSGLOBAL_H */
|
|
||||||
|
|
209
3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp
vendored
209
3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp
vendored
@ -1,209 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-only
|
|
||||||
*
|
|
||||||
* The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
*/
|
|
||||||
#include "pimpl_ptr.h"
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class pimpl_ptr:
|
|
||||||
\ingroup core smartptr
|
|
||||||
\brief Owning pointer for private implementations
|
|
||||||
\since_c 2.1
|
|
||||||
|
|
||||||
(The exception safety of this class has not been evaluated yet.)
|
|
||||||
|
|
||||||
pimpl_ptr is a smart immutable pointer, which owns the contained object. Unlike other smart pointers,
|
|
||||||
it creates a standard constructed object when instanciated via the
|
|
||||||
\link pimpl_ptr() standard constructor\endlink.
|
|
||||||
Additionally, pimpl_ptr respects constness of the pointer object and returns \c const \c T* for
|
|
||||||
a const pimpl_ptr object.
|
|
||||||
|
|
||||||
The content of a pimpl_ptr cannot be changed during it's lifetime.
|
|
||||||
|
|
||||||
\section general-use General Use
|
|
||||||
|
|
||||||
The general use case of pimpl_ptr is the "Pimpl Idiom", i.e. hiding the private implementation of a class
|
|
||||||
from the user's compiler which see \c MyClass as
|
|
||||||
|
|
||||||
\code
|
|
||||||
class MyClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MyClass();
|
|
||||||
~MyClass();
|
|
||||||
|
|
||||||
// public class API
|
|
||||||
int value() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Private; // defined later
|
|
||||||
kdtools::pimpl_ptr< Private > d;
|
|
||||||
};
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
but not the private parts of it. These can only be seen (and accessed) by the code knowing \c MyClass::Private:
|
|
||||||
|
|
||||||
\code
|
|
||||||
class MyClass::Private
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int value;
|
|
||||||
};
|
|
||||||
|
|
||||||
MyClass::MyClass()
|
|
||||||
{
|
|
||||||
// d was automatically filled with new Private
|
|
||||||
d->value = 42;
|
|
||||||
}
|
|
||||||
|
|
||||||
MyClass::~MyClass()
|
|
||||||
{
|
|
||||||
// the content of d gets deleted automatically
|
|
||||||
}
|
|
||||||
|
|
||||||
int MyClass::value() const
|
|
||||||
{
|
|
||||||
// access the private part:
|
|
||||||
// since MyClass::value() is const, the returned pointee is const, too
|
|
||||||
return d->value;
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn pimpl_ptr::pimpl_ptr()
|
|
||||||
|
|
||||||
Default constructor. Constructs a pimpl_tr that contains (owns) a standard constructed
|
|
||||||
instance of \c T.
|
|
||||||
|
|
||||||
\post \c *this owns a new object.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn pimpl_ptr::pimpl_ptr( T * t )
|
|
||||||
|
|
||||||
Constructor. Constructs a pimpl_ptr that contains (owns) \a t.
|
|
||||||
|
|
||||||
\post get() == obj
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn pimpl_ptr::~pimpl_ptr()
|
|
||||||
|
|
||||||
Destructor.
|
|
||||||
|
|
||||||
\post The object previously owned by \c *this has been deleted.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T * pimpl_ptr::get() const
|
|
||||||
|
|
||||||
\returns a const pointer to the contained (owned) object.
|
|
||||||
\overload
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T * pimpl_ptr::get()
|
|
||||||
|
|
||||||
\returns a pointer to the contained (owned) object.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T & pimpl_ptr::operator*() const
|
|
||||||
|
|
||||||
Dereference operator. Returns \link get() *get()\endlink.
|
|
||||||
\overload
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T & pimpl_ptr::operator*()
|
|
||||||
|
|
||||||
Dereference operator. Returns \link get() *get()\endlink.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const T * pimpl_ptr::operator->() const
|
|
||||||
|
|
||||||
Member-by-pointer operator. Returns get().
|
|
||||||
\overload
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn T * pimpl_ptr::operator->()
|
|
||||||
|
|
||||||
Member-by-pointer operator. Returns get().
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef KDTOOLSCORE_UNITTESTS
|
|
||||||
|
|
||||||
#include <kdunittest/test.h>
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QPointer>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct ConstTester
|
|
||||||
{
|
|
||||||
bool isConst()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isConst() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
KDAB_UNITTEST_SIMPLE( pimpl_ptr, "kdcoretools" ) {
|
|
||||||
|
|
||||||
{
|
|
||||||
kdtools::pimpl_ptr< QObject > p;
|
|
||||||
assertNotNull( p.get() );
|
|
||||||
assertNull( p->parent() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
QPointer< QObject > o;
|
|
||||||
{
|
|
||||||
kdtools::pimpl_ptr< QObject > qobject( new QObject );
|
|
||||||
o = qobject.get();
|
|
||||||
assertEqual( o, qobject.operator->() );
|
|
||||||
assertEqual( o, &(qobject.operator*()) );
|
|
||||||
}
|
|
||||||
assertNull( o );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const kdtools::pimpl_ptr< QObject > qobject( new QObject );
|
|
||||||
const QObject* o = qobject.get();
|
|
||||||
assertEqual( o, qobject.operator->() );
|
|
||||||
assertEqual( o, &(qobject.operator*()) );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
kdtools::pimpl_ptr< QObject > o1;
|
|
||||||
assertTrue( o1 );
|
|
||||||
kdtools::pimpl_ptr< QObject > o2( 0 );
|
|
||||||
assertFalse( o2 );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const kdtools::pimpl_ptr< ConstTester > o1;
|
|
||||||
kdtools::pimpl_ptr< ConstTester > o2;
|
|
||||||
assertTrue( o1->isConst() );
|
|
||||||
assertFalse( o2->isConst() );
|
|
||||||
assertTrue( (*o1).isConst() );
|
|
||||||
assertFalse( (*o2).isConst() );
|
|
||||||
assertTrue( o1.get()->isConst() );
|
|
||||||
assertFalse( o2.get()->isConst() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // KDTOOLSCORE_UNITTESTS
|
|
50
3rdparty/kdsingleapplicationguard/pimpl_ptr.h
vendored
50
3rdparty/kdsingleapplicationguard/pimpl_ptr.h
vendored
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-only
|
|
||||||
*
|
|
||||||
* The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
*/
|
|
||||||
#ifndef KDTOOLSCORE_PIMPL_PTR_H
|
|
||||||
#define KDTOOLSCORE_PIMPL_PTR_H
|
|
||||||
|
|
||||||
#include "kdtoolsglobal.h"
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_RUN
|
|
||||||
namespace kdtools {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class pimpl_ptr {
|
|
||||||
KDAB_DISABLE_COPY( pimpl_ptr );
|
|
||||||
T * d;
|
|
||||||
public:
|
|
||||||
pimpl_ptr() : d( new T ) {}
|
|
||||||
explicit pimpl_ptr( T * t ) : d( t ) {}
|
|
||||||
~pimpl_ptr() { delete d; d = nullptr; }
|
|
||||||
|
|
||||||
T * get() { return d; }
|
|
||||||
const T * get() const { return d; }
|
|
||||||
|
|
||||||
T * operator->() { return get(); }
|
|
||||||
const T * operator->() const { return get(); }
|
|
||||||
|
|
||||||
T & operator*() { return *get(); }
|
|
||||||
const T & operator*() const { return *get(); }
|
|
||||||
|
|
||||||
KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( get() )
|
|
||||||
};
|
|
||||||
|
|
||||||
// these are not implemented, so's we can catch their use at
|
|
||||||
// link-time. Leaving them undeclared would open up a comparison
|
|
||||||
// via operator unspecified-bool-type().
|
|
||||||
template <typename T, typename S>
|
|
||||||
void operator==( const pimpl_ptr<T> &, const pimpl_ptr<S> & );
|
|
||||||
template <typename T, typename S>
|
|
||||||
void operator!=( const pimpl_ptr<T> &, const pimpl_ptr<S> & );
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_RUN
|
|
||||||
} // namespace kdtools
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* KDTOOLSCORE_PIMPL_PTR_H */
|
|
||||||
|
|
16
3rdparty/pybind11/CMakeLists.txt
vendored
Normal file
16
3rdparty/pybind11/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# === This file is part of Calamares - <https://calamares.io> ===
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2023 Adriaan de Groot <groot@kde.org>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
#
|
||||||
|
###
|
||||||
|
#
|
||||||
|
# This is a very-stripped-down way of getting the bundled pybind11
|
||||||
|
|
||||||
|
add_library(pybind11_headers INTERFACE)
|
||||||
|
add_library(pybind11::headers ALIAS pybind11_headers)
|
||||||
|
|
||||||
|
target_include_directories(pybind11_headers INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
target_link_libraries(pybind11_headers INTERFACE Python::Python) # Was searched-for at top-level
|
||||||
|
|
||||||
|
|
29
3rdparty/pybind11/LICENSE
vendored
Normal file
29
3rdparty/pybind11/LICENSE
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of
|
||||||
|
external contributions to this project including patches, pull requests, etc.
|
6
3rdparty/pybind11/MANIFEST.in
vendored
Normal file
6
3rdparty/pybind11/MANIFEST.in
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
prune tests
|
||||||
|
recursive-include pybind11/include/pybind11 *.h
|
||||||
|
recursive-include pybind11 *.py
|
||||||
|
recursive-include pybind11 py.typed
|
||||||
|
include pybind11/share/cmake/pybind11/*.cmake
|
||||||
|
include LICENSE README.rst SECURITY.md pyproject.toml setup.py setup.cfg
|
180
3rdparty/pybind11/README.rst
vendored
Normal file
180
3rdparty/pybind11/README.rst
vendored
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
.. figure:: https://github.com/pybind/pybind11/raw/master/docs/pybind11-logo.png
|
||||||
|
:alt: pybind11 logo
|
||||||
|
|
||||||
|
**pybind11 — Seamless operability between C++11 and Python**
|
||||||
|
|
||||||
|
|Latest Documentation Status| |Stable Documentation Status| |Gitter chat| |GitHub Discussions| |CI| |Build status|
|
||||||
|
|
||||||
|
|Repology| |PyPI package| |Conda-forge| |Python Versions|
|
||||||
|
|
||||||
|
`Setuptools example <https://github.com/pybind/python_example>`_
|
||||||
|
• `Scikit-build example <https://github.com/pybind/scikit_build_example>`_
|
||||||
|
• `CMake example <https://github.com/pybind/cmake_example>`_
|
||||||
|
|
||||||
|
.. start
|
||||||
|
|
||||||
|
|
||||||
|
**pybind11** is a lightweight header-only library that exposes C++ types
|
||||||
|
in Python and vice versa, mainly to create Python bindings of existing
|
||||||
|
C++ code. Its goals and syntax are similar to the excellent
|
||||||
|
`Boost.Python <http://www.boost.org/doc/libs/1_58_0/libs/python/doc/>`_
|
||||||
|
library by David Abrahams: to minimize boilerplate code in traditional
|
||||||
|
extension modules by inferring type information using compile-time
|
||||||
|
introspection.
|
||||||
|
|
||||||
|
The main issue with Boost.Python—and the reason for creating such a
|
||||||
|
similar project—is Boost. Boost is an enormously large and complex suite
|
||||||
|
of utility libraries that works with almost every C++ compiler in
|
||||||
|
existence. This compatibility has its cost: arcane template tricks and
|
||||||
|
workarounds are necessary to support the oldest and buggiest of compiler
|
||||||
|
specimens. Now that C++11-compatible compilers are widely available,
|
||||||
|
this heavy machinery has become an excessively large and unnecessary
|
||||||
|
dependency.
|
||||||
|
|
||||||
|
Think of this library as a tiny self-contained version of Boost.Python
|
||||||
|
with everything stripped away that isn't relevant for binding
|
||||||
|
generation. Without comments, the core header files only require ~4K
|
||||||
|
lines of code and depend on Python (3.6+, or PyPy) and the C++
|
||||||
|
standard library. This compact implementation was possible thanks to
|
||||||
|
some of the new C++11 language features (specifically: tuples, lambda
|
||||||
|
functions and variadic templates). Since its creation, this library has
|
||||||
|
grown beyond Boost.Python in many ways, leading to dramatically simpler
|
||||||
|
binding code in many common situations.
|
||||||
|
|
||||||
|
Tutorial and reference documentation is provided at
|
||||||
|
`pybind11.readthedocs.io <https://pybind11.readthedocs.io/en/latest>`_.
|
||||||
|
A PDF version of the manual is available
|
||||||
|
`here <https://pybind11.readthedocs.io/_/downloads/en/latest/pdf/>`_.
|
||||||
|
And the source code is always available at
|
||||||
|
`github.com/pybind/pybind11 <https://github.com/pybind/pybind11>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Core features
|
||||||
|
-------------
|
||||||
|
|
||||||
|
|
||||||
|
pybind11 can map the following core C++ features to Python:
|
||||||
|
|
||||||
|
- Functions accepting and returning custom data structures per value,
|
||||||
|
reference, or pointer
|
||||||
|
- Instance methods and static methods
|
||||||
|
- Overloaded functions
|
||||||
|
- Instance attributes and static attributes
|
||||||
|
- Arbitrary exception types
|
||||||
|
- Enumerations
|
||||||
|
- Callbacks
|
||||||
|
- Iterators and ranges
|
||||||
|
- Custom operators
|
||||||
|
- Single and multiple inheritance
|
||||||
|
- STL data structures
|
||||||
|
- Smart pointers with reference counting like ``std::shared_ptr``
|
||||||
|
- Internal references with correct reference counting
|
||||||
|
- C++ classes with virtual (and pure virtual) methods can be extended
|
||||||
|
in Python
|
||||||
|
|
||||||
|
Goodies
|
||||||
|
-------
|
||||||
|
|
||||||
|
In addition to the core functionality, pybind11 provides some extra
|
||||||
|
goodies:
|
||||||
|
|
||||||
|
- Python 3.6+, and PyPy3 7.3 are supported with an implementation-agnostic
|
||||||
|
interface (pybind11 2.9 was the last version to support Python 2 and 3.5).
|
||||||
|
|
||||||
|
- It is possible to bind C++11 lambda functions with captured
|
||||||
|
variables. The lambda capture data is stored inside the resulting
|
||||||
|
Python function object.
|
||||||
|
|
||||||
|
- pybind11 uses C++11 move constructors and move assignment operators
|
||||||
|
whenever possible to efficiently transfer custom data types.
|
||||||
|
|
||||||
|
- It's easy to expose the internal storage of custom data types through
|
||||||
|
Pythons' buffer protocols. This is handy e.g. for fast conversion
|
||||||
|
between C++ matrix classes like Eigen and NumPy without expensive
|
||||||
|
copy operations.
|
||||||
|
|
||||||
|
- pybind11 can automatically vectorize functions so that they are
|
||||||
|
transparently applied to all entries of one or more NumPy array
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
- Python's slice-based access and assignment operations can be
|
||||||
|
supported with just a few lines of code.
|
||||||
|
|
||||||
|
- Everything is contained in just a few header files; there is no need
|
||||||
|
to link against any additional libraries.
|
||||||
|
|
||||||
|
- Binaries are generally smaller by a factor of at least 2 compared to
|
||||||
|
equivalent bindings generated by Boost.Python. A recent pybind11
|
||||||
|
conversion of PyRosetta, an enormous Boost.Python binding project,
|
||||||
|
`reported <https://graylab.jhu.edu/Sergey/2016.RosettaCon/PyRosetta-4.pdf>`_
|
||||||
|
a binary size reduction of **5.4x** and compile time reduction by
|
||||||
|
**5.8x**.
|
||||||
|
|
||||||
|
- Function signatures are precomputed at compile time (using
|
||||||
|
``constexpr``), leading to smaller binaries.
|
||||||
|
|
||||||
|
- With little extra effort, C++ types can be pickled and unpickled
|
||||||
|
similar to regular Python objects.
|
||||||
|
|
||||||
|
Supported compilers
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
1. Clang/LLVM 3.3 or newer (for Apple Xcode's clang, this is 5.0.0 or
|
||||||
|
newer)
|
||||||
|
2. GCC 4.8 or newer
|
||||||
|
3. Microsoft Visual Studio 2017 or newer
|
||||||
|
4. Intel classic C++ compiler 18 or newer (ICC 20.2 tested in CI)
|
||||||
|
5. Cygwin/GCC (previously tested on 2.5.1)
|
||||||
|
6. NVCC (CUDA 11.0 tested in CI)
|
||||||
|
7. NVIDIA PGI (20.9 tested in CI)
|
||||||
|
|
||||||
|
About
|
||||||
|
-----
|
||||||
|
|
||||||
|
This project was created by `Wenzel
|
||||||
|
Jakob <http://rgl.epfl.ch/people/wjakob>`_. Significant features and/or
|
||||||
|
improvements to the code were contributed by Jonas Adler, Lori A. Burns,
|
||||||
|
Sylvain Corlay, Eric Cousineau, Aaron Gokaslan, Ralf Grosse-Kunstleve, Trent Houliston, Axel
|
||||||
|
Huebl, @hulucc, Yannick Jadoul, Sergey Lyskov, Johan Mabille, Tomasz Miąsko,
|
||||||
|
Dean Moldovan, Ben Pritchard, Jason Rhinelander, Boris Schäling, Pim
|
||||||
|
Schellart, Henry Schreiner, Ivan Smirnov, Boris Staletic, and Patrick Stewart.
|
||||||
|
|
||||||
|
We thank Google for a generous financial contribution to the continuous
|
||||||
|
integration infrastructure used by this project.
|
||||||
|
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
See the `contributing
|
||||||
|
guide <https://github.com/pybind/pybind11/blob/master/.github/CONTRIBUTING.md>`_
|
||||||
|
for information on building and contributing to pybind11.
|
||||||
|
|
||||||
|
License
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
pybind11 is provided under a BSD-style license that can be found in the
|
||||||
|
`LICENSE <https://github.com/pybind/pybind11/blob/master/LICENSE>`_
|
||||||
|
file. By using, distributing, or contributing to this project, you agree
|
||||||
|
to the terms and conditions of this license.
|
||||||
|
|
||||||
|
.. |Latest Documentation Status| image:: https://readthedocs.org/projects/pybind11/badge?version=latest
|
||||||
|
:target: http://pybind11.readthedocs.org/en/latest
|
||||||
|
.. |Stable Documentation Status| image:: https://img.shields.io/badge/docs-stable-blue.svg
|
||||||
|
:target: http://pybind11.readthedocs.org/en/stable
|
||||||
|
.. |Gitter chat| image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg
|
||||||
|
:target: https://gitter.im/pybind/Lobby
|
||||||
|
.. |CI| image:: https://github.com/pybind/pybind11/workflows/CI/badge.svg
|
||||||
|
:target: https://github.com/pybind/pybind11/actions
|
||||||
|
.. |Build status| image:: https://ci.appveyor.com/api/projects/status/riaj54pn4h08xy40?svg=true
|
||||||
|
:target: https://ci.appveyor.com/project/wjakob/pybind11
|
||||||
|
.. |PyPI package| image:: https://img.shields.io/pypi/v/pybind11.svg
|
||||||
|
:target: https://pypi.org/project/pybind11/
|
||||||
|
.. |Conda-forge| image:: https://img.shields.io/conda/vn/conda-forge/pybind11.svg
|
||||||
|
:target: https://github.com/conda-forge/pybind11-feedstock
|
||||||
|
.. |Repology| image:: https://repology.org/badge/latest-versions/python:pybind11.svg
|
||||||
|
:target: https://repology.org/project/python:pybind11/versions
|
||||||
|
.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/pybind11.svg
|
||||||
|
:target: https://pypi.org/project/pybind11/
|
||||||
|
.. |GitHub Discussions| image:: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github
|
||||||
|
:target: https://github.com/pybind/pybind11/discussions
|
13
3rdparty/pybind11/SECURITY.md
vendored
Normal file
13
3rdparty/pybind11/SECURITY.md
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Security updates are applied only to the latest release.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
|
||||||
|
|
||||||
|
Please disclose it at [security advisory](https://github.com/pybind/pybind11/security/advisories/new).
|
||||||
|
|
||||||
|
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.
|
690
3rdparty/pybind11/include/pybind11/attr.h
vendored
Normal file
690
3rdparty/pybind11/include/pybind11/attr.h
vendored
Normal file
@ -0,0 +1,690 @@
|
|||||||
|
/*
|
||||||
|
pybind11/attr.h: Infrastructure for processing custom
|
||||||
|
type and function attributes
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "detail/common.h"
|
||||||
|
#include "cast.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
/// \addtogroup annotations
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// Annotation for methods
|
||||||
|
struct is_method {
|
||||||
|
handle class_;
|
||||||
|
explicit is_method(const handle &c) : class_(c) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Annotation for setters
|
||||||
|
struct is_setter {};
|
||||||
|
|
||||||
|
/// Annotation for operators
|
||||||
|
struct is_operator {};
|
||||||
|
|
||||||
|
/// Annotation for classes that cannot be subclassed
|
||||||
|
struct is_final {};
|
||||||
|
|
||||||
|
/// Annotation for parent scope
|
||||||
|
struct scope {
|
||||||
|
handle value;
|
||||||
|
explicit scope(const handle &s) : value(s) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Annotation for documentation
|
||||||
|
struct doc {
|
||||||
|
const char *value;
|
||||||
|
explicit doc(const char *value) : value(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Annotation for function names
|
||||||
|
struct name {
|
||||||
|
const char *value;
|
||||||
|
explicit name(const char *value) : value(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Annotation indicating that a function is an overload associated with a given "sibling"
|
||||||
|
struct sibling {
|
||||||
|
handle value;
|
||||||
|
explicit sibling(const handle &value) : value(value.ptr()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Annotation indicating that a class derives from another given type
|
||||||
|
template <typename T>
|
||||||
|
struct base {
|
||||||
|
|
||||||
|
PYBIND11_DEPRECATED(
|
||||||
|
"base<T>() was deprecated in favor of specifying 'T' as a template argument to class_")
|
||||||
|
base() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Keep patient alive while nurse lives
|
||||||
|
template <size_t Nurse, size_t Patient>
|
||||||
|
struct keep_alive {};
|
||||||
|
|
||||||
|
/// Annotation indicating that a class is involved in a multiple inheritance relationship
|
||||||
|
struct multiple_inheritance {};
|
||||||
|
|
||||||
|
/// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class
|
||||||
|
struct dynamic_attr {};
|
||||||
|
|
||||||
|
/// Annotation which enables the buffer protocol for a type
|
||||||
|
struct buffer_protocol {};
|
||||||
|
|
||||||
|
/// Annotation which requests that a special metaclass is created for a type
|
||||||
|
struct metaclass {
|
||||||
|
handle value;
|
||||||
|
|
||||||
|
PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now.")
|
||||||
|
metaclass() = default;
|
||||||
|
|
||||||
|
/// Override pybind11's default metaclass
|
||||||
|
explicit metaclass(handle value) : value(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Specifies a custom callback with signature `void (PyHeapTypeObject*)` that
|
||||||
|
/// may be used to customize the Python type.
|
||||||
|
///
|
||||||
|
/// The callback is invoked immediately before `PyType_Ready`.
|
||||||
|
///
|
||||||
|
/// Note: This is an advanced interface, and uses of it may require changes to
|
||||||
|
/// work with later versions of pybind11. You may wish to consult the
|
||||||
|
/// implementation of `make_new_python_type` in `detail/classes.h` to understand
|
||||||
|
/// the context in which the callback will be run.
|
||||||
|
struct custom_type_setup {
|
||||||
|
using callback = std::function<void(PyHeapTypeObject *heap_type)>;
|
||||||
|
|
||||||
|
explicit custom_type_setup(callback value) : value(std::move(value)) {}
|
||||||
|
|
||||||
|
callback value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Annotation that marks a class as local to the module:
|
||||||
|
struct module_local {
|
||||||
|
const bool value;
|
||||||
|
constexpr explicit module_local(bool v = true) : value(v) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Annotation to mark enums as an arithmetic type
|
||||||
|
struct arithmetic {};
|
||||||
|
|
||||||
|
/// Mark a function for addition at the beginning of the existing overload chain instead of the end
|
||||||
|
struct prepend {};
|
||||||
|
|
||||||
|
/** \rst
|
||||||
|
A call policy which places one or more guard variables (``Ts...``) around the function call.
|
||||||
|
|
||||||
|
For example, this definition:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("foo", foo, py::call_guard<T>());
|
||||||
|
|
||||||
|
is equivalent to the following pseudocode:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("foo", [](args...) {
|
||||||
|
T scope_guard;
|
||||||
|
return foo(args...); // forwarded arguments
|
||||||
|
});
|
||||||
|
\endrst */
|
||||||
|
template <typename... Ts>
|
||||||
|
struct call_guard;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct call_guard<> {
|
||||||
|
using type = detail::void_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct call_guard<T> {
|
||||||
|
static_assert(std::is_default_constructible<T>::value,
|
||||||
|
"The guard type must be default constructible");
|
||||||
|
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename... Ts>
|
||||||
|
struct call_guard<T, Ts...> {
|
||||||
|
struct type {
|
||||||
|
T guard{}; // Compose multiple guard types with left-to-right default-constructor order
|
||||||
|
typename call_guard<Ts...>::type next{};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @} annotations
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
/* Forward declarations */
|
||||||
|
enum op_id : int;
|
||||||
|
enum op_type : int;
|
||||||
|
struct undefined_t;
|
||||||
|
template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t>
|
||||||
|
struct op_;
|
||||||
|
void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret);
|
||||||
|
|
||||||
|
/// Internal data structure which holds metadata about a keyword argument
|
||||||
|
struct argument_record {
|
||||||
|
const char *name; ///< Argument name
|
||||||
|
const char *descr; ///< Human-readable version of the argument value
|
||||||
|
handle value; ///< Associated Python object
|
||||||
|
bool convert : 1; ///< True if the argument is allowed to convert when loading
|
||||||
|
bool none : 1; ///< True if None is allowed when loading
|
||||||
|
|
||||||
|
argument_record(const char *name, const char *descr, handle value, bool convert, bool none)
|
||||||
|
: name(name), descr(descr), value(value), convert(convert), none(none) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Internal data structure which holds metadata about a bound function (signature, overloads,
|
||||||
|
/// etc.)
|
||||||
|
struct function_record {
|
||||||
|
function_record()
|
||||||
|
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
|
||||||
|
is_operator(false), is_method(false), is_setter(false), has_args(false),
|
||||||
|
has_kwargs(false), prepend(false) {}
|
||||||
|
|
||||||
|
/// Function name
|
||||||
|
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
|
||||||
|
|
||||||
|
// User-specified documentation string
|
||||||
|
char *doc = nullptr;
|
||||||
|
|
||||||
|
/// Human-readable version of the function signature
|
||||||
|
char *signature = nullptr;
|
||||||
|
|
||||||
|
/// List of registered keyword arguments
|
||||||
|
std::vector<argument_record> args;
|
||||||
|
|
||||||
|
/// Pointer to lambda function which converts arguments and performs the actual call
|
||||||
|
handle (*impl)(function_call &) = nullptr;
|
||||||
|
|
||||||
|
/// Storage for the wrapped function pointer and captured data, if any
|
||||||
|
void *data[3] = {};
|
||||||
|
|
||||||
|
/// Pointer to custom destructor for 'data' (if needed)
|
||||||
|
void (*free_data)(function_record *ptr) = nullptr;
|
||||||
|
|
||||||
|
/// Return value policy associated with this function
|
||||||
|
return_value_policy policy = return_value_policy::automatic;
|
||||||
|
|
||||||
|
/// True if name == '__init__'
|
||||||
|
bool is_constructor : 1;
|
||||||
|
|
||||||
|
/// True if this is a new-style `__init__` defined in `detail/init.h`
|
||||||
|
bool is_new_style_constructor : 1;
|
||||||
|
|
||||||
|
/// True if this is a stateless function pointer
|
||||||
|
bool is_stateless : 1;
|
||||||
|
|
||||||
|
/// True if this is an operator (__add__), etc.
|
||||||
|
bool is_operator : 1;
|
||||||
|
|
||||||
|
/// True if this is a method
|
||||||
|
bool is_method : 1;
|
||||||
|
|
||||||
|
/// True if this is a setter
|
||||||
|
bool is_setter : 1;
|
||||||
|
|
||||||
|
/// True if the function has a '*args' argument
|
||||||
|
bool has_args : 1;
|
||||||
|
|
||||||
|
/// True if the function has a '**kwargs' argument
|
||||||
|
bool has_kwargs : 1;
|
||||||
|
|
||||||
|
/// True if this function is to be inserted at the beginning of the overload resolution chain
|
||||||
|
bool prepend : 1;
|
||||||
|
|
||||||
|
/// Number of arguments (including py::args and/or py::kwargs, if present)
|
||||||
|
std::uint16_t nargs;
|
||||||
|
|
||||||
|
/// Number of leading positional arguments, which are terminated by a py::args or py::kwargs
|
||||||
|
/// argument or by a py::kw_only annotation.
|
||||||
|
std::uint16_t nargs_pos = 0;
|
||||||
|
|
||||||
|
/// Number of leading arguments (counted in `nargs`) that are positional-only
|
||||||
|
std::uint16_t nargs_pos_only = 0;
|
||||||
|
|
||||||
|
/// Python method object
|
||||||
|
PyMethodDef *def = nullptr;
|
||||||
|
|
||||||
|
/// Python handle to the parent scope (a class or a module)
|
||||||
|
handle scope;
|
||||||
|
|
||||||
|
/// Python handle to the sibling function representing an overload chain
|
||||||
|
handle sibling;
|
||||||
|
|
||||||
|
/// Pointer to next overload
|
||||||
|
function_record *next = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Special data structure which (temporarily) holds metadata about a bound class
|
||||||
|
struct type_record {
|
||||||
|
PYBIND11_NOINLINE type_record()
|
||||||
|
: multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false),
|
||||||
|
default_holder(true), module_local(false), is_final(false) {}
|
||||||
|
|
||||||
|
/// Handle to the parent scope
|
||||||
|
handle scope;
|
||||||
|
|
||||||
|
/// Name of the class
|
||||||
|
const char *name = nullptr;
|
||||||
|
|
||||||
|
// Pointer to RTTI type_info data structure
|
||||||
|
const std::type_info *type = nullptr;
|
||||||
|
|
||||||
|
/// How large is the underlying C++ type?
|
||||||
|
size_t type_size = 0;
|
||||||
|
|
||||||
|
/// What is the alignment of the underlying C++ type?
|
||||||
|
size_t type_align = 0;
|
||||||
|
|
||||||
|
/// How large is the type's holder?
|
||||||
|
size_t holder_size = 0;
|
||||||
|
|
||||||
|
/// The global operator new can be overridden with a class-specific variant
|
||||||
|
void *(*operator_new)(size_t) = nullptr;
|
||||||
|
|
||||||
|
/// Function pointer to class_<..>::init_instance
|
||||||
|
void (*init_instance)(instance *, const void *) = nullptr;
|
||||||
|
|
||||||
|
/// Function pointer to class_<..>::dealloc
|
||||||
|
void (*dealloc)(detail::value_and_holder &) = nullptr;
|
||||||
|
|
||||||
|
/// List of base classes of the newly created type
|
||||||
|
list bases;
|
||||||
|
|
||||||
|
/// Optional docstring
|
||||||
|
const char *doc = nullptr;
|
||||||
|
|
||||||
|
/// Custom metaclass (optional)
|
||||||
|
handle metaclass;
|
||||||
|
|
||||||
|
/// Custom type setup.
|
||||||
|
custom_type_setup::callback custom_type_setup_callback;
|
||||||
|
|
||||||
|
/// Multiple inheritance marker
|
||||||
|
bool multiple_inheritance : 1;
|
||||||
|
|
||||||
|
/// Does the class manage a __dict__?
|
||||||
|
bool dynamic_attr : 1;
|
||||||
|
|
||||||
|
/// Does the class implement the buffer protocol?
|
||||||
|
bool buffer_protocol : 1;
|
||||||
|
|
||||||
|
/// Is the default (unique_ptr) holder type used?
|
||||||
|
bool default_holder : 1;
|
||||||
|
|
||||||
|
/// Is the class definition local to the module shared object?
|
||||||
|
bool module_local : 1;
|
||||||
|
|
||||||
|
/// Is the class inheritable from python classes?
|
||||||
|
bool is_final : 1;
|
||||||
|
|
||||||
|
PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *) ) {
|
||||||
|
auto *base_info = detail::get_type_info(base, false);
|
||||||
|
if (!base_info) {
|
||||||
|
std::string tname(base.name());
|
||||||
|
detail::clean_type_id(tname);
|
||||||
|
pybind11_fail("generic_type: type \"" + std::string(name)
|
||||||
|
+ "\" referenced unknown base type \"" + tname + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (default_holder != base_info->default_holder) {
|
||||||
|
std::string tname(base.name());
|
||||||
|
detail::clean_type_id(tname);
|
||||||
|
pybind11_fail("generic_type: type \"" + std::string(name) + "\" "
|
||||||
|
+ (default_holder ? "does not have" : "has")
|
||||||
|
+ " a non-default holder type while its base \"" + tname + "\" "
|
||||||
|
+ (base_info->default_holder ? "does not" : "does"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bases.append((PyObject *) base_info->type);
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX < 0x030B0000
|
||||||
|
dynamic_attr |= base_info->type->tp_dictoffset != 0;
|
||||||
|
#else
|
||||||
|
dynamic_attr |= (base_info->type->tp_flags & Py_TPFLAGS_MANAGED_DICT) != 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (caster) {
|
||||||
|
base_info->implicit_casts.emplace_back(type, caster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline function_call::function_call(const function_record &f, handle p) : func(f), parent(p) {
|
||||||
|
args.reserve(f.nargs);
|
||||||
|
args_convert.reserve(f.nargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tag for a new-style `__init__` defined in `detail/init.h`
|
||||||
|
struct is_new_style_constructor {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partial template specializations to process custom attributes provided to
|
||||||
|
* cpp_function_ and class_. These are either used to initialize the respective
|
||||||
|
* fields in the type_record and function_record data structures or executed at
|
||||||
|
* runtime to deal with custom call policies (e.g. keep_alive).
|
||||||
|
*/
|
||||||
|
template <typename T, typename SFINAE = void>
|
||||||
|
struct process_attribute;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct process_attribute_default {
|
||||||
|
/// Default implementation: do nothing
|
||||||
|
static void init(const T &, function_record *) {}
|
||||||
|
static void init(const T &, type_record *) {}
|
||||||
|
static void precall(function_call &) {}
|
||||||
|
static void postcall(function_call &, handle) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process an attribute specifying the function's name
|
||||||
|
template <>
|
||||||
|
struct process_attribute<name> : process_attribute_default<name> {
|
||||||
|
static void init(const name &n, function_record *r) { r->name = const_cast<char *>(n.value); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process an attribute specifying the function's docstring
|
||||||
|
template <>
|
||||||
|
struct process_attribute<doc> : process_attribute_default<doc> {
|
||||||
|
static void init(const doc &n, function_record *r) { r->doc = const_cast<char *>(n.value); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process an attribute specifying the function's docstring (provided as a C-style string)
|
||||||
|
template <>
|
||||||
|
struct process_attribute<const char *> : process_attribute_default<const char *> {
|
||||||
|
static void init(const char *d, function_record *r) { r->doc = const_cast<char *>(d); }
|
||||||
|
static void init(const char *d, type_record *r) { r->doc = d; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct process_attribute<char *> : process_attribute<const char *> {};
|
||||||
|
|
||||||
|
/// Process an attribute indicating the function's return value policy
|
||||||
|
template <>
|
||||||
|
struct process_attribute<return_value_policy> : process_attribute_default<return_value_policy> {
|
||||||
|
static void init(const return_value_policy &p, function_record *r) { r->policy = p; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process an attribute which indicates that this is an overloaded function associated with a
|
||||||
|
/// given sibling
|
||||||
|
template <>
|
||||||
|
struct process_attribute<sibling> : process_attribute_default<sibling> {
|
||||||
|
static void init(const sibling &s, function_record *r) { r->sibling = s.value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process an attribute which indicates that this function is a method
|
||||||
|
template <>
|
||||||
|
struct process_attribute<is_method> : process_attribute_default<is_method> {
|
||||||
|
static void init(const is_method &s, function_record *r) {
|
||||||
|
r->is_method = true;
|
||||||
|
r->scope = s.class_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process an attribute which indicates that this function is a setter
|
||||||
|
template <>
|
||||||
|
struct process_attribute<is_setter> : process_attribute_default<is_setter> {
|
||||||
|
static void init(const is_setter &, function_record *r) { r->is_setter = true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process an attribute which indicates the parent scope of a method
|
||||||
|
template <>
|
||||||
|
struct process_attribute<scope> : process_attribute_default<scope> {
|
||||||
|
static void init(const scope &s, function_record *r) { r->scope = s.value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process an attribute which indicates that this function is an operator
|
||||||
|
template <>
|
||||||
|
struct process_attribute<is_operator> : process_attribute_default<is_operator> {
|
||||||
|
static void init(const is_operator &, function_record *r) { r->is_operator = true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct process_attribute<is_new_style_constructor>
|
||||||
|
: process_attribute_default<is_new_style_constructor> {
|
||||||
|
static void init(const is_new_style_constructor &, function_record *r) {
|
||||||
|
r->is_new_style_constructor = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void check_kw_only_arg(const arg &a, function_record *r) {
|
||||||
|
if (r->args.size() > r->nargs_pos && (!a.name || a.name[0] == '\0')) {
|
||||||
|
pybind11_fail("arg(): cannot specify an unnamed argument after a kw_only() annotation or "
|
||||||
|
"args() argument");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void append_self_arg_if_needed(function_record *r) {
|
||||||
|
if (r->is_method && r->args.empty()) {
|
||||||
|
r->args.emplace_back("self", nullptr, handle(), /*convert=*/true, /*none=*/false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process a keyword argument attribute (*without* a default value)
|
||||||
|
template <>
|
||||||
|
struct process_attribute<arg> : process_attribute_default<arg> {
|
||||||
|
static void init(const arg &a, function_record *r) {
|
||||||
|
append_self_arg_if_needed(r);
|
||||||
|
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);
|
||||||
|
|
||||||
|
check_kw_only_arg(a, r);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process a keyword argument attribute (*with* a default value)
|
||||||
|
template <>
|
||||||
|
struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
||||||
|
static void init(const arg_v &a, function_record *r) {
|
||||||
|
if (r->is_method && r->args.empty()) {
|
||||||
|
r->args.emplace_back(
|
||||||
|
"self", /*descr=*/nullptr, /*parent=*/handle(), /*convert=*/true, /*none=*/false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!a.value) {
|
||||||
|
#if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||||
|
std::string descr("'");
|
||||||
|
if (a.name) {
|
||||||
|
descr += std::string(a.name) + ": ";
|
||||||
|
}
|
||||||
|
descr += a.type + "'";
|
||||||
|
if (r->is_method) {
|
||||||
|
if (r->name) {
|
||||||
|
descr += " in method '" + (std::string) str(r->scope) + "."
|
||||||
|
+ (std::string) r->name + "'";
|
||||||
|
} else {
|
||||||
|
descr += " in method of '" + (std::string) str(r->scope) + "'";
|
||||||
|
}
|
||||||
|
} else if (r->name) {
|
||||||
|
descr += " in function '" + (std::string) r->name + "'";
|
||||||
|
}
|
||||||
|
pybind11_fail("arg(): could not convert default argument " + descr
|
||||||
|
+ " into a Python object (type not registered yet?)");
|
||||||
|
#else
|
||||||
|
pybind11_fail("arg(): could not convert default argument "
|
||||||
|
"into a Python object (type not registered yet?). "
|
||||||
|
"#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for "
|
||||||
|
"more information.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
|
||||||
|
|
||||||
|
check_kw_only_arg(a, r);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process a keyword-only-arguments-follow pseudo argument
|
||||||
|
template <>
|
||||||
|
struct process_attribute<kw_only> : process_attribute_default<kw_only> {
|
||||||
|
static void init(const kw_only &, function_record *r) {
|
||||||
|
append_self_arg_if_needed(r);
|
||||||
|
if (r->has_args && r->nargs_pos != static_cast<std::uint16_t>(r->args.size())) {
|
||||||
|
pybind11_fail("Mismatched args() and kw_only(): they must occur at the same relative "
|
||||||
|
"argument location (or omit kw_only() entirely)");
|
||||||
|
}
|
||||||
|
r->nargs_pos = static_cast<std::uint16_t>(r->args.size());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process a positional-only-argument maker
|
||||||
|
template <>
|
||||||
|
struct process_attribute<pos_only> : process_attribute_default<pos_only> {
|
||||||
|
static void init(const pos_only &, function_record *r) {
|
||||||
|
append_self_arg_if_needed(r);
|
||||||
|
r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size());
|
||||||
|
if (r->nargs_pos_only > r->nargs_pos) {
|
||||||
|
pybind11_fail("pos_only(): cannot follow a py::args() argument");
|
||||||
|
}
|
||||||
|
// It also can't follow a kw_only, but a static_assert in pybind11.h checks that
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process a parent class attribute. Single inheritance only (class_ itself already guarantees
|
||||||
|
/// that)
|
||||||
|
template <typename T>
|
||||||
|
struct process_attribute<T, enable_if_t<is_pyobject<T>::value>>
|
||||||
|
: process_attribute_default<handle> {
|
||||||
|
static void init(const handle &h, type_record *r) { r->bases.append(h); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process a parent class attribute (deprecated, does not support multiple inheritance)
|
||||||
|
template <typename T>
|
||||||
|
struct process_attribute<base<T>> : process_attribute_default<base<T>> {
|
||||||
|
static void init(const base<T> &, type_record *r) { r->add_base(typeid(T), nullptr); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process a multiple inheritance attribute
|
||||||
|
template <>
|
||||||
|
struct process_attribute<multiple_inheritance> : process_attribute_default<multiple_inheritance> {
|
||||||
|
static void init(const multiple_inheritance &, type_record *r) {
|
||||||
|
r->multiple_inheritance = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr> {
|
||||||
|
static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct process_attribute<custom_type_setup> {
|
||||||
|
static void init(const custom_type_setup &value, type_record *r) {
|
||||||
|
r->custom_type_setup_callback = value.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct process_attribute<is_final> : process_attribute_default<is_final> {
|
||||||
|
static void init(const is_final &, type_record *r) { r->is_final = true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct process_attribute<buffer_protocol> : process_attribute_default<buffer_protocol> {
|
||||||
|
static void init(const buffer_protocol &, type_record *r) { r->buffer_protocol = true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct process_attribute<metaclass> : process_attribute_default<metaclass> {
|
||||||
|
static void init(const metaclass &m, type_record *r) { r->metaclass = m.value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct process_attribute<module_local> : process_attribute_default<module_local> {
|
||||||
|
static void init(const module_local &l, type_record *r) { r->module_local = l.value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process a 'prepend' attribute, putting this at the beginning of the overload chain
|
||||||
|
template <>
|
||||||
|
struct process_attribute<prepend> : process_attribute_default<prepend> {
|
||||||
|
static void init(const prepend &, function_record *r) { r->prepend = true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Process an 'arithmetic' attribute for enums (does nothing here)
|
||||||
|
template <>
|
||||||
|
struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {};
|
||||||
|
|
||||||
|
template <typename... Ts>
|
||||||
|
struct process_attribute<call_guard<Ts...>> : process_attribute_default<call_guard<Ts...>> {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a keep_alive call policy -- invokes keep_alive_impl during the
|
||||||
|
* pre-call handler if both Nurse, Patient != 0 and use the post-call handler
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
template <size_t Nurse, size_t Patient>
|
||||||
|
struct process_attribute<keep_alive<Nurse, Patient>>
|
||||||
|
: public process_attribute_default<keep_alive<Nurse, Patient>> {
|
||||||
|
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0>
|
||||||
|
static void precall(function_call &call) {
|
||||||
|
keep_alive_impl(Nurse, Patient, call, handle());
|
||||||
|
}
|
||||||
|
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0>
|
||||||
|
static void postcall(function_call &, handle) {}
|
||||||
|
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0>
|
||||||
|
static void precall(function_call &) {}
|
||||||
|
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0>
|
||||||
|
static void postcall(function_call &call, handle ret) {
|
||||||
|
keep_alive_impl(Nurse, Patient, call, ret);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Recursively iterate over variadic template arguments
|
||||||
|
template <typename... Args>
|
||||||
|
struct process_attributes {
|
||||||
|
static void init(const Args &...args, function_record *r) {
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(r);
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(r);
|
||||||
|
using expander = int[];
|
||||||
|
(void) expander{
|
||||||
|
0, ((void) process_attribute<typename std::decay<Args>::type>::init(args, r), 0)...};
|
||||||
|
}
|
||||||
|
static void init(const Args &...args, type_record *r) {
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(r);
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(r);
|
||||||
|
using expander = int[];
|
||||||
|
(void) expander{0,
|
||||||
|
(process_attribute<typename std::decay<Args>::type>::init(args, r), 0)...};
|
||||||
|
}
|
||||||
|
static void precall(function_call &call) {
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(call);
|
||||||
|
using expander = int[];
|
||||||
|
(void) expander{0,
|
||||||
|
(process_attribute<typename std::decay<Args>::type>::precall(call), 0)...};
|
||||||
|
}
|
||||||
|
static void postcall(function_call &call, handle fn_ret) {
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(call, fn_ret);
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(fn_ret);
|
||||||
|
using expander = int[];
|
||||||
|
(void) expander{
|
||||||
|
0, (process_attribute<typename std::decay<Args>::type>::postcall(call, fn_ret), 0)...};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using is_call_guard = is_instantiation<call_guard, T>;
|
||||||
|
|
||||||
|
/// Extract the ``type`` from the first `call_guard` in `Extras...` (or `void_type` if none found)
|
||||||
|
template <typename... Extra>
|
||||||
|
using extract_guard_t = typename exactly_one_t<is_call_guard, call_guard<>, Extra...>::type;
|
||||||
|
|
||||||
|
/// Check the number of named arguments at compile time
|
||||||
|
template <typename... Extra,
|
||||||
|
size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...),
|
||||||
|
size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)>
|
||||||
|
constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) {
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(nargs, has_args, has_kwargs);
|
||||||
|
return named == 0 || (self + named + size_t(has_args) + size_t(has_kwargs)) == nargs;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
208
3rdparty/pybind11/include/pybind11/buffer_info.h
vendored
Normal file
208
3rdparty/pybind11/include/pybind11/buffer_info.h
vendored
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
pybind11/buffer_info.h: Python buffer object interface
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "detail/common.h"
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
// Default, C-style strides
|
||||||
|
inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
|
||||||
|
auto ndim = shape.size();
|
||||||
|
std::vector<ssize_t> strides(ndim, itemsize);
|
||||||
|
if (ndim > 0) {
|
||||||
|
for (size_t i = ndim - 1; i > 0; --i) {
|
||||||
|
strides[i - 1] = strides[i] * shape[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strides;
|
||||||
|
}
|
||||||
|
|
||||||
|
// F-style strides; default when constructing an array_t with `ExtraFlags & f_style`
|
||||||
|
inline std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
|
||||||
|
auto ndim = shape.size();
|
||||||
|
std::vector<ssize_t> strides(ndim, itemsize);
|
||||||
|
for (size_t i = 1; i < ndim; ++i) {
|
||||||
|
strides[i] = strides[i - 1] * shape[i - 1];
|
||||||
|
}
|
||||||
|
return strides;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename SFINAE = void>
|
||||||
|
struct compare_buffer_info;
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
/// Information record describing a Python buffer object
|
||||||
|
struct buffer_info {
|
||||||
|
void *ptr = nullptr; // Pointer to the underlying storage
|
||||||
|
ssize_t itemsize = 0; // Size of individual items in bytes
|
||||||
|
ssize_t size = 0; // Total number of entries
|
||||||
|
std::string format; // For homogeneous buffers, this should be set to
|
||||||
|
// format_descriptor<T>::format()
|
||||||
|
ssize_t ndim = 0; // Number of dimensions
|
||||||
|
std::vector<ssize_t> shape; // Shape of the tensor (1 entry per dimension)
|
||||||
|
std::vector<ssize_t> strides; // Number of bytes between adjacent entries
|
||||||
|
// (for each per dimension)
|
||||||
|
bool readonly = false; // flag to indicate if the underlying storage may be written to
|
||||||
|
|
||||||
|
buffer_info() = default;
|
||||||
|
|
||||||
|
buffer_info(void *ptr,
|
||||||
|
ssize_t itemsize,
|
||||||
|
const std::string &format,
|
||||||
|
ssize_t ndim,
|
||||||
|
detail::any_container<ssize_t> shape_in,
|
||||||
|
detail::any_container<ssize_t> strides_in,
|
||||||
|
bool readonly = false)
|
||||||
|
: ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
|
||||||
|
shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) {
|
||||||
|
if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size()) {
|
||||||
|
pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < (size_t) ndim; ++i) {
|
||||||
|
size *= shape[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
buffer_info(T *ptr,
|
||||||
|
detail::any_container<ssize_t> shape_in,
|
||||||
|
detail::any_container<ssize_t> strides_in,
|
||||||
|
bool readonly = false)
|
||||||
|
: buffer_info(private_ctr_tag(),
|
||||||
|
ptr,
|
||||||
|
sizeof(T),
|
||||||
|
format_descriptor<T>::format(),
|
||||||
|
static_cast<ssize_t>(shape_in->size()),
|
||||||
|
std::move(shape_in),
|
||||||
|
std::move(strides_in),
|
||||||
|
readonly) {}
|
||||||
|
|
||||||
|
buffer_info(void *ptr,
|
||||||
|
ssize_t itemsize,
|
||||||
|
const std::string &format,
|
||||||
|
ssize_t size,
|
||||||
|
bool readonly = false)
|
||||||
|
: buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
buffer_info(T *ptr, ssize_t size, bool readonly = false)
|
||||||
|
: buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size, readonly) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
buffer_info(const T *ptr, ssize_t size, bool readonly = true)
|
||||||
|
: buffer_info(
|
||||||
|
const_cast<T *>(ptr), sizeof(T), format_descriptor<T>::format(), size, readonly) {}
|
||||||
|
|
||||||
|
explicit buffer_info(Py_buffer *view, bool ownview = true)
|
||||||
|
: buffer_info(
|
||||||
|
view->buf,
|
||||||
|
view->itemsize,
|
||||||
|
view->format,
|
||||||
|
view->ndim,
|
||||||
|
{view->shape, view->shape + view->ndim},
|
||||||
|
/* Though buffer::request() requests PyBUF_STRIDES, ctypes objects
|
||||||
|
* ignore this flag and return a view with NULL strides.
|
||||||
|
* When strides are NULL, build them manually. */
|
||||||
|
view->strides
|
||||||
|
? std::vector<ssize_t>(view->strides, view->strides + view->ndim)
|
||||||
|
: detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize),
|
||||||
|
(view->readonly != 0)) {
|
||||||
|
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||||
|
this->m_view = view;
|
||||||
|
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||||
|
this->ownview = ownview;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_info(const buffer_info &) = delete;
|
||||||
|
buffer_info &operator=(const buffer_info &) = delete;
|
||||||
|
|
||||||
|
buffer_info(buffer_info &&other) noexcept { (*this) = std::move(other); }
|
||||||
|
|
||||||
|
buffer_info &operator=(buffer_info &&rhs) noexcept {
|
||||||
|
ptr = rhs.ptr;
|
||||||
|
itemsize = rhs.itemsize;
|
||||||
|
size = rhs.size;
|
||||||
|
format = std::move(rhs.format);
|
||||||
|
ndim = rhs.ndim;
|
||||||
|
shape = std::move(rhs.shape);
|
||||||
|
strides = std::move(rhs.strides);
|
||||||
|
std::swap(m_view, rhs.m_view);
|
||||||
|
std::swap(ownview, rhs.ownview);
|
||||||
|
readonly = rhs.readonly;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~buffer_info() {
|
||||||
|
if (m_view && ownview) {
|
||||||
|
PyBuffer_Release(m_view);
|
||||||
|
delete m_view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_buffer *view() const { return m_view; }
|
||||||
|
Py_buffer *&view() { return m_view; }
|
||||||
|
|
||||||
|
/* True if the buffer item type is equivalent to `T`. */
|
||||||
|
// To define "equivalent" by example:
|
||||||
|
// `buffer_info::item_type_is_equivalent_to<int>(b)` and
|
||||||
|
// `buffer_info::item_type_is_equivalent_to<long>(b)` may both be true
|
||||||
|
// on some platforms, but `int` and `unsigned` will never be equivalent.
|
||||||
|
// For the ground truth, please inspect `detail::compare_buffer_info<>`.
|
||||||
|
template <typename T>
|
||||||
|
bool item_type_is_equivalent_to() const {
|
||||||
|
return detail::compare_buffer_info<T>::compare(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct private_ctr_tag {};
|
||||||
|
|
||||||
|
buffer_info(private_ctr_tag,
|
||||||
|
void *ptr,
|
||||||
|
ssize_t itemsize,
|
||||||
|
const std::string &format,
|
||||||
|
ssize_t ndim,
|
||||||
|
detail::any_container<ssize_t> &&shape_in,
|
||||||
|
detail::any_container<ssize_t> &&strides_in,
|
||||||
|
bool readonly)
|
||||||
|
: buffer_info(
|
||||||
|
ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) {}
|
||||||
|
|
||||||
|
Py_buffer *m_view = nullptr;
|
||||||
|
bool ownview = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <typename T, typename SFINAE>
|
||||||
|
struct compare_buffer_info {
|
||||||
|
static bool compare(const buffer_info &b) {
|
||||||
|
// NOLINTNEXTLINE(bugprone-sizeof-expression) Needed for `PyObject *`
|
||||||
|
return b.format == format_descriptor<T>::format() && b.itemsize == (ssize_t) sizeof(T);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> {
|
||||||
|
static bool compare(const buffer_info &b) {
|
||||||
|
return (size_t) b.itemsize == sizeof(T)
|
||||||
|
&& (b.format == format_descriptor<T>::value
|
||||||
|
|| ((sizeof(T) == sizeof(long))
|
||||||
|
&& b.format == (std::is_unsigned<T>::value ? "L" : "l"))
|
||||||
|
|| ((sizeof(T) == sizeof(size_t))
|
||||||
|
&& b.format == (std::is_unsigned<T>::value ? "N" : "n")));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
1704
3rdparty/pybind11/include/pybind11/cast.h
vendored
Normal file
1704
3rdparty/pybind11/include/pybind11/cast.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
225
3rdparty/pybind11/include/pybind11/chrono.h
vendored
Normal file
225
3rdparty/pybind11/include/pybind11/chrono.h
vendored
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
pybind11/chrono.h: Transparent conversion between std::chrono and python's datetime
|
||||||
|
|
||||||
|
Copyright (c) 2016 Trent Houliston <trent@houliston.me> and
|
||||||
|
Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pybind11.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cmath>
|
||||||
|
#include <ctime>
|
||||||
|
#include <datetime.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <typename type>
|
||||||
|
class duration_caster {
|
||||||
|
public:
|
||||||
|
using rep = typename type::rep;
|
||||||
|
using period = typename type::period;
|
||||||
|
|
||||||
|
// signed 25 bits required by the standard.
|
||||||
|
using days = std::chrono::duration<int_least32_t, std::ratio<86400>>;
|
||||||
|
|
||||||
|
bool load(handle src, bool) {
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
// Lazy initialise the PyDateTime import
|
||||||
|
if (!PyDateTimeAPI) {
|
||||||
|
PyDateTime_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!src) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// If invoked with datetime.delta object
|
||||||
|
if (PyDelta_Check(src.ptr())) {
|
||||||
|
value = type(duration_cast<duration<rep, period>>(
|
||||||
|
days(PyDateTime_DELTA_GET_DAYS(src.ptr()))
|
||||||
|
+ seconds(PyDateTime_DELTA_GET_SECONDS(src.ptr()))
|
||||||
|
+ microseconds(PyDateTime_DELTA_GET_MICROSECONDS(src.ptr()))));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If invoked with a float we assume it is seconds and convert
|
||||||
|
if (PyFloat_Check(src.ptr())) {
|
||||||
|
value = type(duration_cast<duration<rep, period>>(
|
||||||
|
duration<double>(PyFloat_AsDouble(src.ptr()))));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a duration just return it back
|
||||||
|
static const std::chrono::duration<rep, period> &
|
||||||
|
get_duration(const std::chrono::duration<rep, period> &src) {
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a time_point get the time_since_epoch
|
||||||
|
template <typename Clock>
|
||||||
|
static std::chrono::duration<rep, period>
|
||||||
|
get_duration(const std::chrono::time_point<Clock, std::chrono::duration<rep, period>> &src) {
|
||||||
|
return src.time_since_epoch();
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(const type &src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
// Use overloaded function to get our duration from our source
|
||||||
|
// Works out if it is a duration or time_point and get the duration
|
||||||
|
auto d = get_duration(src);
|
||||||
|
|
||||||
|
// Lazy initialise the PyDateTime import
|
||||||
|
if (!PyDateTimeAPI) {
|
||||||
|
PyDateTime_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declare these special duration types so the conversions happen with the correct
|
||||||
|
// primitive types (int)
|
||||||
|
using dd_t = duration<int, std::ratio<86400>>;
|
||||||
|
using ss_t = duration<int, std::ratio<1>>;
|
||||||
|
using us_t = duration<int, std::micro>;
|
||||||
|
|
||||||
|
auto dd = duration_cast<dd_t>(d);
|
||||||
|
auto subd = d - dd;
|
||||||
|
auto ss = duration_cast<ss_t>(subd);
|
||||||
|
auto us = duration_cast<us_t>(subd - ss);
|
||||||
|
return PyDelta_FromDSU(dd.count(), ss.count(), us.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(type, const_name("datetime.timedelta"));
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::tm *localtime_thread_safe(const std::time_t *time, std::tm *buf) {
|
||||||
|
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || defined(_MSC_VER)
|
||||||
|
if (localtime_s(buf, time))
|
||||||
|
return nullptr;
|
||||||
|
return buf;
|
||||||
|
#else
|
||||||
|
static std::mutex mtx;
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
std::tm *tm_ptr = std::localtime(time);
|
||||||
|
if (tm_ptr != nullptr) {
|
||||||
|
*buf = *tm_ptr;
|
||||||
|
}
|
||||||
|
return tm_ptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is for casting times on the system clock into datetime.datetime instances
|
||||||
|
template <typename Duration>
|
||||||
|
class type_caster<std::chrono::time_point<std::chrono::system_clock, Duration>> {
|
||||||
|
public:
|
||||||
|
using type = std::chrono::time_point<std::chrono::system_clock, Duration>;
|
||||||
|
bool load(handle src, bool) {
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
// Lazy initialise the PyDateTime import
|
||||||
|
if (!PyDateTimeAPI) {
|
||||||
|
PyDateTime_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!src) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tm cal;
|
||||||
|
microseconds msecs;
|
||||||
|
|
||||||
|
if (PyDateTime_Check(src.ptr())) {
|
||||||
|
cal.tm_sec = PyDateTime_DATE_GET_SECOND(src.ptr());
|
||||||
|
cal.tm_min = PyDateTime_DATE_GET_MINUTE(src.ptr());
|
||||||
|
cal.tm_hour = PyDateTime_DATE_GET_HOUR(src.ptr());
|
||||||
|
cal.tm_mday = PyDateTime_GET_DAY(src.ptr());
|
||||||
|
cal.tm_mon = PyDateTime_GET_MONTH(src.ptr()) - 1;
|
||||||
|
cal.tm_year = PyDateTime_GET_YEAR(src.ptr()) - 1900;
|
||||||
|
cal.tm_isdst = -1;
|
||||||
|
msecs = microseconds(PyDateTime_DATE_GET_MICROSECOND(src.ptr()));
|
||||||
|
} else if (PyDate_Check(src.ptr())) {
|
||||||
|
cal.tm_sec = 0;
|
||||||
|
cal.tm_min = 0;
|
||||||
|
cal.tm_hour = 0;
|
||||||
|
cal.tm_mday = PyDateTime_GET_DAY(src.ptr());
|
||||||
|
cal.tm_mon = PyDateTime_GET_MONTH(src.ptr()) - 1;
|
||||||
|
cal.tm_year = PyDateTime_GET_YEAR(src.ptr()) - 1900;
|
||||||
|
cal.tm_isdst = -1;
|
||||||
|
msecs = microseconds(0);
|
||||||
|
} else if (PyTime_Check(src.ptr())) {
|
||||||
|
cal.tm_sec = PyDateTime_TIME_GET_SECOND(src.ptr());
|
||||||
|
cal.tm_min = PyDateTime_TIME_GET_MINUTE(src.ptr());
|
||||||
|
cal.tm_hour = PyDateTime_TIME_GET_HOUR(src.ptr());
|
||||||
|
cal.tm_mday = 1; // This date (day, month, year) = (1, 0, 70)
|
||||||
|
cal.tm_mon = 0; // represents 1-Jan-1970, which is the first
|
||||||
|
cal.tm_year = 70; // earliest available date for Python's datetime
|
||||||
|
cal.tm_isdst = -1;
|
||||||
|
msecs = microseconds(PyDateTime_TIME_GET_MICROSECOND(src.ptr()));
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = time_point_cast<Duration>(system_clock::from_time_t(std::mktime(&cal)) + msecs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(const std::chrono::time_point<std::chrono::system_clock, Duration> &src,
|
||||||
|
return_value_policy /* policy */,
|
||||||
|
handle /* parent */) {
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
// Lazy initialise the PyDateTime import
|
||||||
|
if (!PyDateTimeAPI) {
|
||||||
|
PyDateTime_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get out microseconds, and make sure they are positive, to avoid bug in eastern
|
||||||
|
// hemisphere time zones (cfr. https://github.com/pybind/pybind11/issues/2417)
|
||||||
|
using us_t = duration<int, std::micro>;
|
||||||
|
auto us = duration_cast<us_t>(src.time_since_epoch() % seconds(1));
|
||||||
|
if (us.count() < 0) {
|
||||||
|
us += seconds(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtract microseconds BEFORE `system_clock::to_time_t`, because:
|
||||||
|
// > If std::time_t has lower precision, it is implementation-defined whether the value is
|
||||||
|
// rounded or truncated. (https://en.cppreference.com/w/cpp/chrono/system_clock/to_time_t)
|
||||||
|
std::time_t tt
|
||||||
|
= system_clock::to_time_t(time_point_cast<system_clock::duration>(src - us));
|
||||||
|
|
||||||
|
std::tm localtime;
|
||||||
|
std::tm *localtime_ptr = localtime_thread_safe(&tt, &localtime);
|
||||||
|
if (!localtime_ptr) {
|
||||||
|
throw cast_error("Unable to represent system_clock in local time");
|
||||||
|
}
|
||||||
|
return PyDateTime_FromDateAndTime(localtime.tm_year + 1900,
|
||||||
|
localtime.tm_mon + 1,
|
||||||
|
localtime.tm_mday,
|
||||||
|
localtime.tm_hour,
|
||||||
|
localtime.tm_min,
|
||||||
|
localtime.tm_sec,
|
||||||
|
us.count());
|
||||||
|
}
|
||||||
|
PYBIND11_TYPE_CASTER(type, const_name("datetime.datetime"));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Other clocks that are not the system clock are not measured as datetime.datetime objects
|
||||||
|
// since they are not measured on calendar time. So instead we just make them timedeltas
|
||||||
|
// Or if they have passed us a time as a float we convert that
|
||||||
|
template <typename Clock, typename Duration>
|
||||||
|
class type_caster<std::chrono::time_point<Clock, Duration>>
|
||||||
|
: public duration_caster<std::chrono::time_point<Clock, Duration>> {};
|
||||||
|
|
||||||
|
template <typename Rep, typename Period>
|
||||||
|
class type_caster<std::chrono::duration<Rep, Period>>
|
||||||
|
: public duration_caster<std::chrono::duration<Rep, Period>> {};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
2
3rdparty/pybind11/include/pybind11/common.h
vendored
Normal file
2
3rdparty/pybind11/include/pybind11/common.h
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#include "detail/common.h"
|
||||||
|
#warning "Including 'common.h' is deprecated. It will be removed in v3.0. Use 'pybind11.h'."
|
74
3rdparty/pybind11/include/pybind11/complex.h
vendored
Normal file
74
3rdparty/pybind11/include/pybind11/complex.h
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
pybind11/complex.h: Complex number support
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pybind11.h"
|
||||||
|
|
||||||
|
#include <complex>
|
||||||
|
|
||||||
|
/// glibc defines I as a macro which breaks things, e.g., boost template names
|
||||||
|
#ifdef I
|
||||||
|
# undef I
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct format_descriptor<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> {
|
||||||
|
static constexpr const char c = format_descriptor<T>::c;
|
||||||
|
static constexpr const char value[3] = {'Z', c, '\0'};
|
||||||
|
static std::string format() { return std::string(value); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef PYBIND11_CPP17
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr const char
|
||||||
|
format_descriptor<std::complex<T>,
|
||||||
|
detail::enable_if_t<std::is_floating_point<T>::value>>::value[3];
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_fmt_numeric<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> {
|
||||||
|
static constexpr bool value = true;
|
||||||
|
static constexpr int index = is_fmt_numeric<T>::index + 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class type_caster<std::complex<T>> {
|
||||||
|
public:
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
if (!src) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!convert && !PyComplex_Check(src.ptr())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Py_complex result = PyComplex_AsCComplex(src.ptr());
|
||||||
|
if (result.real == -1.0 && PyErr_Occurred()) {
|
||||||
|
PyErr_Clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value = std::complex<T>((T) result.real, (T) result.imag);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle
|
||||||
|
cast(const std::complex<T> &src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
return PyComplex_FromDoubles((double) src.real(), (double) src.imag());
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(std::complex<T>, const_name("complex"));
|
||||||
|
};
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
743
3rdparty/pybind11/include/pybind11/detail/class.h
vendored
Normal file
743
3rdparty/pybind11/include/pybind11/detail/class.h
vendored
Normal file
@ -0,0 +1,743 @@
|
|||||||
|
/*
|
||||||
|
pybind11/detail/class.h: Python C API implementation details for py::class_
|
||||||
|
|
||||||
|
Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../attr.h"
|
||||||
|
#include "../options.h"
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
#if !defined(PYPY_VERSION)
|
||||||
|
# define PYBIND11_BUILTIN_QUALNAME
|
||||||
|
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj)
|
||||||
|
#else
|
||||||
|
// In PyPy, we still set __qualname__ so that we can produce reliable function type
|
||||||
|
// signatures; in CPython this macro expands to nothing:
|
||||||
|
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) \
|
||||||
|
setattr((PyObject *) obj, "__qualname__", nameobj)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline std::string get_fully_qualified_tp_name(PyTypeObject *type) {
|
||||||
|
#if !defined(PYPY_VERSION)
|
||||||
|
return type->tp_name;
|
||||||
|
#else
|
||||||
|
auto module_name = handle((PyObject *) type).attr("__module__").cast<std::string>();
|
||||||
|
if (module_name == PYBIND11_BUILTINS_MODULE)
|
||||||
|
return type->tp_name;
|
||||||
|
else
|
||||||
|
return std::move(module_name) + "." + type->tp_name;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PyTypeObject *type_incref(PyTypeObject *type) {
|
||||||
|
Py_INCREF(type);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(PYPY_VERSION)
|
||||||
|
|
||||||
|
/// `pybind11_static_property.__get__()`: Always pass the class instead of the instance.
|
||||||
|
extern "C" inline PyObject *pybind11_static_get(PyObject *self, PyObject * /*ob*/, PyObject *cls) {
|
||||||
|
return PyProperty_Type.tp_descr_get(self, cls, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `pybind11_static_property.__set__()`: Just like the above `__get__()`.
|
||||||
|
extern "C" inline int pybind11_static_set(PyObject *self, PyObject *obj, PyObject *value) {
|
||||||
|
PyObject *cls = PyType_Check(obj) ? obj : (PyObject *) Py_TYPE(obj);
|
||||||
|
return PyProperty_Type.tp_descr_set(self, cls, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward declaration to use in `make_static_property_type()`
|
||||||
|
inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type);
|
||||||
|
|
||||||
|
/** A `static_property` is the same as a `property` but the `__get__()` and `__set__()`
|
||||||
|
methods are modified to always use the object type instead of a concrete instance.
|
||||||
|
Return value: New reference. */
|
||||||
|
inline PyTypeObject *make_static_property_type() {
|
||||||
|
constexpr auto *name = "pybind11_static_property";
|
||||||
|
auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(name));
|
||||||
|
|
||||||
|
/* Danger zone: from now (and until PyType_Ready), make sure to
|
||||||
|
issue no Python C API calls which could potentially invoke the
|
||||||
|
garbage collector (the GC will call type_traverse(), which will in
|
||||||
|
turn find the newly constructed type in an invalid state) */
|
||||||
|
auto *heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
|
||||||
|
if (!heap_type) {
|
||||||
|
pybind11_fail("make_static_property_type(): error allocating type!");
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_type->ht_name = name_obj.inc_ref().ptr();
|
||||||
|
# ifdef PYBIND11_BUILTIN_QUALNAME
|
||||||
|
heap_type->ht_qualname = name_obj.inc_ref().ptr();
|
||||||
|
# endif
|
||||||
|
|
||||||
|
auto *type = &heap_type->ht_type;
|
||||||
|
type->tp_name = name;
|
||||||
|
type->tp_base = type_incref(&PyProperty_Type);
|
||||||
|
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
|
||||||
|
type->tp_descr_get = pybind11_static_get;
|
||||||
|
type->tp_descr_set = pybind11_static_set;
|
||||||
|
|
||||||
|
if (PyType_Ready(type) < 0) {
|
||||||
|
pybind11_fail("make_static_property_type(): failure in PyType_Ready()!");
|
||||||
|
}
|
||||||
|
|
||||||
|
# if PY_VERSION_HEX >= 0x030C0000
|
||||||
|
// PRE 3.12 FEATURE FREEZE. PLEASE REVIEW AFTER FREEZE.
|
||||||
|
// Since Python-3.12 property-derived types are required to
|
||||||
|
// have dynamic attributes (to set `__doc__`)
|
||||||
|
enable_dynamic_attributes(heap_type);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
|
||||||
|
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // PYPY
|
||||||
|
|
||||||
|
/** PyPy has some issues with the above C API, so we evaluate Python code instead.
|
||||||
|
This function will only be called once so performance isn't really a concern.
|
||||||
|
Return value: New reference. */
|
||||||
|
inline PyTypeObject *make_static_property_type() {
|
||||||
|
auto d = dict();
|
||||||
|
PyObject *result = PyRun_String(R"(\
|
||||||
|
class pybind11_static_property(property):
|
||||||
|
def __get__(self, obj, cls):
|
||||||
|
return property.__get__(self, cls, cls)
|
||||||
|
|
||||||
|
def __set__(self, obj, value):
|
||||||
|
cls = obj if isinstance(obj, type) else type(obj)
|
||||||
|
property.__set__(self, cls, value)
|
||||||
|
)",
|
||||||
|
Py_file_input,
|
||||||
|
d.ptr(),
|
||||||
|
d.ptr());
|
||||||
|
if (result == nullptr)
|
||||||
|
throw error_already_set();
|
||||||
|
Py_DECREF(result);
|
||||||
|
return (PyTypeObject *) d["pybind11_static_property"].cast<object>().release().ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PYPY
|
||||||
|
|
||||||
|
/** Types with static properties need to handle `Type.static_prop = x` in a specific way.
|
||||||
|
By default, Python replaces the `static_property` itself, but for wrapped C++ types
|
||||||
|
we need to call `static_property.__set__()` in order to propagate the new value to
|
||||||
|
the underlying C++ data structure. */
|
||||||
|
extern "C" inline int pybind11_meta_setattro(PyObject *obj, PyObject *name, PyObject *value) {
|
||||||
|
// Use `_PyType_Lookup()` instead of `PyObject_GetAttr()` in order to get the raw
|
||||||
|
// descriptor (`property`) instead of calling `tp_descr_get` (`property.__get__()`).
|
||||||
|
PyObject *descr = _PyType_Lookup((PyTypeObject *) obj, name);
|
||||||
|
|
||||||
|
// The following assignment combinations are possible:
|
||||||
|
// 1. `Type.static_prop = value` --> descr_set: `Type.static_prop.__set__(value)`
|
||||||
|
// 2. `Type.static_prop = other_static_prop` --> setattro: replace existing `static_prop`
|
||||||
|
// 3. `Type.regular_attribute = value` --> setattro: regular attribute assignment
|
||||||
|
auto *const static_prop = (PyObject *) get_internals().static_property_type;
|
||||||
|
const auto call_descr_set = (descr != nullptr) && (value != nullptr)
|
||||||
|
&& (PyObject_IsInstance(descr, static_prop) != 0)
|
||||||
|
&& (PyObject_IsInstance(value, static_prop) == 0);
|
||||||
|
if (call_descr_set) {
|
||||||
|
// Call `static_property.__set__()` instead of replacing the `static_property`.
|
||||||
|
#if !defined(PYPY_VERSION)
|
||||||
|
return Py_TYPE(descr)->tp_descr_set(descr, obj, value);
|
||||||
|
#else
|
||||||
|
if (PyObject *result = PyObject_CallMethod(descr, "__set__", "OO", obj, value)) {
|
||||||
|
Py_DECREF(result);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
// Replace existing attribute.
|
||||||
|
return PyType_Type.tp_setattro(obj, name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Python 3's PyInstanceMethod_Type hides itself via its tp_descr_get, which prevents aliasing
|
||||||
|
* methods via cls.attr("m2") = cls.attr("m1"): instead the tp_descr_get returns a plain function,
|
||||||
|
* when called on a class, or a PyMethod, when called on an instance. Override that behaviour here
|
||||||
|
* to do a special case bypass for PyInstanceMethod_Types.
|
||||||
|
*/
|
||||||
|
extern "C" inline PyObject *pybind11_meta_getattro(PyObject *obj, PyObject *name) {
|
||||||
|
PyObject *descr = _PyType_Lookup((PyTypeObject *) obj, name);
|
||||||
|
if (descr && PyInstanceMethod_Check(descr)) {
|
||||||
|
Py_INCREF(descr);
|
||||||
|
return descr;
|
||||||
|
}
|
||||||
|
return PyType_Type.tp_getattro(obj, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// metaclass `__call__` function that is used to create all pybind11 objects.
|
||||||
|
extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, PyObject *kwargs) {
|
||||||
|
|
||||||
|
// use the default metaclass call to create/initialize the object
|
||||||
|
PyObject *self = PyType_Type.tp_call(type, args, kwargs);
|
||||||
|
if (self == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This must be a pybind11 instance
|
||||||
|
auto *instance = reinterpret_cast<detail::instance *>(self);
|
||||||
|
|
||||||
|
// Ensure that the base __init__ function(s) were called
|
||||||
|
for (const auto &vh : values_and_holders(instance)) {
|
||||||
|
if (!vh.holder_constructed()) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"%.200s.__init__() must be called when overriding __init__",
|
||||||
|
get_fully_qualified_tp_name(vh.type->type).c_str());
|
||||||
|
Py_DECREF(self);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cleanup the type-info for a pybind11-registered type.
|
||||||
|
extern "C" inline void pybind11_meta_dealloc(PyObject *obj) {
|
||||||
|
auto *type = (PyTypeObject *) obj;
|
||||||
|
auto &internals = get_internals();
|
||||||
|
|
||||||
|
// A pybind11-registered type will:
|
||||||
|
// 1) be found in internals.registered_types_py
|
||||||
|
// 2) have exactly one associated `detail::type_info`
|
||||||
|
auto found_type = internals.registered_types_py.find(type);
|
||||||
|
if (found_type != internals.registered_types_py.end() && found_type->second.size() == 1
|
||||||
|
&& found_type->second[0]->type == type) {
|
||||||
|
|
||||||
|
auto *tinfo = found_type->second[0];
|
||||||
|
auto tindex = std::type_index(*tinfo->cpptype);
|
||||||
|
internals.direct_conversions.erase(tindex);
|
||||||
|
|
||||||
|
if (tinfo->module_local) {
|
||||||
|
get_local_internals().registered_types_cpp.erase(tindex);
|
||||||
|
} else {
|
||||||
|
internals.registered_types_cpp.erase(tindex);
|
||||||
|
}
|
||||||
|
internals.registered_types_py.erase(tinfo->type);
|
||||||
|
|
||||||
|
// Actually just `std::erase_if`, but that's only available in C++20
|
||||||
|
auto &cache = internals.inactive_override_cache;
|
||||||
|
for (auto it = cache.begin(), last = cache.end(); it != last;) {
|
||||||
|
if (it->first == (PyObject *) tinfo->type) {
|
||||||
|
it = cache.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete tinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyType_Type.tp_dealloc(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This metaclass is assigned by default to all pybind11 types and is required in order
|
||||||
|
for static properties to function correctly. Users may override this using `py::metaclass`.
|
||||||
|
Return value: New reference. */
|
||||||
|
inline PyTypeObject *make_default_metaclass() {
|
||||||
|
constexpr auto *name = "pybind11_type";
|
||||||
|
auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(name));
|
||||||
|
|
||||||
|
/* Danger zone: from now (and until PyType_Ready), make sure to
|
||||||
|
issue no Python C API calls which could potentially invoke the
|
||||||
|
garbage collector (the GC will call type_traverse(), which will in
|
||||||
|
turn find the newly constructed type in an invalid state) */
|
||||||
|
auto *heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
|
||||||
|
if (!heap_type) {
|
||||||
|
pybind11_fail("make_default_metaclass(): error allocating metaclass!");
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_type->ht_name = name_obj.inc_ref().ptr();
|
||||||
|
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||||
|
heap_type->ht_qualname = name_obj.inc_ref().ptr();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto *type = &heap_type->ht_type;
|
||||||
|
type->tp_name = name;
|
||||||
|
type->tp_base = type_incref(&PyType_Type);
|
||||||
|
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
|
||||||
|
|
||||||
|
type->tp_call = pybind11_meta_call;
|
||||||
|
|
||||||
|
type->tp_setattro = pybind11_meta_setattro;
|
||||||
|
type->tp_getattro = pybind11_meta_getattro;
|
||||||
|
|
||||||
|
type->tp_dealloc = pybind11_meta_dealloc;
|
||||||
|
|
||||||
|
if (PyType_Ready(type) < 0) {
|
||||||
|
pybind11_fail("make_default_metaclass(): failure in PyType_Ready()!");
|
||||||
|
}
|
||||||
|
|
||||||
|
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
|
||||||
|
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For multiple inheritance types we need to recursively register/deregister base pointers for any
|
||||||
|
/// base classes with pointers that are difference from the instance value pointer so that we can
|
||||||
|
/// correctly recognize an offset base class pointer. This calls a function with any offset base
|
||||||
|
/// ptrs.
|
||||||
|
inline void traverse_offset_bases(void *valueptr,
|
||||||
|
const detail::type_info *tinfo,
|
||||||
|
instance *self,
|
||||||
|
bool (*f)(void * /*parentptr*/, instance * /*self*/)) {
|
||||||
|
for (handle h : reinterpret_borrow<tuple>(tinfo->type->tp_bases)) {
|
||||||
|
if (auto *parent_tinfo = get_type_info((PyTypeObject *) h.ptr())) {
|
||||||
|
for (auto &c : parent_tinfo->implicit_casts) {
|
||||||
|
if (c.first == tinfo->cpptype) {
|
||||||
|
auto *parentptr = c.second(valueptr);
|
||||||
|
if (parentptr != valueptr) {
|
||||||
|
f(parentptr, self);
|
||||||
|
}
|
||||||
|
traverse_offset_bases(parentptr, parent_tinfo, self, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool register_instance_impl(void *ptr, instance *self) {
|
||||||
|
get_internals().registered_instances.emplace(ptr, self);
|
||||||
|
return true; // unused, but gives the same signature as the deregister func
|
||||||
|
}
|
||||||
|
inline bool deregister_instance_impl(void *ptr, instance *self) {
|
||||||
|
auto ®istered_instances = get_internals().registered_instances;
|
||||||
|
auto range = registered_instances.equal_range(ptr);
|
||||||
|
for (auto it = range.first; it != range.second; ++it) {
|
||||||
|
if (self == it->second) {
|
||||||
|
registered_instances.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void register_instance(instance *self, void *valptr, const type_info *tinfo) {
|
||||||
|
register_instance_impl(valptr, self);
|
||||||
|
if (!tinfo->simple_ancestors) {
|
||||||
|
traverse_offset_bases(valptr, tinfo, self, register_instance_impl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool deregister_instance(instance *self, void *valptr, const type_info *tinfo) {
|
||||||
|
bool ret = deregister_instance_impl(valptr, self);
|
||||||
|
if (!tinfo->simple_ancestors) {
|
||||||
|
traverse_offset_bases(valptr, tinfo, self, deregister_instance_impl);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Instance creation function for all pybind11 types. It allocates the internal instance layout
|
||||||
|
/// for holding C++ objects and holders. Allocation is done lazily (the first time the instance is
|
||||||
|
/// cast to a reference or pointer), and initialization is done by an `__init__` function.
|
||||||
|
inline PyObject *make_new_instance(PyTypeObject *type) {
|
||||||
|
#if defined(PYPY_VERSION)
|
||||||
|
// PyPy gets tp_basicsize wrong (issue 2482) under multiple inheritance when the first
|
||||||
|
// inherited object is a plain Python type (i.e. not derived from an extension type). Fix it.
|
||||||
|
ssize_t instance_size = static_cast<ssize_t>(sizeof(instance));
|
||||||
|
if (type->tp_basicsize < instance_size) {
|
||||||
|
type->tp_basicsize = instance_size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
PyObject *self = type->tp_alloc(type, 0);
|
||||||
|
auto *inst = reinterpret_cast<instance *>(self);
|
||||||
|
// Allocate the value/holder internals:
|
||||||
|
inst->allocate_layout();
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Instance creation function for all pybind11 types. It only allocates space for the
|
||||||
|
/// C++ object, but doesn't call the constructor -- an `__init__` function must do that.
|
||||||
|
extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *, PyObject *) {
|
||||||
|
return make_new_instance(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An `__init__` function constructs the C++ object. Users should provide at least one
|
||||||
|
/// of these using `py::init` or directly with `.def(__init__, ...)`. Otherwise, the
|
||||||
|
/// following default function will be used which simply throws an exception.
|
||||||
|
extern "C" inline int pybind11_object_init(PyObject *self, PyObject *, PyObject *) {
|
||||||
|
PyTypeObject *type = Py_TYPE(self);
|
||||||
|
std::string msg = get_fully_qualified_tp_name(type) + ": No constructor defined!";
|
||||||
|
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void add_patient(PyObject *nurse, PyObject *patient) {
|
||||||
|
auto &internals = get_internals();
|
||||||
|
auto *instance = reinterpret_cast<detail::instance *>(nurse);
|
||||||
|
instance->has_patients = true;
|
||||||
|
Py_INCREF(patient);
|
||||||
|
internals.patients[nurse].push_back(patient);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void clear_patients(PyObject *self) {
|
||||||
|
auto *instance = reinterpret_cast<detail::instance *>(self);
|
||||||
|
auto &internals = get_internals();
|
||||||
|
auto pos = internals.patients.find(self);
|
||||||
|
assert(pos != internals.patients.end());
|
||||||
|
// Clearing the patients can cause more Python code to run, which
|
||||||
|
// can invalidate the iterator. Extract the vector of patients
|
||||||
|
// from the unordered_map first.
|
||||||
|
auto patients = std::move(pos->second);
|
||||||
|
internals.patients.erase(pos);
|
||||||
|
instance->has_patients = false;
|
||||||
|
for (PyObject *&patient : patients) {
|
||||||
|
Py_CLEAR(patient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clears all internal data from the instance and removes it from registered instances in
|
||||||
|
/// preparation for deallocation.
|
||||||
|
inline void clear_instance(PyObject *self) {
|
||||||
|
auto *instance = reinterpret_cast<detail::instance *>(self);
|
||||||
|
|
||||||
|
// Deallocate any values/holders, if present:
|
||||||
|
for (auto &v_h : values_and_holders(instance)) {
|
||||||
|
if (v_h) {
|
||||||
|
|
||||||
|
// We have to deregister before we call dealloc because, for virtual MI types, we still
|
||||||
|
// need to be able to get the parent pointers.
|
||||||
|
if (v_h.instance_registered()
|
||||||
|
&& !deregister_instance(instance, v_h.value_ptr(), v_h.type)) {
|
||||||
|
pybind11_fail(
|
||||||
|
"pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance->owned || v_h.holder_constructed()) {
|
||||||
|
v_h.type->dealloc(v_h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Deallocate the value/holder layout internals:
|
||||||
|
instance->deallocate_layout();
|
||||||
|
|
||||||
|
if (instance->weakrefs) {
|
||||||
|
PyObject_ClearWeakRefs(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject **dict_ptr = _PyObject_GetDictPtr(self);
|
||||||
|
if (dict_ptr) {
|
||||||
|
Py_CLEAR(*dict_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance->has_patients) {
|
||||||
|
clear_patients(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Instance destructor function for all pybind11 types. It calls `type_info.dealloc`
|
||||||
|
/// to destroy the C++ object itself, while the rest is Python bookkeeping.
|
||||||
|
extern "C" inline void pybind11_object_dealloc(PyObject *self) {
|
||||||
|
auto *type = Py_TYPE(self);
|
||||||
|
|
||||||
|
// If this is a GC tracked object, untrack it first
|
||||||
|
// Note that the track call is implicitly done by the
|
||||||
|
// default tp_alloc, which we never override.
|
||||||
|
if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC) != 0) {
|
||||||
|
PyObject_GC_UnTrack(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_instance(self);
|
||||||
|
|
||||||
|
type->tp_free(self);
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX < 0x03080000
|
||||||
|
// `type->tp_dealloc != pybind11_object_dealloc` means that we're being called
|
||||||
|
// as part of a derived type's dealloc, in which case we're not allowed to decref
|
||||||
|
// the type here. For cross-module compatibility, we shouldn't compare directly
|
||||||
|
// with `pybind11_object_dealloc`, but with the common one stashed in internals.
|
||||||
|
auto pybind11_object_type = (PyTypeObject *) get_internals().instance_base;
|
||||||
|
if (type->tp_dealloc == pybind11_object_type->tp_dealloc)
|
||||||
|
Py_DECREF(type);
|
||||||
|
#else
|
||||||
|
// This was not needed before Python 3.8 (Python issue 35810)
|
||||||
|
// https://github.com/pybind/pybind11/issues/1946
|
||||||
|
Py_DECREF(type);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string error_string();
|
||||||
|
|
||||||
|
/** Create the type which can be used as a common base for all classes. This is
|
||||||
|
needed in order to satisfy Python's requirements for multiple inheritance.
|
||||||
|
Return value: New reference. */
|
||||||
|
inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
|
||||||
|
constexpr auto *name = "pybind11_object";
|
||||||
|
auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(name));
|
||||||
|
|
||||||
|
/* Danger zone: from now (and until PyType_Ready), make sure to
|
||||||
|
issue no Python C API calls which could potentially invoke the
|
||||||
|
garbage collector (the GC will call type_traverse(), which will in
|
||||||
|
turn find the newly constructed type in an invalid state) */
|
||||||
|
auto *heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
|
||||||
|
if (!heap_type) {
|
||||||
|
pybind11_fail("make_object_base_type(): error allocating type!");
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_type->ht_name = name_obj.inc_ref().ptr();
|
||||||
|
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||||
|
heap_type->ht_qualname = name_obj.inc_ref().ptr();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto *type = &heap_type->ht_type;
|
||||||
|
type->tp_name = name;
|
||||||
|
type->tp_base = type_incref(&PyBaseObject_Type);
|
||||||
|
type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
|
||||||
|
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
|
||||||
|
|
||||||
|
type->tp_new = pybind11_object_new;
|
||||||
|
type->tp_init = pybind11_object_init;
|
||||||
|
type->tp_dealloc = pybind11_object_dealloc;
|
||||||
|
|
||||||
|
/* Support weak references (needed for the keep_alive feature) */
|
||||||
|
type->tp_weaklistoffset = offsetof(instance, weakrefs);
|
||||||
|
|
||||||
|
if (PyType_Ready(type) < 0) {
|
||||||
|
pybind11_fail("PyType_Ready failed in make_object_base_type(): " + error_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
|
||||||
|
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
|
||||||
|
|
||||||
|
assert(!PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC));
|
||||||
|
return (PyObject *) heap_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// dynamic_attr: Allow the garbage collector to traverse the internal instance `__dict__`.
|
||||||
|
extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *arg) {
|
||||||
|
PyObject *&dict = *_PyObject_GetDictPtr(self);
|
||||||
|
Py_VISIT(dict);
|
||||||
|
// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
|
||||||
|
#if PY_VERSION_HEX >= 0x03090000
|
||||||
|
Py_VISIT(Py_TYPE(self));
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// dynamic_attr: Allow the GC to clear the dictionary.
|
||||||
|
extern "C" inline int pybind11_clear(PyObject *self) {
|
||||||
|
PyObject *&dict = *_PyObject_GetDictPtr(self);
|
||||||
|
Py_CLEAR(dict);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Give instances of this type a `__dict__` and opt into garbage collection.
|
||||||
|
inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) {
|
||||||
|
auto *type = &heap_type->ht_type;
|
||||||
|
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
|
||||||
|
#if PY_VERSION_HEX < 0x030B0000
|
||||||
|
type->tp_dictoffset = type->tp_basicsize; // place dict at the end
|
||||||
|
type->tp_basicsize += (ssize_t) sizeof(PyObject *); // and allocate enough space for it
|
||||||
|
#else
|
||||||
|
type->tp_flags |= Py_TPFLAGS_MANAGED_DICT;
|
||||||
|
#endif
|
||||||
|
type->tp_traverse = pybind11_traverse;
|
||||||
|
type->tp_clear = pybind11_clear;
|
||||||
|
|
||||||
|
static PyGetSetDef getset[] = {{
|
||||||
|
#if PY_VERSION_HEX < 0x03070000
|
||||||
|
const_cast<char *>("__dict__"),
|
||||||
|
#else
|
||||||
|
"__dict__",
|
||||||
|
#endif
|
||||||
|
PyObject_GenericGetDict,
|
||||||
|
PyObject_GenericSetDict,
|
||||||
|
nullptr,
|
||||||
|
nullptr},
|
||||||
|
{nullptr, nullptr, nullptr, nullptr, nullptr}};
|
||||||
|
type->tp_getset = getset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// buffer_protocol: Fill in the view as specified by flags.
|
||||||
|
extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int flags) {
|
||||||
|
// Look for a `get_buffer` implementation in this type's info or any bases (following MRO).
|
||||||
|
type_info *tinfo = nullptr;
|
||||||
|
for (auto type : reinterpret_borrow<tuple>(Py_TYPE(obj)->tp_mro)) {
|
||||||
|
tinfo = get_type_info((PyTypeObject *) type.ptr());
|
||||||
|
if (tinfo && tinfo->get_buffer) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (view == nullptr || !tinfo || !tinfo->get_buffer) {
|
||||||
|
if (view) {
|
||||||
|
view->obj = nullptr;
|
||||||
|
}
|
||||||
|
PyErr_SetString(PyExc_BufferError, "pybind11_getbuffer(): Internal error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
std::memset(view, 0, sizeof(Py_buffer));
|
||||||
|
buffer_info *info = tinfo->get_buffer(obj, tinfo->get_buffer_data);
|
||||||
|
if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE && info->readonly) {
|
||||||
|
delete info;
|
||||||
|
// view->obj = nullptr; // Was just memset to 0, so not necessary
|
||||||
|
PyErr_SetString(PyExc_BufferError, "Writable buffer requested for readonly storage");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
view->obj = obj;
|
||||||
|
view->ndim = 1;
|
||||||
|
view->internal = info;
|
||||||
|
view->buf = info->ptr;
|
||||||
|
view->itemsize = info->itemsize;
|
||||||
|
view->len = view->itemsize;
|
||||||
|
for (auto s : info->shape) {
|
||||||
|
view->len *= s;
|
||||||
|
}
|
||||||
|
view->readonly = static_cast<int>(info->readonly);
|
||||||
|
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
|
||||||
|
view->format = const_cast<char *>(info->format.c_str());
|
||||||
|
}
|
||||||
|
if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
|
||||||
|
view->ndim = (int) info->ndim;
|
||||||
|
view->strides = info->strides.data();
|
||||||
|
view->shape = info->shape.data();
|
||||||
|
}
|
||||||
|
Py_INCREF(view->obj);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// buffer_protocol: Release the resources of the buffer.
|
||||||
|
extern "C" inline void pybind11_releasebuffer(PyObject *, Py_buffer *view) {
|
||||||
|
delete (buffer_info *) view->internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Give this type a buffer interface.
|
||||||
|
inline void enable_buffer_protocol(PyHeapTypeObject *heap_type) {
|
||||||
|
heap_type->ht_type.tp_as_buffer = &heap_type->as_buffer;
|
||||||
|
|
||||||
|
heap_type->as_buffer.bf_getbuffer = pybind11_getbuffer;
|
||||||
|
heap_type->as_buffer.bf_releasebuffer = pybind11_releasebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a brand new Python type according to the `type_record` specification.
|
||||||
|
Return value: New reference. */
|
||||||
|
inline PyObject *make_new_python_type(const type_record &rec) {
|
||||||
|
auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(rec.name));
|
||||||
|
|
||||||
|
auto qualname = name;
|
||||||
|
if (rec.scope && !PyModule_Check(rec.scope.ptr()) && hasattr(rec.scope, "__qualname__")) {
|
||||||
|
qualname = reinterpret_steal<object>(
|
||||||
|
PyUnicode_FromFormat("%U.%U", rec.scope.attr("__qualname__").ptr(), name.ptr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
object module_;
|
||||||
|
if (rec.scope) {
|
||||||
|
if (hasattr(rec.scope, "__module__")) {
|
||||||
|
module_ = rec.scope.attr("__module__");
|
||||||
|
} else if (hasattr(rec.scope, "__name__")) {
|
||||||
|
module_ = rec.scope.attr("__name__");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto *full_name = c_str(
|
||||||
|
#if !defined(PYPY_VERSION)
|
||||||
|
module_ ? str(module_).cast<std::string>() + "." + rec.name :
|
||||||
|
#endif
|
||||||
|
rec.name);
|
||||||
|
|
||||||
|
char *tp_doc = nullptr;
|
||||||
|
if (rec.doc && options::show_user_defined_docstrings()) {
|
||||||
|
/* Allocate memory for docstring (using PyObject_MALLOC, since
|
||||||
|
Python will free this later on) */
|
||||||
|
size_t size = std::strlen(rec.doc) + 1;
|
||||||
|
tp_doc = (char *) PyObject_MALLOC(size);
|
||||||
|
std::memcpy((void *) tp_doc, rec.doc, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &internals = get_internals();
|
||||||
|
auto bases = tuple(rec.bases);
|
||||||
|
auto *base = (bases.empty()) ? internals.instance_base : bases[0].ptr();
|
||||||
|
|
||||||
|
/* Danger zone: from now (and until PyType_Ready), make sure to
|
||||||
|
issue no Python C API calls which could potentially invoke the
|
||||||
|
garbage collector (the GC will call type_traverse(), which will in
|
||||||
|
turn find the newly constructed type in an invalid state) */
|
||||||
|
auto *metaclass
|
||||||
|
= rec.metaclass.ptr() ? (PyTypeObject *) rec.metaclass.ptr() : internals.default_metaclass;
|
||||||
|
|
||||||
|
auto *heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
|
||||||
|
if (!heap_type) {
|
||||||
|
pybind11_fail(std::string(rec.name) + ": Unable to create type object!");
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_type->ht_name = name.release().ptr();
|
||||||
|
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||||
|
heap_type->ht_qualname = qualname.inc_ref().ptr();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto *type = &heap_type->ht_type;
|
||||||
|
type->tp_name = full_name;
|
||||||
|
type->tp_doc = tp_doc;
|
||||||
|
type->tp_base = type_incref((PyTypeObject *) base);
|
||||||
|
type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
|
||||||
|
if (!bases.empty()) {
|
||||||
|
type->tp_bases = bases.release().ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't inherit base __init__ */
|
||||||
|
type->tp_init = pybind11_object_init;
|
||||||
|
|
||||||
|
/* Supported protocols */
|
||||||
|
type->tp_as_number = &heap_type->as_number;
|
||||||
|
type->tp_as_sequence = &heap_type->as_sequence;
|
||||||
|
type->tp_as_mapping = &heap_type->as_mapping;
|
||||||
|
type->tp_as_async = &heap_type->as_async;
|
||||||
|
|
||||||
|
/* Flags */
|
||||||
|
type->tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE;
|
||||||
|
if (!rec.is_final) {
|
||||||
|
type->tp_flags |= Py_TPFLAGS_BASETYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec.dynamic_attr) {
|
||||||
|
enable_dynamic_attributes(heap_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec.buffer_protocol) {
|
||||||
|
enable_buffer_protocol(heap_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec.custom_type_setup_callback) {
|
||||||
|
rec.custom_type_setup_callback(heap_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyType_Ready(type) < 0) {
|
||||||
|
pybind11_fail(std::string(rec.name) + ": PyType_Ready failed: " + error_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!rec.dynamic_attr || PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC));
|
||||||
|
|
||||||
|
/* Register type with the parent scope */
|
||||||
|
if (rec.scope) {
|
||||||
|
setattr(rec.scope, rec.name, (PyObject *) type);
|
||||||
|
} else {
|
||||||
|
Py_INCREF(type); // Keep it alive forever (reference leak)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module_) { // Needed by pydoc
|
||||||
|
setattr((PyObject *) type, "__module__", module_);
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_SET_OLDPY_QUALNAME(type, qualname);
|
||||||
|
|
||||||
|
return (PyObject *) type;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
1255
3rdparty/pybind11/include/pybind11/detail/common.h
vendored
Normal file
1255
3rdparty/pybind11/include/pybind11/detail/common.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
171
3rdparty/pybind11/include/pybind11/detail/descr.h
vendored
Normal file
171
3rdparty/pybind11/include/pybind11/detail/descr.h
vendored
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
#if !defined(_MSC_VER)
|
||||||
|
# define PYBIND11_DESCR_CONSTEXPR static constexpr
|
||||||
|
#else
|
||||||
|
# define PYBIND11_DESCR_CONSTEXPR const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Concatenate type signatures at compile time */
|
||||||
|
template <size_t N, typename... Ts>
|
||||||
|
struct descr {
|
||||||
|
char text[N + 1]{'\0'};
|
||||||
|
|
||||||
|
constexpr descr() = default;
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
constexpr descr(char const (&s)[N + 1]) : descr(s, make_index_sequence<N>()) {}
|
||||||
|
|
||||||
|
template <size_t... Is>
|
||||||
|
constexpr descr(char const (&s)[N + 1], index_sequence<Is...>) : text{s[Is]..., '\0'} {}
|
||||||
|
|
||||||
|
template <typename... Chars>
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} {}
|
||||||
|
|
||||||
|
static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() {
|
||||||
|
return {{&typeid(Ts)..., nullptr}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <size_t N1, size_t N2, typename... Ts1, typename... Ts2, size_t... Is1, size_t... Is2>
|
||||||
|
constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a,
|
||||||
|
const descr<N2, Ts2...> &b,
|
||||||
|
index_sequence<Is1...>,
|
||||||
|
index_sequence<Is2...>) {
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(b);
|
||||||
|
return {a.text[Is1]..., b.text[Is2]...};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
|
||||||
|
constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a,
|
||||||
|
const descr<N2, Ts2...> &b) {
|
||||||
|
return plus_impl(a, b, make_index_sequence<N1>(), make_index_sequence<N2>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
constexpr descr<N - 1> const_name(char const (&text)[N]) {
|
||||||
|
return descr<N - 1>(text);
|
||||||
|
}
|
||||||
|
constexpr descr<0> const_name(char const (&)[1]) { return {}; }
|
||||||
|
|
||||||
|
template <size_t Rem, size_t... Digits>
|
||||||
|
struct int_to_str : int_to_str<Rem / 10, Rem % 10, Digits...> {};
|
||||||
|
template <size_t... Digits>
|
||||||
|
struct int_to_str<0, Digits...> {
|
||||||
|
// WARNING: This only works with C++17 or higher.
|
||||||
|
static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ternary description (like std::conditional)
|
||||||
|
template <bool B, size_t N1, size_t N2>
|
||||||
|
constexpr enable_if_t<B, descr<N1 - 1>> const_name(char const (&text1)[N1], char const (&)[N2]) {
|
||||||
|
return const_name(text1);
|
||||||
|
}
|
||||||
|
template <bool B, size_t N1, size_t N2>
|
||||||
|
constexpr enable_if_t<!B, descr<N2 - 1>> const_name(char const (&)[N1], char const (&text2)[N2]) {
|
||||||
|
return const_name(text2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool B, typename T1, typename T2>
|
||||||
|
constexpr enable_if_t<B, T1> const_name(const T1 &d, const T2 &) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
template <bool B, typename T1, typename T2>
|
||||||
|
constexpr enable_if_t<!B, T2> const_name(const T1 &, const T2 &d) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t Size>
|
||||||
|
auto constexpr const_name() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
|
||||||
|
return int_to_str<Size / 10, Size % 10>::digits;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
constexpr descr<1, Type> const_name() {
|
||||||
|
return {'%'};
|
||||||
|
}
|
||||||
|
|
||||||
|
// If "_" is defined as a macro, py::detail::_ cannot be provided.
|
||||||
|
// It is therefore best to use py::detail::const_name universally.
|
||||||
|
// This block is for backward compatibility only.
|
||||||
|
// (The const_name code is repeated to avoid introducing a "_" #define ourselves.)
|
||||||
|
#ifndef _
|
||||||
|
# define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
|
||||||
|
template <size_t N>
|
||||||
|
constexpr descr<N - 1> _(char const (&text)[N]) {
|
||||||
|
return const_name<N>(text);
|
||||||
|
}
|
||||||
|
template <bool B, size_t N1, size_t N2>
|
||||||
|
constexpr enable_if_t<B, descr<N1 - 1>> _(char const (&text1)[N1], char const (&text2)[N2]) {
|
||||||
|
return const_name<B, N1, N2>(text1, text2);
|
||||||
|
}
|
||||||
|
template <bool B, size_t N1, size_t N2>
|
||||||
|
constexpr enable_if_t<!B, descr<N2 - 1>> _(char const (&text1)[N1], char const (&text2)[N2]) {
|
||||||
|
return const_name<B, N1, N2>(text1, text2);
|
||||||
|
}
|
||||||
|
template <bool B, typename T1, typename T2>
|
||||||
|
constexpr enable_if_t<B, T1> _(const T1 &d1, const T2 &d2) {
|
||||||
|
return const_name<B, T1, T2>(d1, d2);
|
||||||
|
}
|
||||||
|
template <bool B, typename T1, typename T2>
|
||||||
|
constexpr enable_if_t<!B, T2> _(const T1 &d1, const T2 &d2) {
|
||||||
|
return const_name<B, T1, T2>(d1, d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t Size>
|
||||||
|
auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
|
||||||
|
return const_name<Size>();
|
||||||
|
}
|
||||||
|
template <typename Type>
|
||||||
|
constexpr descr<1, Type> _() {
|
||||||
|
return const_name<Type>();
|
||||||
|
}
|
||||||
|
#endif // #ifndef _
|
||||||
|
|
||||||
|
constexpr descr<0> concat() { return {}; }
|
||||||
|
|
||||||
|
template <size_t N, typename... Ts>
|
||||||
|
constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) {
|
||||||
|
return descr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cpp_fold_expressions
|
||||||
|
template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
|
||||||
|
constexpr descr<N1 + N2 + 2, Ts1..., Ts2...> operator,(const descr<N1, Ts1...> &a,
|
||||||
|
const descr<N2, Ts2...> &b) {
|
||||||
|
return a + const_name(", ") + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N, typename... Ts, typename... Args>
|
||||||
|
constexpr auto concat(const descr<N, Ts...> &d, const Args &...args) {
|
||||||
|
return (d, ..., args);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template <size_t N, typename... Ts, typename... Args>
|
||||||
|
constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
|
||||||
|
-> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
|
||||||
|
return d + const_name(", ") + concat(args...);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <size_t N, typename... Ts>
|
||||||
|
constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) {
|
||||||
|
return const_name("{") + descr + const_name("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
434
3rdparty/pybind11/include/pybind11/detail/init.h
vendored
Normal file
434
3rdparty/pybind11/include/pybind11/detail/init.h
vendored
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
/*
|
||||||
|
pybind11/detail/init.h: init factory function implementation and support code.
|
||||||
|
|
||||||
|
Copyright (c) 2017 Jason Rhinelander <jason@imaginary.ca>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "class.h"
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class type_caster<value_and_holder> {
|
||||||
|
public:
|
||||||
|
bool load(handle h, bool) {
|
||||||
|
value = reinterpret_cast<value_and_holder *>(h.ptr());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename>
|
||||||
|
using cast_op_type = value_and_holder &;
|
||||||
|
explicit operator value_and_holder &() { return *value; }
|
||||||
|
static constexpr auto name = const_name<value_and_holder>();
|
||||||
|
|
||||||
|
private:
|
||||||
|
value_and_holder *value = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(initimpl)
|
||||||
|
|
||||||
|
inline void no_nullptr(void *ptr) {
|
||||||
|
if (!ptr) {
|
||||||
|
throw type_error("pybind11::init(): factory function returned nullptr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementing functions for all forms of py::init<...> and py::init(...)
|
||||||
|
template <typename Class>
|
||||||
|
using Cpp = typename Class::type;
|
||||||
|
template <typename Class>
|
||||||
|
using Alias = typename Class::type_alias;
|
||||||
|
template <typename Class>
|
||||||
|
using Holder = typename Class::holder_type;
|
||||||
|
|
||||||
|
template <typename Class>
|
||||||
|
using is_alias_constructible = std::is_constructible<Alias<Class>, Cpp<Class> &&>;
|
||||||
|
|
||||||
|
// Takes a Cpp pointer and returns true if it actually is a polymorphic Alias instance.
|
||||||
|
template <typename Class, enable_if_t<Class::has_alias, int> = 0>
|
||||||
|
bool is_alias(Cpp<Class> *ptr) {
|
||||||
|
return dynamic_cast<Alias<Class> *>(ptr) != nullptr;
|
||||||
|
}
|
||||||
|
// Failing fallback version of the above for a no-alias class (always returns false)
|
||||||
|
template <typename /*Class*/>
|
||||||
|
constexpr bool is_alias(void *) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs and returns a new object; if the given arguments don't map to a constructor, we fall
|
||||||
|
// back to brace aggregate initiailization so that for aggregate initialization can be used with
|
||||||
|
// py::init, e.g. `py::init<int, int>` to initialize a `struct T { int a; int b; }`. For
|
||||||
|
// non-aggregate types, we need to use an ordinary T(...) constructor (invoking as `T{...}` usually
|
||||||
|
// works, but will not do the expected thing when `T` has an `initializer_list<T>` constructor).
|
||||||
|
template <typename Class,
|
||||||
|
typename... Args,
|
||||||
|
detail::enable_if_t<std::is_constructible<Class, Args...>::value, int> = 0>
|
||||||
|
inline Class *construct_or_initialize(Args &&...args) {
|
||||||
|
return new Class(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
template <typename Class,
|
||||||
|
typename... Args,
|
||||||
|
detail::enable_if_t<!std::is_constructible<Class, Args...>::value, int> = 0>
|
||||||
|
inline Class *construct_or_initialize(Args &&...args) {
|
||||||
|
return new Class{std::forward<Args>(args)...};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempts to constructs an alias using a `Alias(Cpp &&)` constructor. This allows types with
|
||||||
|
// an alias to provide only a single Cpp factory function as long as the Alias can be
|
||||||
|
// constructed from an rvalue reference of the base Cpp type. This means that Alias classes
|
||||||
|
// can, when appropriate, simply define a `Alias(Cpp &&)` constructor rather than needing to
|
||||||
|
// inherit all the base class constructors.
|
||||||
|
template <typename Class>
|
||||||
|
void construct_alias_from_cpp(std::true_type /*is_alias_constructible*/,
|
||||||
|
value_and_holder &v_h,
|
||||||
|
Cpp<Class> &&base) {
|
||||||
|
v_h.value_ptr() = new Alias<Class>(std::move(base));
|
||||||
|
}
|
||||||
|
template <typename Class>
|
||||||
|
[[noreturn]] void construct_alias_from_cpp(std::false_type /*!is_alias_constructible*/,
|
||||||
|
value_and_holder &,
|
||||||
|
Cpp<Class> &&) {
|
||||||
|
throw type_error("pybind11::init(): unable to convert returned instance to required "
|
||||||
|
"alias class: no `Alias<Class>(Class &&)` constructor available");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error-generating fallback for factories that don't match one of the below construction
|
||||||
|
// mechanisms.
|
||||||
|
template <typename Class>
|
||||||
|
void construct(...) {
|
||||||
|
static_assert(!std::is_same<Class, Class>::value /* always false */,
|
||||||
|
"pybind11::init(): init function must return a compatible pointer, "
|
||||||
|
"holder, or value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointer return v1: the factory function returns a class pointer for a registered class.
|
||||||
|
// If we don't need an alias (because this class doesn't have one, or because the final type is
|
||||||
|
// inherited on the Python side) we can simply take over ownership. Otherwise we need to try to
|
||||||
|
// construct an Alias from the returned base instance.
|
||||||
|
template <typename Class>
|
||||||
|
void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
|
||||||
|
no_nullptr(ptr);
|
||||||
|
if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
|
||||||
|
// We're going to try to construct an alias by moving the cpp type. Whether or not
|
||||||
|
// that succeeds, we still need to destroy the original cpp pointer (either the
|
||||||
|
// moved away leftover, if the alias construction works, or the value itself if we
|
||||||
|
// throw an error), but we can't just call `delete ptr`: it might have a special
|
||||||
|
// deleter, or might be shared_from_this. So we construct a holder around it as if
|
||||||
|
// it was a normal instance, then steal the holder away into a local variable; thus
|
||||||
|
// the holder and destruction happens when we leave the C++ scope, and the holder
|
||||||
|
// class gets to handle the destruction however it likes.
|
||||||
|
v_h.value_ptr() = ptr;
|
||||||
|
v_h.set_instance_registered(true); // To prevent init_instance from registering it
|
||||||
|
v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder
|
||||||
|
Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>())); // Steal the holder
|
||||||
|
v_h.type->dealloc(v_h); // Destroys the moved-out holder remains, resets value ptr to null
|
||||||
|
v_h.set_instance_registered(false);
|
||||||
|
|
||||||
|
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(*ptr));
|
||||||
|
} else {
|
||||||
|
// Otherwise the type isn't inherited, so we don't need an Alias
|
||||||
|
v_h.value_ptr() = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointer return v2: a factory that always returns an alias instance ptr. We simply take over
|
||||||
|
// ownership of the pointer.
|
||||||
|
template <typename Class, enable_if_t<Class::has_alias, int> = 0>
|
||||||
|
void construct(value_and_holder &v_h, Alias<Class> *alias_ptr, bool) {
|
||||||
|
no_nullptr(alias_ptr);
|
||||||
|
v_h.value_ptr() = static_cast<Cpp<Class> *>(alias_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Holder return: copy its pointer, and move or copy the returned holder into the new instance's
|
||||||
|
// holder. This also handles types like std::shared_ptr<T> and std::unique_ptr<T> where T is a
|
||||||
|
// derived type (through those holder's implicit conversion from derived class holder
|
||||||
|
// constructors).
|
||||||
|
template <typename Class>
|
||||||
|
void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
|
||||||
|
auto *ptr = holder_helper<Holder<Class>>::get(holder);
|
||||||
|
no_nullptr(ptr);
|
||||||
|
// If we need an alias, check that the held pointer is actually an alias instance
|
||||||
|
if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
|
||||||
|
throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance "
|
||||||
|
"is not an alias instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
v_h.value_ptr() = ptr;
|
||||||
|
v_h.type->init_instance(v_h.inst, &holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return-by-value version 1: returning a cpp class by value. If the class has an alias and an
|
||||||
|
// alias is required the alias must have an `Alias(Cpp &&)` constructor so that we can construct
|
||||||
|
// the alias from the base when needed (i.e. because of Python-side inheritance). When we don't
|
||||||
|
// need it, we simply move-construct the cpp value into a new instance.
|
||||||
|
template <typename Class>
|
||||||
|
void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
|
||||||
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
|
||||||
|
static_assert(is_move_constructible<Cpp<Class>>::value,
|
||||||
|
"pybind11::init() return-by-value factory function requires a movable class");
|
||||||
|
if (Class::has_alias && need_alias) {
|
||||||
|
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result));
|
||||||
|
} else {
|
||||||
|
v_h.value_ptr() = new Cpp<Class>(std::move(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return-by-value version 2: returning a value of the alias type itself. We move-construct an
|
||||||
|
// Alias instance (even if no the python-side inheritance is involved). The is intended for
|
||||||
|
// cases where Alias initialization is always desired.
|
||||||
|
template <typename Class>
|
||||||
|
void construct(value_and_holder &v_h, Alias<Class> &&result, bool) {
|
||||||
|
static_assert(
|
||||||
|
is_move_constructible<Alias<Class>>::value,
|
||||||
|
"pybind11::init() return-by-alias-value factory function requires a movable alias class");
|
||||||
|
v_h.value_ptr() = new Alias<Class>(std::move(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementing class for py::init<...>()
|
||||||
|
template <typename... Args>
|
||||||
|
struct constructor {
|
||||||
|
template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0>
|
||||||
|
static void execute(Class &cl, const Extra &...extra) {
|
||||||
|
cl.def(
|
||||||
|
"__init__",
|
||||||
|
[](value_and_holder &v_h, Args... args) {
|
||||||
|
v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
|
||||||
|
},
|
||||||
|
is_new_style_constructor(),
|
||||||
|
extra...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename Class,
|
||||||
|
typename... Extra,
|
||||||
|
enable_if_t<Class::has_alias && std::is_constructible<Cpp<Class>, Args...>::value, int>
|
||||||
|
= 0>
|
||||||
|
static void execute(Class &cl, const Extra &...extra) {
|
||||||
|
cl.def(
|
||||||
|
"__init__",
|
||||||
|
[](value_and_holder &v_h, Args... args) {
|
||||||
|
if (Py_TYPE(v_h.inst) == v_h.type->type) {
|
||||||
|
v_h.value_ptr()
|
||||||
|
= construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
|
||||||
|
} else {
|
||||||
|
v_h.value_ptr()
|
||||||
|
= construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
is_new_style_constructor(),
|
||||||
|
extra...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename Class,
|
||||||
|
typename... Extra,
|
||||||
|
enable_if_t<Class::has_alias && !std::is_constructible<Cpp<Class>, Args...>::value, int>
|
||||||
|
= 0>
|
||||||
|
static void execute(Class &cl, const Extra &...extra) {
|
||||||
|
cl.def(
|
||||||
|
"__init__",
|
||||||
|
[](value_and_holder &v_h, Args... args) {
|
||||||
|
v_h.value_ptr()
|
||||||
|
= construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||||
|
},
|
||||||
|
is_new_style_constructor(),
|
||||||
|
extra...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementing class for py::init_alias<...>()
|
||||||
|
template <typename... Args>
|
||||||
|
struct alias_constructor {
|
||||||
|
template <
|
||||||
|
typename Class,
|
||||||
|
typename... Extra,
|
||||||
|
enable_if_t<Class::has_alias && std::is_constructible<Alias<Class>, Args...>::value, int>
|
||||||
|
= 0>
|
||||||
|
static void execute(Class &cl, const Extra &...extra) {
|
||||||
|
cl.def(
|
||||||
|
"__init__",
|
||||||
|
[](value_and_holder &v_h, Args... args) {
|
||||||
|
v_h.value_ptr()
|
||||||
|
= construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||||
|
},
|
||||||
|
is_new_style_constructor(),
|
||||||
|
extra...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation class for py::init(Func) and py::init(Func, AliasFunc)
|
||||||
|
template <typename CFunc,
|
||||||
|
typename AFunc = void_type (*)(),
|
||||||
|
typename = function_signature_t<CFunc>,
|
||||||
|
typename = function_signature_t<AFunc>>
|
||||||
|
struct factory;
|
||||||
|
|
||||||
|
// Specialization for py::init(Func)
|
||||||
|
template <typename Func, typename Return, typename... Args>
|
||||||
|
struct factory<Func, void_type (*)(), Return(Args...)> {
|
||||||
|
remove_reference_t<Func> class_factory;
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
factory(Func &&f) : class_factory(std::forward<Func>(f)) {}
|
||||||
|
|
||||||
|
// The given class either has no alias or has no separate alias factory;
|
||||||
|
// this always constructs the class itself. If the class is registered with an alias
|
||||||
|
// type and an alias instance is needed (i.e. because the final type is a Python class
|
||||||
|
// inheriting from the C++ type) the returned value needs to either already be an alias
|
||||||
|
// instance, or the alias needs to be constructible from a `Class &&` argument.
|
||||||
|
template <typename Class, typename... Extra>
|
||||||
|
void execute(Class &cl, const Extra &...extra) && {
|
||||||
|
#if defined(PYBIND11_CPP14)
|
||||||
|
cl.def(
|
||||||
|
"__init__",
|
||||||
|
[func = std::move(class_factory)]
|
||||||
|
#else
|
||||||
|
auto &func = class_factory;
|
||||||
|
cl.def(
|
||||||
|
"__init__",
|
||||||
|
[func]
|
||||||
|
#endif
|
||||||
|
(value_and_holder &v_h, Args... args) {
|
||||||
|
construct<Class>(
|
||||||
|
v_h, func(std::forward<Args>(args)...), Py_TYPE(v_h.inst) != v_h.type->type);
|
||||||
|
},
|
||||||
|
is_new_style_constructor(),
|
||||||
|
extra...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization for py::init(Func, AliasFunc)
|
||||||
|
template <typename CFunc,
|
||||||
|
typename AFunc,
|
||||||
|
typename CReturn,
|
||||||
|
typename... CArgs,
|
||||||
|
typename AReturn,
|
||||||
|
typename... AArgs>
|
||||||
|
struct factory<CFunc, AFunc, CReturn(CArgs...), AReturn(AArgs...)> {
|
||||||
|
static_assert(sizeof...(CArgs) == sizeof...(AArgs),
|
||||||
|
"pybind11::init(class_factory, alias_factory): class and alias factories "
|
||||||
|
"must have identical argument signatures");
|
||||||
|
static_assert(all_of<std::is_same<CArgs, AArgs>...>::value,
|
||||||
|
"pybind11::init(class_factory, alias_factory): class and alias factories "
|
||||||
|
"must have identical argument signatures");
|
||||||
|
|
||||||
|
remove_reference_t<CFunc> class_factory;
|
||||||
|
remove_reference_t<AFunc> alias_factory;
|
||||||
|
|
||||||
|
factory(CFunc &&c, AFunc &&a)
|
||||||
|
: class_factory(std::forward<CFunc>(c)), alias_factory(std::forward<AFunc>(a)) {}
|
||||||
|
|
||||||
|
// The class factory is called when the `self` type passed to `__init__` is the direct
|
||||||
|
// class (i.e. not inherited), the alias factory when `self` is a Python-side subtype.
|
||||||
|
template <typename Class, typename... Extra>
|
||||||
|
void execute(Class &cl, const Extra &...extra) && {
|
||||||
|
static_assert(Class::has_alias,
|
||||||
|
"The two-argument version of `py::init()` can "
|
||||||
|
"only be used if the class has an alias");
|
||||||
|
#if defined(PYBIND11_CPP14)
|
||||||
|
cl.def(
|
||||||
|
"__init__",
|
||||||
|
[class_func = std::move(class_factory), alias_func = std::move(alias_factory)]
|
||||||
|
#else
|
||||||
|
auto &class_func = class_factory;
|
||||||
|
auto &alias_func = alias_factory;
|
||||||
|
cl.def(
|
||||||
|
"__init__",
|
||||||
|
[class_func, alias_func]
|
||||||
|
#endif
|
||||||
|
(value_and_holder &v_h, CArgs... args) {
|
||||||
|
if (Py_TYPE(v_h.inst) == v_h.type->type) {
|
||||||
|
// If the instance type equals the registered type we don't have inheritance,
|
||||||
|
// so don't need the alias and can construct using the class function:
|
||||||
|
construct<Class>(v_h, class_func(std::forward<CArgs>(args)...), false);
|
||||||
|
} else {
|
||||||
|
construct<Class>(v_h, alias_func(std::forward<CArgs>(args)...), true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
is_new_style_constructor(),
|
||||||
|
extra...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Set just the C++ state. Same as `__init__`.
|
||||||
|
template <typename Class, typename T>
|
||||||
|
void setstate(value_and_holder &v_h, T &&result, bool need_alias) {
|
||||||
|
construct<Class>(v_h, std::forward<T>(result), need_alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set both the C++ and Python states
|
||||||
|
template <typename Class,
|
||||||
|
typename T,
|
||||||
|
typename O,
|
||||||
|
enable_if_t<std::is_convertible<O, handle>::value, int> = 0>
|
||||||
|
void setstate(value_and_holder &v_h, std::pair<T, O> &&result, bool need_alias) {
|
||||||
|
construct<Class>(v_h, std::move(result.first), need_alias);
|
||||||
|
auto d = handle(result.second);
|
||||||
|
if (PyDict_Check(d.ptr()) && PyDict_Size(d.ptr()) == 0) {
|
||||||
|
// Skipping setattr below, to not force use of py::dynamic_attr() for Class unnecessarily.
|
||||||
|
// See PR #2972 for details.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setattr((PyObject *) v_h.inst, "__dict__", d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implementation for py::pickle(GetState, SetState)
|
||||||
|
template <typename Get,
|
||||||
|
typename Set,
|
||||||
|
typename = function_signature_t<Get>,
|
||||||
|
typename = function_signature_t<Set>>
|
||||||
|
struct pickle_factory;
|
||||||
|
|
||||||
|
template <typename Get,
|
||||||
|
typename Set,
|
||||||
|
typename RetState,
|
||||||
|
typename Self,
|
||||||
|
typename NewInstance,
|
||||||
|
typename ArgState>
|
||||||
|
struct pickle_factory<Get, Set, RetState(Self), NewInstance(ArgState)> {
|
||||||
|
static_assert(std::is_same<intrinsic_t<RetState>, intrinsic_t<ArgState>>::value,
|
||||||
|
"The type returned by `__getstate__` must be the same "
|
||||||
|
"as the argument accepted by `__setstate__`");
|
||||||
|
|
||||||
|
remove_reference_t<Get> get;
|
||||||
|
remove_reference_t<Set> set;
|
||||||
|
|
||||||
|
pickle_factory(Get get, Set set) : get(std::forward<Get>(get)), set(std::forward<Set>(set)) {}
|
||||||
|
|
||||||
|
template <typename Class, typename... Extra>
|
||||||
|
void execute(Class &cl, const Extra &...extra) && {
|
||||||
|
cl.def("__getstate__", std::move(get));
|
||||||
|
|
||||||
|
#if defined(PYBIND11_CPP14)
|
||||||
|
cl.def(
|
||||||
|
"__setstate__",
|
||||||
|
[func = std::move(set)]
|
||||||
|
#else
|
||||||
|
auto &func = set;
|
||||||
|
cl.def(
|
||||||
|
"__setstate__",
|
||||||
|
[func]
|
||||||
|
#endif
|
||||||
|
(value_and_holder &v_h, ArgState state) {
|
||||||
|
setstate<Class>(
|
||||||
|
v_h, func(std::forward<ArgState>(state)), Py_TYPE(v_h.inst) != v_h.type->type);
|
||||||
|
},
|
||||||
|
is_new_style_constructor(),
|
||||||
|
extra...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(initimpl)
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
656
3rdparty/pybind11/include/pybind11/detail/internals.h
vendored
Normal file
656
3rdparty/pybind11/include/pybind11/detail/internals.h
vendored
Normal file
@ -0,0 +1,656 @@
|
|||||||
|
/*
|
||||||
|
pybind11/detail/internals.h: Internal data structure and related functions
|
||||||
|
|
||||||
|
Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#if defined(WITH_THREAD) && defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||||
|
# include "../gil.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../pytypes.h"
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
/// Tracks the `internals` and `type_info` ABI version independent of the main library version.
|
||||||
|
///
|
||||||
|
/// Some portions of the code use an ABI that is conditional depending on this
|
||||||
|
/// version number. That allows ABI-breaking changes to be "pre-implemented".
|
||||||
|
/// Once the default version number is incremented, the conditional logic that
|
||||||
|
/// no longer applies can be removed. Additionally, users that need not
|
||||||
|
/// maintain ABI compatibility can increase the version number in order to take
|
||||||
|
/// advantage of any functionality/efficiency improvements that depend on the
|
||||||
|
/// newer ABI.
|
||||||
|
///
|
||||||
|
/// WARNING: If you choose to manually increase the ABI version, note that
|
||||||
|
/// pybind11 may not be tested as thoroughly with a non-default ABI version, and
|
||||||
|
/// further ABI-incompatible changes may be made before the ABI is officially
|
||||||
|
/// changed to the new version.
|
||||||
|
#ifndef PYBIND11_INTERNALS_VERSION
|
||||||
|
# if PY_VERSION_HEX >= 0x030C0000
|
||||||
|
// Version bump for Python 3.12+, before first 3.12 beta release.
|
||||||
|
# define PYBIND11_INTERNALS_VERSION 5
|
||||||
|
# else
|
||||||
|
# define PYBIND11_INTERNALS_VERSION 4
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This requirement is mainly to reduce the support burden (see PR #4570).
|
||||||
|
static_assert(PY_VERSION_HEX < 0x030C0000 || PYBIND11_INTERNALS_VERSION >= 5,
|
||||||
|
"pybind11 ABI version 5 is the minimum for Python 3.12+");
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
using ExceptionTranslator = void (*)(std::exception_ptr);
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
constexpr const char *internals_function_record_capsule_name = "pybind11_function_record_capsule";
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
inline PyTypeObject *make_static_property_type();
|
||||||
|
inline PyTypeObject *make_default_metaclass();
|
||||||
|
inline PyObject *make_object_base_type(PyTypeObject *metaclass);
|
||||||
|
|
||||||
|
// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
|
||||||
|
// Thread Specific Storage (TSS) API.
|
||||||
|
#if PY_VERSION_HEX >= 0x03070000
|
||||||
|
// Avoid unnecessary allocation of `Py_tss_t`, since we cannot use
|
||||||
|
// `Py_LIMITED_API` anyway.
|
||||||
|
# if PYBIND11_INTERNALS_VERSION > 4
|
||||||
|
# define PYBIND11_TLS_KEY_REF Py_tss_t &
|
||||||
|
# if defined(__GNUC__) && !defined(__INTEL_COMPILER)
|
||||||
|
// Clang on macOS warns due to `Py_tss_NEEDS_INIT` not specifying an initializer
|
||||||
|
// for every field.
|
||||||
|
# define PYBIND11_TLS_KEY_INIT(var) \
|
||||||
|
_Pragma("GCC diagnostic push") /**/ \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \
|
||||||
|
Py_tss_t var \
|
||||||
|
= Py_tss_NEEDS_INIT; \
|
||||||
|
_Pragma("GCC diagnostic pop")
|
||||||
|
# else
|
||||||
|
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t var = Py_tss_NEEDS_INIT;
|
||||||
|
# endif
|
||||||
|
# define PYBIND11_TLS_KEY_CREATE(var) (PyThread_tss_create(&(var)) == 0)
|
||||||
|
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get(&(key))
|
||||||
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set(&(key), (value))
|
||||||
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set(&(key), nullptr)
|
||||||
|
# define PYBIND11_TLS_FREE(key) PyThread_tss_delete(&(key))
|
||||||
|
# else
|
||||||
|
# define PYBIND11_TLS_KEY_REF Py_tss_t *
|
||||||
|
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t *var = nullptr;
|
||||||
|
# define PYBIND11_TLS_KEY_CREATE(var) \
|
||||||
|
(((var) = PyThread_tss_alloc()) != nullptr && (PyThread_tss_create((var)) == 0))
|
||||||
|
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key))
|
||||||
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set((key), (value))
|
||||||
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set((key), nullptr)
|
||||||
|
# define PYBIND11_TLS_FREE(key) PyThread_tss_free(key)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
// Usually an int but a long on Cygwin64 with Python 3.x
|
||||||
|
# define PYBIND11_TLS_KEY_REF decltype(PyThread_create_key())
|
||||||
|
# define PYBIND11_TLS_KEY_INIT(var) PYBIND11_TLS_KEY_REF var = 0;
|
||||||
|
# define PYBIND11_TLS_KEY_CREATE(var) (((var) = PyThread_create_key()) != -1)
|
||||||
|
# define PYBIND11_TLS_GET_VALUE(key) PyThread_get_key_value((key))
|
||||||
|
# if defined(PYPY_VERSION)
|
||||||
|
// On CPython < 3.4 and on PyPy, `PyThread_set_key_value` strangely does not set
|
||||||
|
// the value if it has already been set. Instead, it must first be deleted and
|
||||||
|
// then set again.
|
||||||
|
inline void tls_replace_value(PYBIND11_TLS_KEY_REF key, void *value) {
|
||||||
|
PyThread_delete_key_value(key);
|
||||||
|
PyThread_set_key_value(key, value);
|
||||||
|
}
|
||||||
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_delete_key_value(key)
|
||||||
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) \
|
||||||
|
::pybind11::detail::tls_replace_value((key), (value))
|
||||||
|
# else
|
||||||
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_set_key_value((key), nullptr)
|
||||||
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_set_key_value((key), (value))
|
||||||
|
# endif
|
||||||
|
# define PYBIND11_TLS_FREE(key) (void) key
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
|
||||||
|
// other STLs, this means `typeid(A)` from one module won't equal `typeid(A)` from another module
|
||||||
|
// even when `A` is the same, non-hidden-visibility type (e.g. from a common include). Under
|
||||||
|
// libstdc++, this doesn't happen: equality and the type_index hash are based on the type name,
|
||||||
|
// which works. If not under a known-good stl, provide our own name-based hash and equality
|
||||||
|
// functions that use the type name.
|
||||||
|
#if (PYBIND11_INTERNALS_VERSION <= 4 && defined(__GLIBCXX__)) \
|
||||||
|
|| (PYBIND11_INTERNALS_VERSION >= 5 && !defined(_LIBCPP_VERSION))
|
||||||
|
inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) { return lhs == rhs; }
|
||||||
|
using type_hash = std::hash<std::type_index>;
|
||||||
|
using type_equal_to = std::equal_to<std::type_index>;
|
||||||
|
#else
|
||||||
|
inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) {
|
||||||
|
return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct type_hash {
|
||||||
|
size_t operator()(const std::type_index &t) const {
|
||||||
|
size_t hash = 5381;
|
||||||
|
const char *ptr = t.name();
|
||||||
|
while (auto c = static_cast<unsigned char>(*ptr++)) {
|
||||||
|
hash = (hash * 33) ^ c;
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct type_equal_to {
|
||||||
|
bool operator()(const std::type_index &lhs, const std::type_index &rhs) const {
|
||||||
|
return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename value_type>
|
||||||
|
using type_map = std::unordered_map<std::type_index, value_type, type_hash, type_equal_to>;
|
||||||
|
|
||||||
|
struct override_hash {
|
||||||
|
inline size_t operator()(const std::pair<const PyObject *, const char *> &v) const {
|
||||||
|
size_t value = std::hash<const void *>()(v.first);
|
||||||
|
value ^= std::hash<const void *>()(v.second) + 0x9e3779b9 + (value << 6) + (value >> 2);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Internal data structure used to track registered instances and types.
|
||||||
|
/// Whenever binary incompatible changes are made to this structure,
|
||||||
|
/// `PYBIND11_INTERNALS_VERSION` must be incremented.
|
||||||
|
struct internals {
|
||||||
|
// std::type_index -> pybind11's type information
|
||||||
|
type_map<type_info *> registered_types_cpp;
|
||||||
|
// PyTypeObject* -> base type_info(s)
|
||||||
|
std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py;
|
||||||
|
std::unordered_multimap<const void *, instance *> registered_instances; // void * -> instance*
|
||||||
|
std::unordered_set<std::pair<const PyObject *, const char *>, override_hash>
|
||||||
|
inactive_override_cache;
|
||||||
|
type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
|
||||||
|
std::unordered_map<const PyObject *, std::vector<PyObject *>> patients;
|
||||||
|
std::forward_list<ExceptionTranslator> registered_exception_translators;
|
||||||
|
std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across
|
||||||
|
// extensions
|
||||||
|
#if PYBIND11_INTERNALS_VERSION == 4
|
||||||
|
std::vector<PyObject *> unused_loader_patient_stack_remove_at_v5;
|
||||||
|
#endif
|
||||||
|
std::forward_list<std::string> static_strings; // Stores the std::strings backing
|
||||||
|
// detail::c_str()
|
||||||
|
PyTypeObject *static_property_type;
|
||||||
|
PyTypeObject *default_metaclass;
|
||||||
|
PyObject *instance_base;
|
||||||
|
#if defined(WITH_THREAD)
|
||||||
|
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
|
||||||
|
PYBIND11_TLS_KEY_INIT(tstate)
|
||||||
|
# if PYBIND11_INTERNALS_VERSION > 4
|
||||||
|
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key)
|
||||||
|
# endif // PYBIND11_INTERNALS_VERSION > 4
|
||||||
|
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
|
||||||
|
PyInterpreterState *istate = nullptr;
|
||||||
|
|
||||||
|
# if PYBIND11_INTERNALS_VERSION > 4
|
||||||
|
// Note that we have to use a std::string to allocate memory to ensure a unique address
|
||||||
|
// We want unique addresses since we use pointer equality to compare function records
|
||||||
|
std::string function_record_capsule_name = internals_function_record_capsule_name;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
internals() = default;
|
||||||
|
internals(const internals &other) = delete;
|
||||||
|
internals &operator=(const internals &other) = delete;
|
||||||
|
~internals() {
|
||||||
|
# if PYBIND11_INTERNALS_VERSION > 4
|
||||||
|
PYBIND11_TLS_FREE(loader_life_support_tls_key);
|
||||||
|
# endif // PYBIND11_INTERNALS_VERSION > 4
|
||||||
|
|
||||||
|
// This destructor is called *after* Py_Finalize() in finalize_interpreter().
|
||||||
|
// That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is
|
||||||
|
// called. PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does
|
||||||
|
// nothing. PyThread_tss_free calls PyThread_tss_delete and PyMem_RawFree.
|
||||||
|
// PyThread_tss_delete just calls TlsFree (on Windows) or pthread_key_delete (on *NIX).
|
||||||
|
// Neither of those have anything to do with CPython internals. PyMem_RawFree *requires*
|
||||||
|
// that the `tstate` be allocated with the CPython allocator.
|
||||||
|
PYBIND11_TLS_FREE(tstate);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Additional type information which does not fit into the PyTypeObject.
|
||||||
|
/// Changes to this struct also require bumping `PYBIND11_INTERNALS_VERSION`.
|
||||||
|
struct type_info {
|
||||||
|
PyTypeObject *type;
|
||||||
|
const std::type_info *cpptype;
|
||||||
|
size_t type_size, type_align, holder_size_in_ptrs;
|
||||||
|
void *(*operator_new)(size_t);
|
||||||
|
void (*init_instance)(instance *, const void *);
|
||||||
|
void (*dealloc)(value_and_holder &v_h);
|
||||||
|
std::vector<PyObject *(*) (PyObject *, PyTypeObject *)> implicit_conversions;
|
||||||
|
std::vector<std::pair<const std::type_info *, void *(*) (void *)>> implicit_casts;
|
||||||
|
std::vector<bool (*)(PyObject *, void *&)> *direct_conversions;
|
||||||
|
buffer_info *(*get_buffer)(PyObject *, void *) = nullptr;
|
||||||
|
void *get_buffer_data = nullptr;
|
||||||
|
void *(*module_local_load)(PyObject *, const type_info *) = nullptr;
|
||||||
|
/* A simple type never occurs as a (direct or indirect) parent
|
||||||
|
* of a class that makes use of multiple inheritance.
|
||||||
|
* A type can be simple even if it has non-simple ancestors as long as it has no descendants.
|
||||||
|
*/
|
||||||
|
bool simple_type : 1;
|
||||||
|
/* True if there is no multiple inheritance in this type's inheritance tree */
|
||||||
|
bool simple_ancestors : 1;
|
||||||
|
/* for base vs derived holder_type checks */
|
||||||
|
bool default_holder : 1;
|
||||||
|
/* true if this is a type registered with py::module_local */
|
||||||
|
bool module_local : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// On MSVC, debug and release builds are not ABI-compatible!
|
||||||
|
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||||
|
# define PYBIND11_BUILD_TYPE "_debug"
|
||||||
|
#else
|
||||||
|
# define PYBIND11_BUILD_TYPE ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Let's assume that different compilers are ABI-incompatible.
|
||||||
|
/// A user can manually set this string if they know their
|
||||||
|
/// compiler is compatible.
|
||||||
|
#ifndef PYBIND11_COMPILER_TYPE
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define PYBIND11_COMPILER_TYPE "_msvc"
|
||||||
|
# elif defined(__INTEL_COMPILER)
|
||||||
|
# define PYBIND11_COMPILER_TYPE "_icc"
|
||||||
|
# elif defined(__clang__)
|
||||||
|
# define PYBIND11_COMPILER_TYPE "_clang"
|
||||||
|
# elif defined(__PGI)
|
||||||
|
# define PYBIND11_COMPILER_TYPE "_pgi"
|
||||||
|
# elif defined(__MINGW32__)
|
||||||
|
# define PYBIND11_COMPILER_TYPE "_mingw"
|
||||||
|
# elif defined(__CYGWIN__)
|
||||||
|
# define PYBIND11_COMPILER_TYPE "_gcc_cygwin"
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
# define PYBIND11_COMPILER_TYPE "_gcc"
|
||||||
|
# else
|
||||||
|
# define PYBIND11_COMPILER_TYPE "_unknown"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Also standard libs
|
||||||
|
#ifndef PYBIND11_STDLIB
|
||||||
|
# if defined(_LIBCPP_VERSION)
|
||||||
|
# define PYBIND11_STDLIB "_libcpp"
|
||||||
|
# elif defined(__GLIBCXX__) || defined(__GLIBCPP__)
|
||||||
|
# define PYBIND11_STDLIB "_libstdcpp"
|
||||||
|
# else
|
||||||
|
# define PYBIND11_STDLIB ""
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// On Linux/OSX, changes in __GXX_ABI_VERSION__ indicate ABI incompatibility.
|
||||||
|
#ifndef PYBIND11_BUILD_ABI
|
||||||
|
# if defined(__GXX_ABI_VERSION)
|
||||||
|
# define PYBIND11_BUILD_ABI "_cxxabi" PYBIND11_TOSTRING(__GXX_ABI_VERSION)
|
||||||
|
# else
|
||||||
|
# define PYBIND11_BUILD_ABI ""
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PYBIND11_INTERNALS_KIND
|
||||||
|
# if defined(WITH_THREAD)
|
||||||
|
# define PYBIND11_INTERNALS_KIND ""
|
||||||
|
# else
|
||||||
|
# define PYBIND11_INTERNALS_KIND "_without_thread"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PYBIND11_INTERNALS_ID \
|
||||||
|
"__pybind11_internals_v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \
|
||||||
|
PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB PYBIND11_BUILD_ABI \
|
||||||
|
PYBIND11_BUILD_TYPE "__"
|
||||||
|
|
||||||
|
#define PYBIND11_MODULE_LOCAL_ID \
|
||||||
|
"__pybind11_module_local_v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \
|
||||||
|
PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB PYBIND11_BUILD_ABI \
|
||||||
|
PYBIND11_BUILD_TYPE "__"
|
||||||
|
|
||||||
|
/// Each module locally stores a pointer to the `internals` data. The data
|
||||||
|
/// itself is shared among modules with the same `PYBIND11_INTERNALS_ID`.
|
||||||
|
inline internals **&get_internals_pp() {
|
||||||
|
static internals **internals_pp = nullptr;
|
||||||
|
return internals_pp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// forward decl
|
||||||
|
inline void translate_exception(std::exception_ptr);
|
||||||
|
|
||||||
|
template <class T,
|
||||||
|
enable_if_t<std::is_same<std::nested_exception, remove_cvref_t<T>>::value, int> = 0>
|
||||||
|
bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
|
||||||
|
std::exception_ptr nested = exc.nested_ptr();
|
||||||
|
if (nested != nullptr && nested != p) {
|
||||||
|
translate_exception(nested);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T,
|
||||||
|
enable_if_t<!std::is_same<std::nested_exception, remove_cvref_t<T>>::value, int> = 0>
|
||||||
|
bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
|
||||||
|
if (const auto *nep = dynamic_cast<const std::nested_exception *>(std::addressof(exc))) {
|
||||||
|
return handle_nested_exception(*nep, p);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool raise_err(PyObject *exc_type, const char *msg) {
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
raise_from(exc_type, msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
PyErr_SetString(exc_type, msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void translate_exception(std::exception_ptr p) {
|
||||||
|
if (!p) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
std::rethrow_exception(p);
|
||||||
|
} catch (error_already_set &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
e.restore();
|
||||||
|
return;
|
||||||
|
} catch (const builtin_exception &e) {
|
||||||
|
// Could not use template since it's an abstract class.
|
||||||
|
if (const auto *nep = dynamic_cast<const std::nested_exception *>(std::addressof(e))) {
|
||||||
|
handle_nested_exception(*nep, p);
|
||||||
|
}
|
||||||
|
e.set_error();
|
||||||
|
return;
|
||||||
|
} catch (const std::bad_alloc &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_MemoryError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::domain_error &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_ValueError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::invalid_argument &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_ValueError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::length_error &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_ValueError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::out_of_range &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_IndexError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::range_error &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_ValueError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::overflow_error &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_OverflowError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_RuntimeError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::nested_exception &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_RuntimeError, "Caught an unknown nested exception!");
|
||||||
|
return;
|
||||||
|
} catch (...) {
|
||||||
|
raise_err(PyExc_RuntimeError, "Caught an unknown exception!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(__GLIBCXX__)
|
||||||
|
inline void translate_local_exception(std::exception_ptr p) {
|
||||||
|
try {
|
||||||
|
if (p) {
|
||||||
|
std::rethrow_exception(p);
|
||||||
|
}
|
||||||
|
} catch (error_already_set &e) {
|
||||||
|
e.restore();
|
||||||
|
return;
|
||||||
|
} catch (const builtin_exception &e) {
|
||||||
|
e.set_error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline object get_python_state_dict() {
|
||||||
|
object state_dict;
|
||||||
|
#if PYBIND11_INTERNALS_VERSION <= 4 || PY_VERSION_HEX < 0x03080000 || defined(PYPY_VERSION)
|
||||||
|
state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins());
|
||||||
|
#else
|
||||||
|
# if PY_VERSION_HEX < 0x03090000
|
||||||
|
PyInterpreterState *istate = _PyInterpreterState_Get();
|
||||||
|
# else
|
||||||
|
PyInterpreterState *istate = PyInterpreterState_Get();
|
||||||
|
# endif
|
||||||
|
if (istate) {
|
||||||
|
state_dict = reinterpret_borrow<object>(PyInterpreterState_GetDict(istate));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!state_dict) {
|
||||||
|
raise_from(PyExc_SystemError, "pybind11::detail::get_python_state_dict() FAILED");
|
||||||
|
}
|
||||||
|
return state_dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object get_internals_obj_from_state_dict(handle state_dict) {
|
||||||
|
return reinterpret_borrow<object>(dict_getitemstring(state_dict.ptr(), PYBIND11_INTERNALS_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline internals **get_internals_pp_from_capsule(handle obj) {
|
||||||
|
void *raw_ptr = PyCapsule_GetPointer(obj.ptr(), /*name=*/nullptr);
|
||||||
|
if (raw_ptr == nullptr) {
|
||||||
|
raise_from(PyExc_SystemError, "pybind11::detail::get_internals_pp_from_capsule() FAILED");
|
||||||
|
}
|
||||||
|
return static_cast<internals **>(raw_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a reference to the current `internals` data
|
||||||
|
PYBIND11_NOINLINE internals &get_internals() {
|
||||||
|
auto **&internals_pp = get_internals_pp();
|
||||||
|
if (internals_pp && *internals_pp) {
|
||||||
|
return **internals_pp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WITH_THREAD)
|
||||||
|
# if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||||
|
gil_scoped_acquire gil;
|
||||||
|
# else
|
||||||
|
// Ensure that the GIL is held since we will need to make Python calls.
|
||||||
|
// Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
|
||||||
|
struct gil_scoped_acquire_local {
|
||||||
|
gil_scoped_acquire_local() : state(PyGILState_Ensure()) {}
|
||||||
|
gil_scoped_acquire_local(const gil_scoped_acquire_local &) = delete;
|
||||||
|
gil_scoped_acquire_local &operator=(const gil_scoped_acquire_local &) = delete;
|
||||||
|
~gil_scoped_acquire_local() { PyGILState_Release(state); }
|
||||||
|
const PyGILState_STATE state;
|
||||||
|
} gil;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
error_scope err_scope;
|
||||||
|
|
||||||
|
dict state_dict = get_python_state_dict();
|
||||||
|
if (object internals_obj = get_internals_obj_from_state_dict(state_dict)) {
|
||||||
|
internals_pp = get_internals_pp_from_capsule(internals_obj);
|
||||||
|
}
|
||||||
|
if (internals_pp && *internals_pp) {
|
||||||
|
// We loaded the internals through `state_dict`, which means that our `error_already_set`
|
||||||
|
// and `builtin_exception` may be different local classes than the ones set up in the
|
||||||
|
// initial exception translator, below, so add another for our local exception classes.
|
||||||
|
//
|
||||||
|
// libstdc++ doesn't require this (types there are identified only by name)
|
||||||
|
// libc++ with CPython doesn't require this (types are explicitly exported)
|
||||||
|
// libc++ with PyPy still need it, awaiting further investigation
|
||||||
|
#if !defined(__GLIBCXX__)
|
||||||
|
(*internals_pp)->registered_exception_translators.push_front(&translate_local_exception);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (!internals_pp) {
|
||||||
|
internals_pp = new internals *();
|
||||||
|
}
|
||||||
|
auto *&internals_ptr = *internals_pp;
|
||||||
|
internals_ptr = new internals();
|
||||||
|
#if defined(WITH_THREAD)
|
||||||
|
|
||||||
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
|
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
||||||
|
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->tstate)) {
|
||||||
|
pybind11_fail("get_internals: could not successfully initialize the tstate TSS key!");
|
||||||
|
}
|
||||||
|
PYBIND11_TLS_REPLACE_VALUE(internals_ptr->tstate, tstate);
|
||||||
|
|
||||||
|
# if PYBIND11_INTERNALS_VERSION > 4
|
||||||
|
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
||||||
|
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->loader_life_support_tls_key)) {
|
||||||
|
pybind11_fail("get_internals: could not successfully initialize the "
|
||||||
|
"loader_life_support TSS key!");
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
internals_ptr->istate = tstate->interp;
|
||||||
|
#endif
|
||||||
|
state_dict[PYBIND11_INTERNALS_ID] = capsule(internals_pp);
|
||||||
|
internals_ptr->registered_exception_translators.push_front(&translate_exception);
|
||||||
|
internals_ptr->static_property_type = make_static_property_type();
|
||||||
|
internals_ptr->default_metaclass = make_default_metaclass();
|
||||||
|
internals_ptr->instance_base = make_object_base_type(internals_ptr->default_metaclass);
|
||||||
|
}
|
||||||
|
return **internals_pp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the internals struct (above) is shared between all the modules. local_internals are only
|
||||||
|
// for a single module. Any changes made to internals may require an update to
|
||||||
|
// PYBIND11_INTERNALS_VERSION, breaking backwards compatibility. local_internals is, by design,
|
||||||
|
// restricted to a single module. Whether a module has local internals or not should not
|
||||||
|
// impact any other modules, because the only things accessing the local internals is the
|
||||||
|
// module that contains them.
|
||||||
|
struct local_internals {
|
||||||
|
type_map<type_info *> registered_types_cpp;
|
||||||
|
std::forward_list<ExceptionTranslator> registered_exception_translators;
|
||||||
|
#if defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
|
||||||
|
|
||||||
|
// For ABI compatibility, we can't store the loader_life_support TLS key in
|
||||||
|
// the `internals` struct directly. Instead, we store it in `shared_data` and
|
||||||
|
// cache a copy in `local_internals`. If we allocated a separate TLS key for
|
||||||
|
// each instance of `local_internals`, we could end up allocating hundreds of
|
||||||
|
// TLS keys if hundreds of different pybind11 modules are loaded (which is a
|
||||||
|
// plausible number).
|
||||||
|
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key)
|
||||||
|
|
||||||
|
// Holds the shared TLS key for the loader_life_support stack.
|
||||||
|
struct shared_loader_life_support_data {
|
||||||
|
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key)
|
||||||
|
shared_loader_life_support_data() {
|
||||||
|
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
||||||
|
if (!PYBIND11_TLS_KEY_CREATE(loader_life_support_tls_key)) {
|
||||||
|
pybind11_fail("local_internals: could not successfully initialize the "
|
||||||
|
"loader_life_support TLS key!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We can't help but leak the TLS key, because Python never unloads extension modules.
|
||||||
|
};
|
||||||
|
|
||||||
|
local_internals() {
|
||||||
|
auto &internals = get_internals();
|
||||||
|
// Get or create the `loader_life_support_stack_key`.
|
||||||
|
auto &ptr = internals.shared_data["_life_support"];
|
||||||
|
if (!ptr) {
|
||||||
|
ptr = new shared_loader_life_support_data;
|
||||||
|
}
|
||||||
|
loader_life_support_tls_key
|
||||||
|
= static_cast<shared_loader_life_support_data *>(ptr)->loader_life_support_tls_key;
|
||||||
|
}
|
||||||
|
#endif // defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Works like `get_internals`, but for things which are locally registered.
|
||||||
|
inline local_internals &get_local_internals() {
|
||||||
|
// Current static can be created in the interpreter finalization routine. If the later will be
|
||||||
|
// destroyed in another static variable destructor, creation of this static there will cause
|
||||||
|
// static deinitialization fiasco. In order to avoid it we avoid destruction of the
|
||||||
|
// local_internals static. One can read more about the problem and current solution here:
|
||||||
|
// https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
|
||||||
|
static auto *locals = new local_internals();
|
||||||
|
return *locals;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs a std::string with the given arguments, stores it in `internals`, and returns its
|
||||||
|
/// `c_str()`. Such strings objects have a long storage duration -- the internal strings are only
|
||||||
|
/// cleared when the program exits or after interpreter shutdown (when embedding), and so are
|
||||||
|
/// suitable for c-style strings needed by Python internals (such as PyTypeObject's tp_name).
|
||||||
|
template <typename... Args>
|
||||||
|
const char *c_str(Args &&...args) {
|
||||||
|
auto &strings = get_internals().static_strings;
|
||||||
|
strings.emplace_front(std::forward<Args>(args)...);
|
||||||
|
return strings.front().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *get_function_record_capsule_name() {
|
||||||
|
#if PYBIND11_INTERNALS_VERSION > 4
|
||||||
|
return get_internals().function_record_capsule_name.c_str();
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine whether or not the following capsule contains a pybind11 function record.
|
||||||
|
// Note that we use `internals` to make sure that only ABI compatible records are touched.
|
||||||
|
//
|
||||||
|
// This check is currently used in two places:
|
||||||
|
// - An important optimization in functional.h to avoid overhead in C++ -> Python -> C++
|
||||||
|
// - The sibling feature of cpp_function to allow overloads
|
||||||
|
inline bool is_function_record_capsule(const capsule &cap) {
|
||||||
|
// Pointer equality as we rely on internals() to ensure unique pointers
|
||||||
|
return cap.name() == get_function_record_capsule_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
/// Returns a named pointer that is shared among all extension modules (using the same
|
||||||
|
/// pybind11 version) running in the current interpreter. Names starting with underscores
|
||||||
|
/// are reserved for internal usage. Returns `nullptr` if no matching entry was found.
|
||||||
|
PYBIND11_NOINLINE void *get_shared_data(const std::string &name) {
|
||||||
|
auto &internals = detail::get_internals();
|
||||||
|
auto it = internals.shared_data.find(name);
|
||||||
|
return it != internals.shared_data.end() ? it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the shared data that can be later recovered by `get_shared_data()`.
|
||||||
|
PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *data) {
|
||||||
|
detail::get_internals().shared_data[name] = data;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a typed reference to a shared data entry (by using `get_shared_data()`) if
|
||||||
|
/// such entry exists. Otherwise, a new object of default-constructible type `T` is
|
||||||
|
/// added to the shared data under the given name and a reference to it is returned.
|
||||||
|
template <typename T>
|
||||||
|
T &get_or_create_shared_data(const std::string &name) {
|
||||||
|
auto &internals = detail::get_internals();
|
||||||
|
auto it = internals.shared_data.find(name);
|
||||||
|
T *ptr = (T *) (it != internals.shared_data.end() ? it->second : nullptr);
|
||||||
|
if (!ptr) {
|
||||||
|
ptr = new T();
|
||||||
|
internals.shared_data[name] = ptr;
|
||||||
|
}
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
1177
3rdparty/pybind11/include/pybind11/detail/type_caster_base.h
vendored
Normal file
1177
3rdparty/pybind11/include/pybind11/detail/type_caster_base.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
65
3rdparty/pybind11/include/pybind11/detail/typeid.h
vendored
Normal file
65
3rdparty/pybind11/include/pybind11/detail/typeid.h
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
pybind11/detail/typeid.h: Compiler-independent access to type identifiers
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
# include <cxxabi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
/// Erase all occurrences of a substring
|
||||||
|
inline void erase_all(std::string &string, const std::string &search) {
|
||||||
|
for (size_t pos = 0;;) {
|
||||||
|
pos = string.find(search, pos);
|
||||||
|
if (pos == std::string::npos) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
string.erase(pos, search.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NOINLINE void clean_type_id(std::string &name) {
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
int status = 0;
|
||||||
|
std::unique_ptr<char, void (*)(void *)> res{
|
||||||
|
abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free};
|
||||||
|
if (status == 0) {
|
||||||
|
name = res.get();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
detail::erase_all(name, "class ");
|
||||||
|
detail::erase_all(name, "struct ");
|
||||||
|
detail::erase_all(name, "enum ");
|
||||||
|
#endif
|
||||||
|
detail::erase_all(name, "pybind11::");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string clean_type_id(const char *typeid_name) {
|
||||||
|
std::string name(typeid_name);
|
||||||
|
detail::clean_type_id(name);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
/// Return a string representation of a C++ type
|
||||||
|
template <typename T>
|
||||||
|
static std::string type_id() {
|
||||||
|
return detail::clean_type_id(typeid(T).name());
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
12
3rdparty/pybind11/include/pybind11/eigen.h
vendored
Normal file
12
3rdparty/pybind11/include/pybind11/eigen.h
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
pybind11/eigen.h: Transparent conversion for dense and sparse Eigen matrices
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "eigen/matrix.h"
|
9
3rdparty/pybind11/include/pybind11/eigen/common.h
vendored
Normal file
9
3rdparty/pybind11/include/pybind11/eigen/common.h
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) 2023 The pybind Community.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Common message for `static_assert()`s, which are useful to easily
|
||||||
|
// preempt much less obvious errors.
|
||||||
|
#define PYBIND11_EIGEN_MESSAGE_POINTER_TYPES_ARE_NOT_SUPPORTED \
|
||||||
|
"Pointer types (in particular `PyObject *`) are not supported as scalar types for Eigen " \
|
||||||
|
"types."
|
714
3rdparty/pybind11/include/pybind11/eigen/matrix.h
vendored
Normal file
714
3rdparty/pybind11/include/pybind11/eigen/matrix.h
vendored
Normal file
@ -0,0 +1,714 @@
|
|||||||
|
/*
|
||||||
|
pybind11/eigen/matrix.h: Transparent conversion for dense and sparse Eigen matrices
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../numpy.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
/* HINT: To suppress warnings originating from the Eigen headers, use -isystem.
|
||||||
|
See also:
|
||||||
|
https://stackoverflow.com/questions/2579576/i-dir-vs-isystem-dir
|
||||||
|
https://stackoverflow.com/questions/1741816/isystem-for-ms-visual-studio-c-compiler
|
||||||
|
*/
|
||||||
|
PYBIND11_WARNING_PUSH
|
||||||
|
PYBIND11_WARNING_DISABLE_MSVC(5054) // https://github.com/pybind/pybind11/pull/3741
|
||||||
|
// C5054: operator '&': deprecated between enumerations of different types
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
PYBIND11_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Eigen/Core>
|
||||||
|
#include <Eigen/SparseCore>
|
||||||
|
|
||||||
|
PYBIND11_WARNING_POP
|
||||||
|
|
||||||
|
// Eigen prior to 3.2.7 doesn't have proper move constructors--but worse, some classes get implicit
|
||||||
|
// move constructors that break things. We could detect this an explicitly copy, but an extra copy
|
||||||
|
// of matrices seems highly undesirable.
|
||||||
|
static_assert(EIGEN_VERSION_AT_LEAST(3, 2, 7),
|
||||||
|
"Eigen matrix support in pybind11 requires Eigen >= 3.2.7");
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
||||||
|
|
||||||
|
// Provide a convenience alias for easier pass-by-ref usage with fully dynamic strides:
|
||||||
|
using EigenDStride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
|
||||||
|
template <typename MatrixType>
|
||||||
|
using EigenDRef = Eigen::Ref<MatrixType, 0, EigenDStride>;
|
||||||
|
template <typename MatrixType>
|
||||||
|
using EigenDMap = Eigen::Map<MatrixType, 0, EigenDStride>;
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
#if EIGEN_VERSION_AT_LEAST(3, 3, 0)
|
||||||
|
using EigenIndex = Eigen::Index;
|
||||||
|
template <typename Scalar, int Flags, typename StorageIndex>
|
||||||
|
using EigenMapSparseMatrix = Eigen::Map<Eigen::SparseMatrix<Scalar, Flags, StorageIndex>>;
|
||||||
|
#else
|
||||||
|
using EigenIndex = EIGEN_DEFAULT_DENSE_INDEX_TYPE;
|
||||||
|
template <typename Scalar, int Flags, typename StorageIndex>
|
||||||
|
using EigenMapSparseMatrix = Eigen::MappedSparseMatrix<Scalar, Flags, StorageIndex>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Matches Eigen::Map, Eigen::Ref, blocks, etc:
|
||||||
|
template <typename T>
|
||||||
|
using is_eigen_dense_map = all_of<is_template_base_of<Eigen::DenseBase, T>,
|
||||||
|
std::is_base_of<Eigen::MapBase<T, Eigen::ReadOnlyAccessors>, T>>;
|
||||||
|
template <typename T>
|
||||||
|
using is_eigen_mutable_map = std::is_base_of<Eigen::MapBase<T, Eigen::WriteAccessors>, T>;
|
||||||
|
template <typename T>
|
||||||
|
using is_eigen_dense_plain
|
||||||
|
= all_of<negation<is_eigen_dense_map<T>>, is_template_base_of<Eigen::PlainObjectBase, T>>;
|
||||||
|
template <typename T>
|
||||||
|
using is_eigen_sparse = is_template_base_of<Eigen::SparseMatrixBase, T>;
|
||||||
|
// Test for objects inheriting from EigenBase<Derived> that aren't captured by the above. This
|
||||||
|
// basically covers anything that can be assigned to a dense matrix but that don't have a typical
|
||||||
|
// matrix data layout that can be copied from their .data(). For example, DiagonalMatrix and
|
||||||
|
// SelfAdjointView fall into this category.
|
||||||
|
template <typename T>
|
||||||
|
using is_eigen_other
|
||||||
|
= all_of<is_template_base_of<Eigen::EigenBase, T>,
|
||||||
|
negation<any_of<is_eigen_dense_map<T>, is_eigen_dense_plain<T>, is_eigen_sparse<T>>>>;
|
||||||
|
|
||||||
|
// Captures numpy/eigen conformability status (returned by EigenProps::conformable()):
|
||||||
|
template <bool EigenRowMajor>
|
||||||
|
struct EigenConformable {
|
||||||
|
bool conformable = false;
|
||||||
|
EigenIndex rows = 0, cols = 0;
|
||||||
|
EigenDStride stride{0, 0}; // Only valid if negativestrides is false!
|
||||||
|
bool negativestrides = false; // If true, do not use stride!
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
EigenConformable(bool fits = false) : conformable{fits} {}
|
||||||
|
// Matrix type:
|
||||||
|
EigenConformable(EigenIndex r, EigenIndex c, EigenIndex rstride, EigenIndex cstride)
|
||||||
|
: conformable{true}, rows{r}, cols{c},
|
||||||
|
// TODO: when Eigen bug #747 is fixed, remove the tests for non-negativity.
|
||||||
|
// http://eigen.tuxfamily.org/bz/show_bug.cgi?id=747
|
||||||
|
stride{EigenRowMajor ? (rstride > 0 ? rstride : 0)
|
||||||
|
: (cstride > 0 ? cstride : 0) /* outer stride */,
|
||||||
|
EigenRowMajor ? (cstride > 0 ? cstride : 0)
|
||||||
|
: (rstride > 0 ? rstride : 0) /* inner stride */},
|
||||||
|
negativestrides{rstride < 0 || cstride < 0} {}
|
||||||
|
// Vector type:
|
||||||
|
EigenConformable(EigenIndex r, EigenIndex c, EigenIndex stride)
|
||||||
|
: EigenConformable(r, c, r == 1 ? c * stride : stride, c == 1 ? r : r * stride) {}
|
||||||
|
|
||||||
|
template <typename props>
|
||||||
|
bool stride_compatible() const {
|
||||||
|
// To have compatible strides, we need (on both dimensions) one of fully dynamic strides,
|
||||||
|
// matching strides, or a dimension size of 1 (in which case the stride value is
|
||||||
|
// irrelevant). Alternatively, if any dimension size is 0, the strides are not relevant
|
||||||
|
// (and numpy ≥ 1.23 sets the strides to 0 in that case, so we need to check explicitly).
|
||||||
|
if (negativestrides) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rows == 0 || cols == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (props::inner_stride == Eigen::Dynamic || props::inner_stride == stride.inner()
|
||||||
|
|| (EigenRowMajor ? cols : rows) == 1)
|
||||||
|
&& (props::outer_stride == Eigen::Dynamic || props::outer_stride == stride.outer()
|
||||||
|
|| (EigenRowMajor ? rows : cols) == 1);
|
||||||
|
}
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
operator bool() const { return conformable; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
struct eigen_extract_stride {
|
||||||
|
using type = Type;
|
||||||
|
};
|
||||||
|
template <typename PlainObjectType, int MapOptions, typename StrideType>
|
||||||
|
struct eigen_extract_stride<Eigen::Map<PlainObjectType, MapOptions, StrideType>> {
|
||||||
|
using type = StrideType;
|
||||||
|
};
|
||||||
|
template <typename PlainObjectType, int Options, typename StrideType>
|
||||||
|
struct eigen_extract_stride<Eigen::Ref<PlainObjectType, Options, StrideType>> {
|
||||||
|
using type = StrideType;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper struct for extracting information from an Eigen type
|
||||||
|
template <typename Type_>
|
||||||
|
struct EigenProps {
|
||||||
|
using Type = Type_;
|
||||||
|
using Scalar = typename Type::Scalar;
|
||||||
|
using StrideType = typename eigen_extract_stride<Type>::type;
|
||||||
|
static constexpr EigenIndex rows = Type::RowsAtCompileTime, cols = Type::ColsAtCompileTime,
|
||||||
|
size = Type::SizeAtCompileTime;
|
||||||
|
static constexpr bool row_major = Type::IsRowMajor,
|
||||||
|
vector
|
||||||
|
= Type::IsVectorAtCompileTime, // At least one dimension has fixed size 1
|
||||||
|
fixed_rows = rows != Eigen::Dynamic, fixed_cols = cols != Eigen::Dynamic,
|
||||||
|
fixed = size != Eigen::Dynamic, // Fully-fixed size
|
||||||
|
dynamic = !fixed_rows && !fixed_cols; // Fully-dynamic size
|
||||||
|
|
||||||
|
template <EigenIndex i, EigenIndex ifzero>
|
||||||
|
using if_zero = std::integral_constant<EigenIndex, i == 0 ? ifzero : i>;
|
||||||
|
static constexpr EigenIndex inner_stride
|
||||||
|
= if_zero<StrideType::InnerStrideAtCompileTime, 1>::value,
|
||||||
|
outer_stride = if_zero < StrideType::OuterStrideAtCompileTime,
|
||||||
|
vector ? size
|
||||||
|
: row_major ? cols
|
||||||
|
: rows > ::value;
|
||||||
|
static constexpr bool dynamic_stride
|
||||||
|
= inner_stride == Eigen::Dynamic && outer_stride == Eigen::Dynamic;
|
||||||
|
static constexpr bool requires_row_major
|
||||||
|
= !dynamic_stride && !vector && (row_major ? inner_stride : outer_stride) == 1;
|
||||||
|
static constexpr bool requires_col_major
|
||||||
|
= !dynamic_stride && !vector && (row_major ? outer_stride : inner_stride) == 1;
|
||||||
|
|
||||||
|
// Takes an input array and determines whether we can make it fit into the Eigen type. If
|
||||||
|
// the array is a vector, we attempt to fit it into either an Eigen 1xN or Nx1 vector
|
||||||
|
// (preferring the latter if it will fit in either, i.e. for a fully dynamic matrix type).
|
||||||
|
static EigenConformable<row_major> conformable(const array &a) {
|
||||||
|
const auto dims = a.ndim();
|
||||||
|
if (dims < 1 || dims > 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dims == 2) { // Matrix type: require exact match (or dynamic)
|
||||||
|
|
||||||
|
EigenIndex np_rows = a.shape(0), np_cols = a.shape(1),
|
||||||
|
np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)),
|
||||||
|
np_cstride = a.strides(1) / static_cast<ssize_t>(sizeof(Scalar));
|
||||||
|
if ((fixed_rows && np_rows != rows) || (fixed_cols && np_cols != cols)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {np_rows, np_cols, np_rstride, np_cstride};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we're storing an n-vector. Only one of the strides will be used, but
|
||||||
|
// whichever is used, we want the (single) numpy stride value.
|
||||||
|
const EigenIndex n = a.shape(0),
|
||||||
|
stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar));
|
||||||
|
|
||||||
|
if (vector) { // Eigen type is a compile-time vector
|
||||||
|
if (fixed && size != n) {
|
||||||
|
return false; // Vector size mismatch
|
||||||
|
}
|
||||||
|
return {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride};
|
||||||
|
}
|
||||||
|
if (fixed) {
|
||||||
|
// The type has a fixed size, but is not a vector: abort
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fixed_cols) {
|
||||||
|
// Since this isn't a vector, cols must be != 1. We allow this only if it exactly
|
||||||
|
// equals the number of elements (rows is Dynamic, and so 1 row is allowed).
|
||||||
|
if (cols != n) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return {1, n, stride};
|
||||||
|
} // Otherwise it's either fully dynamic, or column dynamic; both become a column vector
|
||||||
|
if (fixed_rows && rows != n) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return {n, 1, stride};
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr bool show_writeable
|
||||||
|
= is_eigen_dense_map<Type>::value && is_eigen_mutable_map<Type>::value;
|
||||||
|
static constexpr bool show_order = is_eigen_dense_map<Type>::value;
|
||||||
|
static constexpr bool show_c_contiguous = show_order && requires_row_major;
|
||||||
|
static constexpr bool show_f_contiguous
|
||||||
|
= !show_c_contiguous && show_order && requires_col_major;
|
||||||
|
|
||||||
|
static constexpr auto descriptor
|
||||||
|
= const_name("numpy.ndarray[") + npy_format_descriptor<Scalar>::name + const_name("[")
|
||||||
|
+ const_name<fixed_rows>(const_name<(size_t) rows>(), const_name("m")) + const_name(", ")
|
||||||
|
+ const_name<fixed_cols>(const_name<(size_t) cols>(), const_name("n")) + const_name("]")
|
||||||
|
+
|
||||||
|
// For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to
|
||||||
|
// be satisfied: writeable=True (for a mutable reference), and, depending on the map's
|
||||||
|
// stride options, possibly f_contiguous or c_contiguous. We include them in the
|
||||||
|
// descriptor output to provide some hint as to why a TypeError is occurring (otherwise
|
||||||
|
// it can be confusing to see that a function accepts a 'numpy.ndarray[float64[3,2]]' and
|
||||||
|
// an error message that you *gave* a numpy.ndarray of the right type and dimensions.
|
||||||
|
const_name<show_writeable>(", flags.writeable", "")
|
||||||
|
+ const_name<show_c_contiguous>(", flags.c_contiguous", "")
|
||||||
|
+ const_name<show_f_contiguous>(", flags.f_contiguous", "") + const_name("]");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Casts an Eigen type to numpy array. If given a base, the numpy array references the src data,
|
||||||
|
// otherwise it'll make a copy. writeable lets you turn off the writeable flag for the array.
|
||||||
|
template <typename props>
|
||||||
|
handle
|
||||||
|
eigen_array_cast(typename props::Type const &src, handle base = handle(), bool writeable = true) {
|
||||||
|
constexpr ssize_t elem_size = sizeof(typename props::Scalar);
|
||||||
|
array a;
|
||||||
|
if (props::vector) {
|
||||||
|
a = array({src.size()}, {elem_size * src.innerStride()}, src.data(), base);
|
||||||
|
} else {
|
||||||
|
a = array({src.rows(), src.cols()},
|
||||||
|
{elem_size * src.rowStride(), elem_size * src.colStride()},
|
||||||
|
src.data(),
|
||||||
|
base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!writeable) {
|
||||||
|
array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes an lvalue ref to some Eigen type and a (python) base object, creating a numpy array that
|
||||||
|
// reference the Eigen object's data with `base` as the python-registered base class (if omitted,
|
||||||
|
// the base will be set to None, and lifetime management is up to the caller). The numpy array is
|
||||||
|
// non-writeable if the given type is const.
|
||||||
|
template <typename props, typename Type>
|
||||||
|
handle eigen_ref_array(Type &src, handle parent = none()) {
|
||||||
|
// none here is to get past array's should-we-copy detection, which currently always
|
||||||
|
// copies when there is no base. Setting the base to None should be harmless.
|
||||||
|
return eigen_array_cast<props>(src, parent, !std::is_const<Type>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes a pointer to some dense, plain Eigen type, builds a capsule around it, then returns a
|
||||||
|
// numpy array that references the encapsulated data with a python-side reference to the capsule to
|
||||||
|
// tie its destruction to that of any dependent python objects. Const-ness is determined by
|
||||||
|
// whether or not the Type of the pointer given is const.
|
||||||
|
template <typename props, typename Type, typename = enable_if_t<is_eigen_dense_plain<Type>::value>>
|
||||||
|
handle eigen_encapsulate(Type *src) {
|
||||||
|
capsule base(src, [](void *o) { delete static_cast<Type *>(o); });
|
||||||
|
return eigen_ref_array<props>(*src, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type caster for regular, dense matrix types (e.g. MatrixXd), but not maps/refs/etc. of dense
|
||||||
|
// types.
|
||||||
|
template <typename Type>
|
||||||
|
struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> {
|
||||||
|
using Scalar = typename Type::Scalar;
|
||||||
|
static_assert(!std::is_pointer<Scalar>::value,
|
||||||
|
PYBIND11_EIGEN_MESSAGE_POINTER_TYPES_ARE_NOT_SUPPORTED);
|
||||||
|
using props = EigenProps<Type>;
|
||||||
|
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
// If we're in no-convert mode, only load if given an array of the correct type
|
||||||
|
if (!convert && !isinstance<array_t<Scalar>>(src)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coerce into an array, but don't do type conversion yet; the copy below handles it.
|
||||||
|
auto buf = array::ensure(src);
|
||||||
|
|
||||||
|
if (!buf) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dims = buf.ndim();
|
||||||
|
if (dims < 1 || dims > 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fits = props::conformable(buf);
|
||||||
|
if (!fits) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the new type, then build a numpy reference into it
|
||||||
|
value = Type(fits.rows, fits.cols);
|
||||||
|
auto ref = reinterpret_steal<array>(eigen_ref_array<props>(value));
|
||||||
|
if (dims == 1) {
|
||||||
|
ref = ref.squeeze();
|
||||||
|
} else if (ref.ndim() == 1) {
|
||||||
|
buf = buf.squeeze();
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = detail::npy_api::get().PyArray_CopyInto_(ref.ptr(), buf.ptr());
|
||||||
|
|
||||||
|
if (result < 0) { // Copy failed!
|
||||||
|
PyErr_Clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Cast implementation
|
||||||
|
template <typename CType>
|
||||||
|
static handle cast_impl(CType *src, return_value_policy policy, handle parent) {
|
||||||
|
switch (policy) {
|
||||||
|
case return_value_policy::take_ownership:
|
||||||
|
case return_value_policy::automatic:
|
||||||
|
return eigen_encapsulate<props>(src);
|
||||||
|
case return_value_policy::move:
|
||||||
|
return eigen_encapsulate<props>(new CType(std::move(*src)));
|
||||||
|
case return_value_policy::copy:
|
||||||
|
return eigen_array_cast<props>(*src);
|
||||||
|
case return_value_policy::reference:
|
||||||
|
case return_value_policy::automatic_reference:
|
||||||
|
return eigen_ref_array<props>(*src);
|
||||||
|
case return_value_policy::reference_internal:
|
||||||
|
return eigen_ref_array<props>(*src, parent);
|
||||||
|
default:
|
||||||
|
throw cast_error("unhandled return_value_policy: should not happen!");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Normal returned non-reference, non-const value:
|
||||||
|
static handle cast(Type &&src, return_value_policy /* policy */, handle parent) {
|
||||||
|
return cast_impl(&src, return_value_policy::move, parent);
|
||||||
|
}
|
||||||
|
// If you return a non-reference const, we mark the numpy array readonly:
|
||||||
|
static handle cast(const Type &&src, return_value_policy /* policy */, handle parent) {
|
||||||
|
return cast_impl(&src, return_value_policy::move, parent);
|
||||||
|
}
|
||||||
|
// lvalue reference return; default (automatic) becomes copy
|
||||||
|
static handle cast(Type &src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic
|
||||||
|
|| policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::copy;
|
||||||
|
}
|
||||||
|
return cast_impl(&src, policy, parent);
|
||||||
|
}
|
||||||
|
// const lvalue reference return; default (automatic) becomes copy
|
||||||
|
static handle cast(const Type &src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic
|
||||||
|
|| policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::copy;
|
||||||
|
}
|
||||||
|
return cast(&src, policy, parent);
|
||||||
|
}
|
||||||
|
// non-const pointer return
|
||||||
|
static handle cast(Type *src, return_value_policy policy, handle parent) {
|
||||||
|
return cast_impl(src, policy, parent);
|
||||||
|
}
|
||||||
|
// const pointer return
|
||||||
|
static handle cast(const Type *src, return_value_policy policy, handle parent) {
|
||||||
|
return cast_impl(src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto name = props::descriptor;
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
operator Type *() { return &value; }
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
operator Type &() { return value; }
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
operator Type &&() && { return std::move(value); }
|
||||||
|
template <typename T>
|
||||||
|
using cast_op_type = movable_cast_op_type<T>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Base class for casting reference/map/block/etc. objects back to python.
|
||||||
|
template <typename MapType>
|
||||||
|
struct eigen_map_caster {
|
||||||
|
static_assert(!std::is_pointer<typename MapType::Scalar>::value,
|
||||||
|
PYBIND11_EIGEN_MESSAGE_POINTER_TYPES_ARE_NOT_SUPPORTED);
|
||||||
|
|
||||||
|
private:
|
||||||
|
using props = EigenProps<MapType>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Directly referencing a ref/map's data is a bit dangerous (whatever the map/ref points to has
|
||||||
|
// to stay around), but we'll allow it under the assumption that you know what you're doing
|
||||||
|
// (and have an appropriate keep_alive in place). We return a numpy array pointing directly at
|
||||||
|
// the ref's data (The numpy array ends up read-only if the ref was to a const matrix type.)
|
||||||
|
// Note that this means you need to ensure you don't destroy the object in some other way (e.g.
|
||||||
|
// with an appropriate keep_alive, or with a reference to a statically allocated matrix).
|
||||||
|
static handle cast(const MapType &src, return_value_policy policy, handle parent) {
|
||||||
|
switch (policy) {
|
||||||
|
case return_value_policy::copy:
|
||||||
|
return eigen_array_cast<props>(src);
|
||||||
|
case return_value_policy::reference_internal:
|
||||||
|
return eigen_array_cast<props>(src, parent, is_eigen_mutable_map<MapType>::value);
|
||||||
|
case return_value_policy::reference:
|
||||||
|
case return_value_policy::automatic:
|
||||||
|
case return_value_policy::automatic_reference:
|
||||||
|
return eigen_array_cast<props>(src, none(), is_eigen_mutable_map<MapType>::value);
|
||||||
|
default:
|
||||||
|
// move, take_ownership don't make any sense for a ref/map:
|
||||||
|
pybind11_fail("Invalid return_value_policy for Eigen Map/Ref/Block type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto name = props::descriptor;
|
||||||
|
|
||||||
|
// Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return
|
||||||
|
// types but not bound arguments). We still provide them (with an explicitly delete) so that
|
||||||
|
// you end up here if you try anyway.
|
||||||
|
bool load(handle, bool) = delete;
|
||||||
|
operator MapType() = delete;
|
||||||
|
template <typename>
|
||||||
|
using cast_op_type = MapType;
|
||||||
|
};
|
||||||
|
|
||||||
|
// We can return any map-like object (but can only load Refs, specialized next):
|
||||||
|
template <typename Type>
|
||||||
|
struct type_caster<Type, enable_if_t<is_eigen_dense_map<Type>::value>> : eigen_map_caster<Type> {};
|
||||||
|
|
||||||
|
// Loader for Ref<...> arguments. See the documentation for info on how to make this work without
|
||||||
|
// copying (it requires some extra effort in many cases).
|
||||||
|
template <typename PlainObjectType, typename StrideType>
|
||||||
|
struct type_caster<
|
||||||
|
Eigen::Ref<PlainObjectType, 0, StrideType>,
|
||||||
|
enable_if_t<is_eigen_dense_map<Eigen::Ref<PlainObjectType, 0, StrideType>>::value>>
|
||||||
|
: public eigen_map_caster<Eigen::Ref<PlainObjectType, 0, StrideType>> {
|
||||||
|
private:
|
||||||
|
using Type = Eigen::Ref<PlainObjectType, 0, StrideType>;
|
||||||
|
using props = EigenProps<Type>;
|
||||||
|
using Scalar = typename props::Scalar;
|
||||||
|
static_assert(!std::is_pointer<Scalar>::value,
|
||||||
|
PYBIND11_EIGEN_MESSAGE_POINTER_TYPES_ARE_NOT_SUPPORTED);
|
||||||
|
using MapType = Eigen::Map<PlainObjectType, 0, StrideType>;
|
||||||
|
using Array
|
||||||
|
= array_t<Scalar,
|
||||||
|
array::forcecast
|
||||||
|
| ((props::row_major ? props::inner_stride : props::outer_stride) == 1
|
||||||
|
? array::c_style
|
||||||
|
: (props::row_major ? props::outer_stride : props::inner_stride) == 1
|
||||||
|
? array::f_style
|
||||||
|
: 0)>;
|
||||||
|
static constexpr bool need_writeable = is_eigen_mutable_map<Type>::value;
|
||||||
|
// Delay construction (these have no default constructor)
|
||||||
|
std::unique_ptr<MapType> map;
|
||||||
|
std::unique_ptr<Type> ref;
|
||||||
|
// Our array. When possible, this is just a numpy array pointing to the source data, but
|
||||||
|
// sometimes we can't avoid copying (e.g. input is not a numpy array at all, has an
|
||||||
|
// incompatible layout, or is an array of a type that needs to be converted). Using a numpy
|
||||||
|
// temporary (rather than an Eigen temporary) saves an extra copy when we need both type
|
||||||
|
// conversion and storage order conversion. (Note that we refuse to use this temporary copy
|
||||||
|
// when loading an argument for a Ref<M> with M non-const, i.e. a read-write reference).
|
||||||
|
Array copy_or_ref;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
// First check whether what we have is already an array of the right type. If not, we
|
||||||
|
// can't avoid a copy (because the copy is also going to do type conversion).
|
||||||
|
bool need_copy = !isinstance<Array>(src);
|
||||||
|
|
||||||
|
EigenConformable<props::row_major> fits;
|
||||||
|
if (!need_copy) {
|
||||||
|
// We don't need a converting copy, but we also need to check whether the strides are
|
||||||
|
// compatible with the Ref's stride requirements
|
||||||
|
auto aref = reinterpret_borrow<Array>(src);
|
||||||
|
|
||||||
|
if (aref && (!need_writeable || aref.writeable())) {
|
||||||
|
fits = props::conformable(aref);
|
||||||
|
if (!fits) {
|
||||||
|
return false; // Incompatible dimensions
|
||||||
|
}
|
||||||
|
if (!fits.template stride_compatible<props>()) {
|
||||||
|
need_copy = true;
|
||||||
|
} else {
|
||||||
|
copy_or_ref = std::move(aref);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
need_copy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_copy) {
|
||||||
|
// We need to copy: If we need a mutable reference, or we're not supposed to convert
|
||||||
|
// (either because we're in the no-convert overload pass, or because we're explicitly
|
||||||
|
// instructed not to copy (via `py::arg().noconvert()`) we have to fail loading.
|
||||||
|
if (!convert || need_writeable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array copy = Array::ensure(src);
|
||||||
|
if (!copy) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fits = props::conformable(copy);
|
||||||
|
if (!fits || !fits.template stride_compatible<props>()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
copy_or_ref = std::move(copy);
|
||||||
|
loader_life_support::add_patient(copy_or_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.reset();
|
||||||
|
map.reset(new MapType(data(copy_or_ref),
|
||||||
|
fits.rows,
|
||||||
|
fits.cols,
|
||||||
|
make_stride(fits.stride.outer(), fits.stride.inner())));
|
||||||
|
ref.reset(new Type(*map));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
operator Type *() { return ref.get(); }
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
operator Type &() { return *ref; }
|
||||||
|
template <typename _T>
|
||||||
|
using cast_op_type = pybind11::detail::cast_op_type<_T>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T = Type, enable_if_t<is_eigen_mutable_map<T>::value, int> = 0>
|
||||||
|
Scalar *data(Array &a) {
|
||||||
|
return a.mutable_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = Type, enable_if_t<!is_eigen_mutable_map<T>::value, int> = 0>
|
||||||
|
const Scalar *data(Array &a) {
|
||||||
|
return a.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to figure out a constructor of `Stride` that will work.
|
||||||
|
// If both strides are fixed, use a default constructor:
|
||||||
|
template <typename S>
|
||||||
|
using stride_ctor_default = bool_constant<S::InnerStrideAtCompileTime != Eigen::Dynamic
|
||||||
|
&& S::OuterStrideAtCompileTime != Eigen::Dynamic
|
||||||
|
&& std::is_default_constructible<S>::value>;
|
||||||
|
// Otherwise, if there is a two-index constructor, assume it is (outer,inner) like
|
||||||
|
// Eigen::Stride, and use it:
|
||||||
|
template <typename S>
|
||||||
|
using stride_ctor_dual
|
||||||
|
= bool_constant<!stride_ctor_default<S>::value
|
||||||
|
&& std::is_constructible<S, EigenIndex, EigenIndex>::value>;
|
||||||
|
// Otherwise, if there is a one-index constructor, and just one of the strides is dynamic, use
|
||||||
|
// it (passing whichever stride is dynamic).
|
||||||
|
template <typename S>
|
||||||
|
using stride_ctor_outer
|
||||||
|
= bool_constant<!any_of<stride_ctor_default<S>, stride_ctor_dual<S>>::value
|
||||||
|
&& S::OuterStrideAtCompileTime == Eigen::Dynamic
|
||||||
|
&& S::InnerStrideAtCompileTime != Eigen::Dynamic
|
||||||
|
&& std::is_constructible<S, EigenIndex>::value>;
|
||||||
|
template <typename S>
|
||||||
|
using stride_ctor_inner
|
||||||
|
= bool_constant<!any_of<stride_ctor_default<S>, stride_ctor_dual<S>>::value
|
||||||
|
&& S::InnerStrideAtCompileTime == Eigen::Dynamic
|
||||||
|
&& S::OuterStrideAtCompileTime != Eigen::Dynamic
|
||||||
|
&& std::is_constructible<S, EigenIndex>::value>;
|
||||||
|
|
||||||
|
template <typename S = StrideType, enable_if_t<stride_ctor_default<S>::value, int> = 0>
|
||||||
|
static S make_stride(EigenIndex, EigenIndex) {
|
||||||
|
return S();
|
||||||
|
}
|
||||||
|
template <typename S = StrideType, enable_if_t<stride_ctor_dual<S>::value, int> = 0>
|
||||||
|
static S make_stride(EigenIndex outer, EigenIndex inner) {
|
||||||
|
return S(outer, inner);
|
||||||
|
}
|
||||||
|
template <typename S = StrideType, enable_if_t<stride_ctor_outer<S>::value, int> = 0>
|
||||||
|
static S make_stride(EigenIndex outer, EigenIndex) {
|
||||||
|
return S(outer);
|
||||||
|
}
|
||||||
|
template <typename S = StrideType, enable_if_t<stride_ctor_inner<S>::value, int> = 0>
|
||||||
|
static S make_stride(EigenIndex, EigenIndex inner) {
|
||||||
|
return S(inner);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// type_caster for special matrix types (e.g. DiagonalMatrix), which are EigenBase, but not
|
||||||
|
// EigenDense (i.e. they don't have a data(), at least not with the usual matrix layout).
|
||||||
|
// load() is not supported, but we can cast them into the python domain by first copying to a
|
||||||
|
// regular Eigen::Matrix, then casting that.
|
||||||
|
template <typename Type>
|
||||||
|
struct type_caster<Type, enable_if_t<is_eigen_other<Type>::value>> {
|
||||||
|
static_assert(!std::is_pointer<typename Type::Scalar>::value,
|
||||||
|
PYBIND11_EIGEN_MESSAGE_POINTER_TYPES_ARE_NOT_SUPPORTED);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using Matrix
|
||||||
|
= Eigen::Matrix<typename Type::Scalar, Type::RowsAtCompileTime, Type::ColsAtCompileTime>;
|
||||||
|
using props = EigenProps<Matrix>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
handle h = eigen_encapsulate<props>(new Matrix(src));
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
static handle cast(const Type *src, return_value_policy policy, handle parent) {
|
||||||
|
return cast(*src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto name = props::descriptor;
|
||||||
|
|
||||||
|
// Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return
|
||||||
|
// types but not bound arguments). We still provide them (with an explicitly delete) so that
|
||||||
|
// you end up here if you try anyway.
|
||||||
|
bool load(handle, bool) = delete;
|
||||||
|
operator Type() = delete;
|
||||||
|
template <typename>
|
||||||
|
using cast_op_type = Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||||
|
using Scalar = typename Type::Scalar;
|
||||||
|
static_assert(!std::is_pointer<Scalar>::value,
|
||||||
|
PYBIND11_EIGEN_MESSAGE_POINTER_TYPES_ARE_NOT_SUPPORTED);
|
||||||
|
using StorageIndex = remove_reference_t<decltype(*std::declval<Type>().outerIndexPtr())>;
|
||||||
|
using Index = typename Type::Index;
|
||||||
|
static constexpr bool rowMajor = Type::IsRowMajor;
|
||||||
|
|
||||||
|
bool load(handle src, bool) {
|
||||||
|
if (!src) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto obj = reinterpret_borrow<object>(src);
|
||||||
|
object sparse_module = module_::import("scipy.sparse");
|
||||||
|
object matrix_type = sparse_module.attr(rowMajor ? "csr_matrix" : "csc_matrix");
|
||||||
|
|
||||||
|
if (!type::handle_of(obj).is(matrix_type)) {
|
||||||
|
try {
|
||||||
|
obj = matrix_type(obj);
|
||||||
|
} catch (const error_already_set &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto values = array_t<Scalar>((object) obj.attr("data"));
|
||||||
|
auto innerIndices = array_t<StorageIndex>((object) obj.attr("indices"));
|
||||||
|
auto outerIndices = array_t<StorageIndex>((object) obj.attr("indptr"));
|
||||||
|
auto shape = pybind11::tuple((pybind11::object) obj.attr("shape"));
|
||||||
|
auto nnz = obj.attr("nnz").cast<Index>();
|
||||||
|
|
||||||
|
if (!values || !innerIndices || !outerIndices) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = EigenMapSparseMatrix<Scalar,
|
||||||
|
Type::Flags &(Eigen::RowMajor | Eigen::ColMajor),
|
||||||
|
StorageIndex>(shape[0].cast<Index>(),
|
||||||
|
shape[1].cast<Index>(),
|
||||||
|
std::move(nnz),
|
||||||
|
outerIndices.mutable_data(),
|
||||||
|
innerIndices.mutable_data(),
|
||||||
|
values.mutable_data());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
const_cast<Type &>(src).makeCompressed();
|
||||||
|
|
||||||
|
object matrix_type
|
||||||
|
= module_::import("scipy.sparse").attr(rowMajor ? "csr_matrix" : "csc_matrix");
|
||||||
|
|
||||||
|
array data(src.nonZeros(), src.valuePtr());
|
||||||
|
array outerIndices((rowMajor ? src.rows() : src.cols()) + 1, src.outerIndexPtr());
|
||||||
|
array innerIndices(src.nonZeros(), src.innerIndexPtr());
|
||||||
|
|
||||||
|
return matrix_type(pybind11::make_tuple(
|
||||||
|
std::move(data), std::move(innerIndices), std::move(outerIndices)),
|
||||||
|
pybind11::make_tuple(src.rows(), src.cols()))
|
||||||
|
.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(Type,
|
||||||
|
const_name<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[",
|
||||||
|
"scipy.sparse.csc_matrix[")
|
||||||
|
+ npy_format_descriptor<Scalar>::name + const_name("]"));
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
516
3rdparty/pybind11/include/pybind11/eigen/tensor.h
vendored
Normal file
516
3rdparty/pybind11/include/pybind11/eigen/tensor.h
vendored
Normal file
@ -0,0 +1,516 @@
|
|||||||
|
/*
|
||||||
|
pybind11/eigen/tensor.h: Transparent conversion for Eigen tensors
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../numpy.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
|
||||||
|
static_assert(__GNUC__ > 5, "Eigen Tensor support in pybind11 requires GCC > 5.0");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Disable warnings for Eigen
|
||||||
|
PYBIND11_WARNING_PUSH
|
||||||
|
PYBIND11_WARNING_DISABLE_MSVC(4554)
|
||||||
|
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
PYBIND11_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <unsupported/Eigen/CXX11/Tensor>
|
||||||
|
|
||||||
|
PYBIND11_WARNING_POP
|
||||||
|
|
||||||
|
static_assert(EIGEN_VERSION_AT_LEAST(3, 3, 0),
|
||||||
|
"Eigen Tensor support in pybind11 requires Eigen >= 3.3.0");
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
inline bool is_tensor_aligned(const void *data) {
|
||||||
|
return (reinterpret_cast<std::size_t>(data) % EIGEN_DEFAULT_ALIGN_BYTES) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr int compute_array_flag_from_tensor() {
|
||||||
|
static_assert((static_cast<int>(T::Layout) == static_cast<int>(Eigen::RowMajor))
|
||||||
|
|| (static_cast<int>(T::Layout) == static_cast<int>(Eigen::ColMajor)),
|
||||||
|
"Layout must be row or column major");
|
||||||
|
return (static_cast<int>(T::Layout) == static_cast<int>(Eigen::RowMajor)) ? array::c_style
|
||||||
|
: array::f_style;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct eigen_tensor_helper {};
|
||||||
|
|
||||||
|
template <typename Scalar_, int NumIndices_, int Options_, typename IndexType>
|
||||||
|
struct eigen_tensor_helper<Eigen::Tensor<Scalar_, NumIndices_, Options_, IndexType>> {
|
||||||
|
using Type = Eigen::Tensor<Scalar_, NumIndices_, Options_, IndexType>;
|
||||||
|
using ValidType = void;
|
||||||
|
|
||||||
|
static Eigen::DSizes<typename Type::Index, Type::NumIndices> get_shape(const Type &f) {
|
||||||
|
return f.dimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr bool
|
||||||
|
is_correct_shape(const Eigen::DSizes<typename Type::Index, Type::NumIndices> & /*shape*/) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct helper {};
|
||||||
|
|
||||||
|
template <size_t... Is>
|
||||||
|
struct helper<index_sequence<Is...>> {
|
||||||
|
static constexpr auto value = concat(const_name(((void) Is, "?"))...);
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr auto dimensions_descriptor
|
||||||
|
= helper<decltype(make_index_sequence<Type::NumIndices>())>::value;
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
static Type *alloc(Args &&...args) {
|
||||||
|
return new Type(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free(Type *tensor) { delete tensor; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Scalar_, typename std::ptrdiff_t... Indices, int Options_, typename IndexType>
|
||||||
|
struct eigen_tensor_helper<
|
||||||
|
Eigen::TensorFixedSize<Scalar_, Eigen::Sizes<Indices...>, Options_, IndexType>> {
|
||||||
|
using Type = Eigen::TensorFixedSize<Scalar_, Eigen::Sizes<Indices...>, Options_, IndexType>;
|
||||||
|
using ValidType = void;
|
||||||
|
|
||||||
|
static constexpr Eigen::DSizes<typename Type::Index, Type::NumIndices>
|
||||||
|
get_shape(const Type & /*f*/) {
|
||||||
|
return get_shape();
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr Eigen::DSizes<typename Type::Index, Type::NumIndices> get_shape() {
|
||||||
|
return Eigen::DSizes<typename Type::Index, Type::NumIndices>(Indices...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_correct_shape(const Eigen::DSizes<typename Type::Index, Type::NumIndices> &shape) {
|
||||||
|
return get_shape() == shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto dimensions_descriptor = concat(const_name<Indices>()...);
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
static Type *alloc(Args &&...args) {
|
||||||
|
Eigen::aligned_allocator<Type> allocator;
|
||||||
|
return ::new (allocator.allocate(1)) Type(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free(Type *tensor) {
|
||||||
|
Eigen::aligned_allocator<Type> allocator;
|
||||||
|
tensor->~Type();
|
||||||
|
allocator.deallocate(tensor, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type, bool ShowDetails, bool NeedsWriteable = false>
|
||||||
|
struct get_tensor_descriptor {
|
||||||
|
static constexpr auto details
|
||||||
|
= const_name<NeedsWriteable>(", flags.writeable", "")
|
||||||
|
+ const_name<static_cast<int>(Type::Layout) == static_cast<int>(Eigen::RowMajor)>(
|
||||||
|
", flags.c_contiguous", ", flags.f_contiguous");
|
||||||
|
static constexpr auto value
|
||||||
|
= const_name("numpy.ndarray[") + npy_format_descriptor<typename Type::Scalar>::name
|
||||||
|
+ const_name("[") + eigen_tensor_helper<remove_cv_t<Type>>::dimensions_descriptor
|
||||||
|
+ const_name("]") + const_name<ShowDetails>(details, const_name("")) + const_name("]");
|
||||||
|
};
|
||||||
|
|
||||||
|
// When EIGEN_AVOID_STL_ARRAY is defined, Eigen::DSizes<T, 0> does not have the begin() member
|
||||||
|
// function. Falling back to a simple loop works around this issue.
|
||||||
|
//
|
||||||
|
// We need to disable the type-limits warning for the inner loop when size = 0.
|
||||||
|
|
||||||
|
PYBIND11_WARNING_PUSH
|
||||||
|
PYBIND11_WARNING_DISABLE_GCC("-Wtype-limits")
|
||||||
|
|
||||||
|
template <typename T, int size>
|
||||||
|
std::vector<T> convert_dsizes_to_vector(const Eigen::DSizes<T, size> &arr) {
|
||||||
|
std::vector<T> result(size);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
result[i] = arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int size>
|
||||||
|
Eigen::DSizes<T, size> get_shape_for_array(const array &arr) {
|
||||||
|
Eigen::DSizes<T, size> result;
|
||||||
|
const T *shape = arr.shape();
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
result[i] = shape[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_WARNING_POP
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
|
||||||
|
static_assert(!std::is_pointer<typename Type::Scalar>::value,
|
||||||
|
PYBIND11_EIGEN_MESSAGE_POINTER_TYPES_ARE_NOT_SUPPORTED);
|
||||||
|
using Helper = eigen_tensor_helper<Type>;
|
||||||
|
static constexpr auto temp_name = get_tensor_descriptor<Type, false>::value;
|
||||||
|
PYBIND11_TYPE_CASTER(Type, temp_name);
|
||||||
|
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
if (!convert) {
|
||||||
|
if (!isinstance<array>(src)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
array temp = array::ensure(src);
|
||||||
|
if (!temp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!temp.dtype().is(dtype::of<typename Type::Scalar>())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_t<typename Type::Scalar, compute_array_flag_from_tensor<Type>()> arr(
|
||||||
|
reinterpret_borrow<object>(src));
|
||||||
|
|
||||||
|
if (arr.ndim() != Type::NumIndices) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto shape = get_shape_for_array<typename Type::Index, Type::NumIndices>(arr);
|
||||||
|
|
||||||
|
if (!Helper::is_correct_shape(shape)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if EIGEN_VERSION_AT_LEAST(3, 4, 0)
|
||||||
|
auto data_pointer = arr.data();
|
||||||
|
#else
|
||||||
|
// Handle Eigen bug
|
||||||
|
auto data_pointer = const_cast<typename Type::Scalar *>(arr.data());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (is_tensor_aligned(arr.data())) {
|
||||||
|
value = Eigen::TensorMap<const Type, Eigen::Aligned>(data_pointer, shape);
|
||||||
|
} else {
|
||||||
|
value = Eigen::TensorMap<const Type>(data_pointer, shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(Type &&src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::reference
|
||||||
|
|| policy == return_value_policy::reference_internal) {
|
||||||
|
pybind11_fail("Cannot use a reference return value policy for an rvalue");
|
||||||
|
}
|
||||||
|
return cast_impl(&src, return_value_policy::move, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(const Type &&src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::reference
|
||||||
|
|| policy == return_value_policy::reference_internal) {
|
||||||
|
pybind11_fail("Cannot use a reference return value policy for an rvalue");
|
||||||
|
}
|
||||||
|
return cast_impl(&src, return_value_policy::move, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(Type &src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic
|
||||||
|
|| policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::copy;
|
||||||
|
}
|
||||||
|
return cast_impl(&src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(const Type &src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic
|
||||||
|
|| policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::copy;
|
||||||
|
}
|
||||||
|
return cast(&src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(Type *src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic) {
|
||||||
|
policy = return_value_policy::take_ownership;
|
||||||
|
} else if (policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::reference;
|
||||||
|
}
|
||||||
|
return cast_impl(src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(const Type *src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic) {
|
||||||
|
policy = return_value_policy::take_ownership;
|
||||||
|
} else if (policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::reference;
|
||||||
|
}
|
||||||
|
return cast_impl(src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C>
|
||||||
|
static handle cast_impl(C *src, return_value_policy policy, handle parent) {
|
||||||
|
object parent_object;
|
||||||
|
bool writeable = false;
|
||||||
|
switch (policy) {
|
||||||
|
case return_value_policy::move:
|
||||||
|
if (std::is_const<C>::value) {
|
||||||
|
pybind11_fail("Cannot move from a constant reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
src = Helper::alloc(std::move(*src));
|
||||||
|
|
||||||
|
parent_object
|
||||||
|
= capsule(src, [](void *ptr) { Helper::free(reinterpret_cast<Type *>(ptr)); });
|
||||||
|
writeable = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case return_value_policy::take_ownership:
|
||||||
|
if (std::is_const<C>::value) {
|
||||||
|
// This cast is ugly, and might be UB in some cases, but we don't have an
|
||||||
|
// alternative here as we must free that memory
|
||||||
|
Helper::free(const_cast<Type *>(src));
|
||||||
|
pybind11_fail("Cannot take ownership of a const reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_object
|
||||||
|
= capsule(src, [](void *ptr) { Helper::free(reinterpret_cast<Type *>(ptr)); });
|
||||||
|
writeable = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case return_value_policy::copy:
|
||||||
|
writeable = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case return_value_policy::reference:
|
||||||
|
parent_object = none();
|
||||||
|
writeable = !std::is_const<C>::value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case return_value_policy::reference_internal:
|
||||||
|
// Default should do the right thing
|
||||||
|
if (!parent) {
|
||||||
|
pybind11_fail("Cannot use reference internal when there is no parent");
|
||||||
|
}
|
||||||
|
parent_object = reinterpret_borrow<object>(parent);
|
||||||
|
writeable = !std::is_const<C>::value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pybind11_fail("pybind11 bug in eigen.h, please file a bug report");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = array_t<typename Type::Scalar, compute_array_flag_from_tensor<Type>()>(
|
||||||
|
convert_dsizes_to_vector(Helper::get_shape(*src)), src->data(), parent_object);
|
||||||
|
|
||||||
|
if (!writeable) {
|
||||||
|
array_proxy(result.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.release();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename StoragePointerType,
|
||||||
|
bool needs_writeable,
|
||||||
|
enable_if_t<!needs_writeable, bool> = true>
|
||||||
|
StoragePointerType get_array_data_for_type(array &arr) {
|
||||||
|
#if EIGEN_VERSION_AT_LEAST(3, 4, 0)
|
||||||
|
return reinterpret_cast<StoragePointerType>(arr.data());
|
||||||
|
#else
|
||||||
|
// Handle Eigen bug
|
||||||
|
return reinterpret_cast<StoragePointerType>(const_cast<void *>(arr.data()));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename StoragePointerType,
|
||||||
|
bool needs_writeable,
|
||||||
|
enable_if_t<needs_writeable, bool> = true>
|
||||||
|
StoragePointerType get_array_data_for_type(array &arr) {
|
||||||
|
return reinterpret_cast<StoragePointerType>(arr.mutable_data());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct get_storage_pointer_type;
|
||||||
|
|
||||||
|
template <typename MapType>
|
||||||
|
struct get_storage_pointer_type<MapType, void_t<typename MapType::StoragePointerType>> {
|
||||||
|
using SPT = typename MapType::StoragePointerType;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename MapType>
|
||||||
|
struct get_storage_pointer_type<MapType, void_t<typename MapType::PointerArgType>> {
|
||||||
|
using SPT = typename MapType::PointerArgType;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type, int Options>
|
||||||
|
struct type_caster<Eigen::TensorMap<Type, Options>,
|
||||||
|
typename eigen_tensor_helper<remove_cv_t<Type>>::ValidType> {
|
||||||
|
static_assert(!std::is_pointer<typename Type::Scalar>::value,
|
||||||
|
PYBIND11_EIGEN_MESSAGE_POINTER_TYPES_ARE_NOT_SUPPORTED);
|
||||||
|
using MapType = Eigen::TensorMap<Type, Options>;
|
||||||
|
using Helper = eigen_tensor_helper<remove_cv_t<Type>>;
|
||||||
|
|
||||||
|
bool load(handle src, bool /*convert*/) {
|
||||||
|
// Note that we have a lot more checks here as we want to make sure to avoid copies
|
||||||
|
if (!isinstance<array>(src)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto arr = reinterpret_borrow<array>(src);
|
||||||
|
if ((arr.flags() & compute_array_flag_from_tensor<Type>()) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arr.dtype().is(dtype::of<typename Type::Scalar>())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arr.ndim() != Type::NumIndices) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool is_aligned = (Options & Eigen::Aligned) != 0;
|
||||||
|
|
||||||
|
if (is_aligned && !is_tensor_aligned(arr.data())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shape = get_shape_for_array<typename Type::Index, Type::NumIndices>(arr);
|
||||||
|
|
||||||
|
if (!Helper::is_correct_shape(shape)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needs_writeable && !arr.writeable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = get_array_data_for_type<typename get_storage_pointer_type<MapType>::SPT,
|
||||||
|
needs_writeable>(arr);
|
||||||
|
|
||||||
|
value.reset(new MapType(std::move(result), std::move(shape)));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(MapType &&src, return_value_policy policy, handle parent) {
|
||||||
|
return cast_impl(&src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(const MapType &&src, return_value_policy policy, handle parent) {
|
||||||
|
return cast_impl(&src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(MapType &src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic
|
||||||
|
|| policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::copy;
|
||||||
|
}
|
||||||
|
return cast_impl(&src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(const MapType &src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic
|
||||||
|
|| policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::copy;
|
||||||
|
}
|
||||||
|
return cast(&src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(MapType *src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic) {
|
||||||
|
policy = return_value_policy::take_ownership;
|
||||||
|
} else if (policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::reference;
|
||||||
|
}
|
||||||
|
return cast_impl(src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(const MapType *src, return_value_policy policy, handle parent) {
|
||||||
|
if (policy == return_value_policy::automatic) {
|
||||||
|
policy = return_value_policy::take_ownership;
|
||||||
|
} else if (policy == return_value_policy::automatic_reference) {
|
||||||
|
policy = return_value_policy::reference;
|
||||||
|
}
|
||||||
|
return cast_impl(src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C>
|
||||||
|
static handle cast_impl(C *src, return_value_policy policy, handle parent) {
|
||||||
|
object parent_object;
|
||||||
|
constexpr bool writeable = !std::is_const<C>::value;
|
||||||
|
switch (policy) {
|
||||||
|
case return_value_policy::reference:
|
||||||
|
parent_object = none();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case return_value_policy::reference_internal:
|
||||||
|
// Default should do the right thing
|
||||||
|
if (!parent) {
|
||||||
|
pybind11_fail("Cannot use reference internal when there is no parent");
|
||||||
|
}
|
||||||
|
parent_object = reinterpret_borrow<object>(parent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case return_value_policy::take_ownership:
|
||||||
|
delete src;
|
||||||
|
// fallthrough
|
||||||
|
default:
|
||||||
|
// move, take_ownership don't make any sense for a ref/map:
|
||||||
|
pybind11_fail("Invalid return_value_policy for Eigen Map type, must be either "
|
||||||
|
"reference or reference_internal");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = array_t<typename Type::Scalar, compute_array_flag_from_tensor<Type>()>(
|
||||||
|
convert_dsizes_to_vector(Helper::get_shape(*src)),
|
||||||
|
src->data(),
|
||||||
|
std::move(parent_object));
|
||||||
|
|
||||||
|
if (!writeable) {
|
||||||
|
array_proxy(result.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if EIGEN_VERSION_AT_LEAST(3, 4, 0)
|
||||||
|
|
||||||
|
static constexpr bool needs_writeable = !std::is_const<typename std::remove_pointer<
|
||||||
|
typename get_storage_pointer_type<MapType>::SPT>::type>::value;
|
||||||
|
#else
|
||||||
|
// Handle Eigen bug
|
||||||
|
static constexpr bool needs_writeable = !std::is_const<Type>::value;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// TODO: Move to std::optional once std::optional has more support
|
||||||
|
std::unique_ptr<MapType> value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr auto name = get_tensor_descriptor<Type, true, needs_writeable>::value;
|
||||||
|
explicit operator MapType *() { return value.get(); }
|
||||||
|
explicit operator MapType &() { return *value; }
|
||||||
|
explicit operator MapType &&() && { return std::move(*value); }
|
||||||
|
|
||||||
|
template <typename T_>
|
||||||
|
using cast_op_type = ::pybind11::detail::movable_cast_op_type<T_>;
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
316
3rdparty/pybind11/include/pybind11/embed.h
vendored
Normal file
316
3rdparty/pybind11/include/pybind11/embed.h
vendored
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
/*
|
||||||
|
pybind11/embed.h: Support for embedding the interpreter
|
||||||
|
|
||||||
|
Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pybind11.h"
|
||||||
|
#include "eval.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if defined(PYPY_VERSION)
|
||||||
|
# error Embedding the interpreter is not supported with PyPy
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
|
||||||
|
extern "C" PyObject *pybind11_init_impl_##name(); \
|
||||||
|
extern "C" PyObject *pybind11_init_impl_##name() { return pybind11_init_wrapper_##name(); }
|
||||||
|
|
||||||
|
/** \rst
|
||||||
|
Add a new module to the table of builtins for the interpreter. Must be
|
||||||
|
defined in global scope. The first macro parameter is the name of the
|
||||||
|
module (without quotes). The second parameter is the variable which will
|
||||||
|
be used as the interface to add functions and classes to the module.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_EMBEDDED_MODULE(example, m) {
|
||||||
|
// ... initialize functions and classes here
|
||||||
|
m.def("foo", []() {
|
||||||
|
return "Hello, World!";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
\endrst */
|
||||||
|
#define PYBIND11_EMBEDDED_MODULE(name, variable) \
|
||||||
|
static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name); \
|
||||||
|
static void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ &); \
|
||||||
|
static PyObject PYBIND11_CONCAT(*pybind11_init_wrapper_, name)() { \
|
||||||
|
auto m = ::pybind11::module_::create_extension_module( \
|
||||||
|
PYBIND11_TOSTRING(name), nullptr, &PYBIND11_CONCAT(pybind11_module_def_, name)); \
|
||||||
|
try { \
|
||||||
|
PYBIND11_CONCAT(pybind11_init_, name)(m); \
|
||||||
|
return m.ptr(); \
|
||||||
|
} \
|
||||||
|
PYBIND11_CATCH_INIT_EXCEPTIONS \
|
||||||
|
} \
|
||||||
|
PYBIND11_EMBEDDED_MODULE_IMPL(name) \
|
||||||
|
::pybind11::detail::embedded_module PYBIND11_CONCAT(pybind11_module_, name)( \
|
||||||
|
PYBIND11_TOSTRING(name), PYBIND11_CONCAT(pybind11_init_impl_, name)); \
|
||||||
|
void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ \
|
||||||
|
& variable) // NOLINT(bugprone-macro-parentheses)
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
/// Python 2.7/3.x compatible version of `PyImport_AppendInittab` and error checks.
|
||||||
|
struct embedded_module {
|
||||||
|
using init_t = PyObject *(*) ();
|
||||||
|
embedded_module(const char *name, init_t init) {
|
||||||
|
if (Py_IsInitialized() != 0) {
|
||||||
|
pybind11_fail("Can't add new modules after the interpreter has been initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = PyImport_AppendInittab(name, init);
|
||||||
|
if (result == -1) {
|
||||||
|
pybind11_fail("Insufficient memory to add a new module");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wide_char_arg_deleter {
|
||||||
|
void operator()(wchar_t *ptr) const {
|
||||||
|
// API docs: https://docs.python.org/3/c-api/sys.html#c.Py_DecodeLocale
|
||||||
|
PyMem_RawFree(ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline wchar_t *widen_chars(const char *safe_arg) {
|
||||||
|
wchar_t *widened_arg = Py_DecodeLocale(safe_arg, nullptr);
|
||||||
|
return widened_arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void precheck_interpreter() {
|
||||||
|
if (Py_IsInitialized() != 0) {
|
||||||
|
pybind11_fail("The interpreter is already running");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX)
|
||||||
|
# define PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX (0x03080000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX < PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
|
||||||
|
inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers,
|
||||||
|
int argc,
|
||||||
|
const char *const *argv,
|
||||||
|
bool add_program_dir_to_path) {
|
||||||
|
detail::precheck_interpreter();
|
||||||
|
Py_InitializeEx(init_signal_handlers ? 1 : 0);
|
||||||
|
# if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000
|
||||||
|
PyEval_InitThreads();
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// Before it was special-cased in python 3.8, passing an empty or null argv
|
||||||
|
// caused a segfault, so we have to reimplement the special case ourselves.
|
||||||
|
bool special_case = (argv == nullptr || argc <= 0);
|
||||||
|
|
||||||
|
const char *const empty_argv[]{"\0"};
|
||||||
|
const char *const *safe_argv = special_case ? empty_argv : argv;
|
||||||
|
if (special_case) {
|
||||||
|
argc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto argv_size = static_cast<size_t>(argc);
|
||||||
|
// SetArgv* on python 3 takes wchar_t, so we have to convert.
|
||||||
|
std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]);
|
||||||
|
std::vector<std::unique_ptr<wchar_t[], detail::wide_char_arg_deleter>> widened_argv_entries;
|
||||||
|
widened_argv_entries.reserve(argv_size);
|
||||||
|
for (size_t ii = 0; ii < argv_size; ++ii) {
|
||||||
|
widened_argv_entries.emplace_back(detail::widen_chars(safe_argv[ii]));
|
||||||
|
if (!widened_argv_entries.back()) {
|
||||||
|
// A null here indicates a character-encoding failure or the python
|
||||||
|
// interpreter out of memory. Give up.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
widened_argv[ii] = widened_argv_entries.back().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *pysys_argv = widened_argv.get();
|
||||||
|
|
||||||
|
PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
|
||||||
|
inline void initialize_interpreter(PyConfig *config,
|
||||||
|
int argc = 0,
|
||||||
|
const char *const *argv = nullptr,
|
||||||
|
bool add_program_dir_to_path = true) {
|
||||||
|
detail::precheck_interpreter();
|
||||||
|
PyStatus status = PyConfig_SetBytesArgv(config, argc, const_cast<char *const *>(argv));
|
||||||
|
if (PyStatus_Exception(status) != 0) {
|
||||||
|
// A failure here indicates a character-encoding failure or the python
|
||||||
|
// interpreter out of memory. Give up.
|
||||||
|
PyConfig_Clear(config);
|
||||||
|
throw std::runtime_error(PyStatus_IsError(status) != 0 ? status.err_msg
|
||||||
|
: "Failed to prepare CPython");
|
||||||
|
}
|
||||||
|
status = Py_InitializeFromConfig(config);
|
||||||
|
if (PyStatus_Exception(status) != 0) {
|
||||||
|
PyConfig_Clear(config);
|
||||||
|
throw std::runtime_error(PyStatus_IsError(status) != 0 ? status.err_msg
|
||||||
|
: "Failed to init CPython");
|
||||||
|
}
|
||||||
|
if (add_program_dir_to_path) {
|
||||||
|
PyRun_SimpleString("import sys, os.path; "
|
||||||
|
"sys.path.insert(0, "
|
||||||
|
"os.path.abspath(os.path.dirname(sys.argv[0])) "
|
||||||
|
"if sys.argv and os.path.exists(sys.argv[0]) else '')");
|
||||||
|
}
|
||||||
|
PyConfig_Clear(config);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** \rst
|
||||||
|
Initialize the Python interpreter. No other pybind11 or CPython API functions can be
|
||||||
|
called before this is done; with the exception of `PYBIND11_EMBEDDED_MODULE`. The
|
||||||
|
optional `init_signal_handlers` parameter can be used to skip the registration of
|
||||||
|
signal handlers (see the `Python documentation`_ for details). Calling this function
|
||||||
|
again after the interpreter has already been initialized is a fatal error.
|
||||||
|
|
||||||
|
If initializing the Python interpreter fails, then the program is terminated. (This
|
||||||
|
is controlled by the CPython runtime and is an exception to pybind11's normal behavior
|
||||||
|
of throwing exceptions on errors.)
|
||||||
|
|
||||||
|
The remaining optional parameters, `argc`, `argv`, and `add_program_dir_to_path` are
|
||||||
|
used to populate ``sys.argv`` and ``sys.path``.
|
||||||
|
See the |PySys_SetArgvEx documentation|_ for details.
|
||||||
|
|
||||||
|
.. _Python documentation: https://docs.python.org/3/c-api/init.html#c.Py_InitializeEx
|
||||||
|
.. |PySys_SetArgvEx documentation| replace:: ``PySys_SetArgvEx`` documentation
|
||||||
|
.. _PySys_SetArgvEx documentation: https://docs.python.org/3/c-api/init.html#c.PySys_SetArgvEx
|
||||||
|
\endrst */
|
||||||
|
inline void initialize_interpreter(bool init_signal_handlers = true,
|
||||||
|
int argc = 0,
|
||||||
|
const char *const *argv = nullptr,
|
||||||
|
bool add_program_dir_to_path = true) {
|
||||||
|
#if PY_VERSION_HEX < PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
|
||||||
|
detail::initialize_interpreter_pre_pyconfig(
|
||||||
|
init_signal_handlers, argc, argv, add_program_dir_to_path);
|
||||||
|
#else
|
||||||
|
PyConfig config;
|
||||||
|
PyConfig_InitPythonConfig(&config);
|
||||||
|
// See PR #4473 for background
|
||||||
|
config.parse_argv = 0;
|
||||||
|
|
||||||
|
config.install_signal_handlers = init_signal_handlers ? 1 : 0;
|
||||||
|
initialize_interpreter(&config, argc, argv, add_program_dir_to_path);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \rst
|
||||||
|
Shut down the Python interpreter. No pybind11 or CPython API functions can be called
|
||||||
|
after this. In addition, pybind11 objects must not outlive the interpreter:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
{ // BAD
|
||||||
|
py::initialize_interpreter();
|
||||||
|
auto hello = py::str("Hello, World!");
|
||||||
|
py::finalize_interpreter();
|
||||||
|
} // <-- BOOM, hello's destructor is called after interpreter shutdown
|
||||||
|
|
||||||
|
{ // GOOD
|
||||||
|
py::initialize_interpreter();
|
||||||
|
{ // scoped
|
||||||
|
auto hello = py::str("Hello, World!");
|
||||||
|
} // <-- OK, hello is cleaned up properly
|
||||||
|
py::finalize_interpreter();
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // BETTER
|
||||||
|
py::scoped_interpreter guard{};
|
||||||
|
auto hello = py::str("Hello, World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
The interpreter can be restarted by calling `initialize_interpreter` again.
|
||||||
|
Modules created using pybind11 can be safely re-initialized. However, Python
|
||||||
|
itself cannot completely unload binary extension modules and there are several
|
||||||
|
caveats with regard to interpreter restarting. All the details can be found
|
||||||
|
in the CPython documentation. In short, not all interpreter memory may be
|
||||||
|
freed, either due to reference cycles or user-created global data.
|
||||||
|
|
||||||
|
\endrst */
|
||||||
|
inline void finalize_interpreter() {
|
||||||
|
// Get the internals pointer (without creating it if it doesn't exist). It's possible for the
|
||||||
|
// internals to be created during Py_Finalize() (e.g. if a py::capsule calls `get_internals()`
|
||||||
|
// during destruction), so we get the pointer-pointer here and check it after Py_Finalize().
|
||||||
|
detail::internals **internals_ptr_ptr = detail::get_internals_pp();
|
||||||
|
// It could also be stashed in state_dict, so look there too:
|
||||||
|
if (object internals_obj
|
||||||
|
= get_internals_obj_from_state_dict(detail::get_python_state_dict())) {
|
||||||
|
internals_ptr_ptr = detail::get_internals_pp_from_capsule(internals_obj);
|
||||||
|
}
|
||||||
|
// Local internals contains data managed by the current interpreter, so we must clear them to
|
||||||
|
// avoid undefined behaviors when initializing another interpreter
|
||||||
|
detail::get_local_internals().registered_types_cpp.clear();
|
||||||
|
detail::get_local_internals().registered_exception_translators.clear();
|
||||||
|
|
||||||
|
Py_Finalize();
|
||||||
|
|
||||||
|
if (internals_ptr_ptr) {
|
||||||
|
delete *internals_ptr_ptr;
|
||||||
|
*internals_ptr_ptr = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \rst
|
||||||
|
Scope guard version of `initialize_interpreter` and `finalize_interpreter`.
|
||||||
|
This a move-only guard and only a single instance can exist.
|
||||||
|
|
||||||
|
See `initialize_interpreter` for a discussion of its constructor arguments.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/embed.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
py::scoped_interpreter guard{};
|
||||||
|
py::print(Hello, World!);
|
||||||
|
} // <-- interpreter shutdown
|
||||||
|
\endrst */
|
||||||
|
class scoped_interpreter {
|
||||||
|
public:
|
||||||
|
explicit scoped_interpreter(bool init_signal_handlers = true,
|
||||||
|
int argc = 0,
|
||||||
|
const char *const *argv = nullptr,
|
||||||
|
bool add_program_dir_to_path = true) {
|
||||||
|
initialize_interpreter(init_signal_handlers, argc, argv, add_program_dir_to_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
|
||||||
|
explicit scoped_interpreter(PyConfig *config,
|
||||||
|
int argc = 0,
|
||||||
|
const char *const *argv = nullptr,
|
||||||
|
bool add_program_dir_to_path = true) {
|
||||||
|
initialize_interpreter(config, argc, argv, add_program_dir_to_path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
scoped_interpreter(const scoped_interpreter &) = delete;
|
||||||
|
scoped_interpreter(scoped_interpreter &&other) noexcept { other.is_valid = false; }
|
||||||
|
scoped_interpreter &operator=(const scoped_interpreter &) = delete;
|
||||||
|
scoped_interpreter &operator=(scoped_interpreter &&) = delete;
|
||||||
|
|
||||||
|
~scoped_interpreter() {
|
||||||
|
if (is_valid) {
|
||||||
|
finalize_interpreter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_valid = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
156
3rdparty/pybind11/include/pybind11/eval.h
vendored
Normal file
156
3rdparty/pybind11/include/pybind11/eval.h
vendored
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
pybind11/eval.h: Support for evaluating Python expressions and statements
|
||||||
|
from strings and files
|
||||||
|
|
||||||
|
Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and
|
||||||
|
Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pybind11.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
inline void ensure_builtins_in_globals(object &global) {
|
||||||
|
#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x03080000
|
||||||
|
// Running exec and eval adds `builtins` module under `__builtins__` key to
|
||||||
|
// globals if not yet present. Python 3.8 made PyRun_String behave
|
||||||
|
// similarly. Let's also do that for older versions, for consistency. This
|
||||||
|
// was missing from PyPy3.8 7.3.7.
|
||||||
|
if (!global.contains("__builtins__"))
|
||||||
|
global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE);
|
||||||
|
#else
|
||||||
|
(void) global;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
enum eval_mode {
|
||||||
|
/// Evaluate a string containing an isolated expression
|
||||||
|
eval_expr,
|
||||||
|
|
||||||
|
/// Evaluate a string containing a single statement. Returns \c none
|
||||||
|
eval_single_statement,
|
||||||
|
|
||||||
|
/// Evaluate a string containing a sequence of statement. Returns \c none
|
||||||
|
eval_statements
|
||||||
|
};
|
||||||
|
|
||||||
|
template <eval_mode mode = eval_expr>
|
||||||
|
object eval(const str &expr, object global = globals(), object local = object()) {
|
||||||
|
if (!local) {
|
||||||
|
local = global;
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::ensure_builtins_in_globals(global);
|
||||||
|
|
||||||
|
/* PyRun_String does not accept a PyObject / encoding specifier,
|
||||||
|
this seems to be the only alternative */
|
||||||
|
std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr;
|
||||||
|
|
||||||
|
int start = 0;
|
||||||
|
switch (mode) {
|
||||||
|
case eval_expr:
|
||||||
|
start = Py_eval_input;
|
||||||
|
break;
|
||||||
|
case eval_single_statement:
|
||||||
|
start = Py_single_input;
|
||||||
|
break;
|
||||||
|
case eval_statements:
|
||||||
|
start = Py_file_input;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pybind11_fail("invalid evaluation mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
|
||||||
|
if (!result) {
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
return reinterpret_steal<object>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <eval_mode mode = eval_expr, size_t N>
|
||||||
|
object eval(const char (&s)[N], object global = globals(), object local = object()) {
|
||||||
|
/* Support raw string literals by removing common leading whitespace */
|
||||||
|
auto expr = (s[0] == '\n') ? str(module_::import("textwrap").attr("dedent")(s)) : str(s);
|
||||||
|
return eval<mode>(expr, std::move(global), std::move(local));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void exec(const str &expr, object global = globals(), object local = object()) {
|
||||||
|
eval<eval_statements>(expr, std::move(global), std::move(local));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
void exec(const char (&s)[N], object global = globals(), object local = object()) {
|
||||||
|
eval<eval_statements>(s, std::move(global), std::move(local));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(PYPY_VERSION)
|
||||||
|
template <eval_mode mode = eval_statements>
|
||||||
|
object eval_file(str, object, object) {
|
||||||
|
pybind11_fail("eval_file not supported in PyPy3. Use eval");
|
||||||
|
}
|
||||||
|
template <eval_mode mode = eval_statements>
|
||||||
|
object eval_file(str, object) {
|
||||||
|
pybind11_fail("eval_file not supported in PyPy3. Use eval");
|
||||||
|
}
|
||||||
|
template <eval_mode mode = eval_statements>
|
||||||
|
object eval_file(str) {
|
||||||
|
pybind11_fail("eval_file not supported in PyPy3. Use eval");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template <eval_mode mode = eval_statements>
|
||||||
|
object eval_file(str fname, object global = globals(), object local = object()) {
|
||||||
|
if (!local) {
|
||||||
|
local = global;
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::ensure_builtins_in_globals(global);
|
||||||
|
|
||||||
|
int start = 0;
|
||||||
|
switch (mode) {
|
||||||
|
case eval_expr:
|
||||||
|
start = Py_eval_input;
|
||||||
|
break;
|
||||||
|
case eval_single_statement:
|
||||||
|
start = Py_single_input;
|
||||||
|
break;
|
||||||
|
case eval_statements:
|
||||||
|
start = Py_file_input;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pybind11_fail("invalid evaluation mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
int closeFile = 1;
|
||||||
|
std::string fname_str = (std::string) fname;
|
||||||
|
FILE *f = _Py_fopen_obj(fname.ptr(), "r");
|
||||||
|
if (!f) {
|
||||||
|
PyErr_Clear();
|
||||||
|
pybind11_fail("File \"" + fname_str + "\" could not be opened!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!global.contains("__file__")) {
|
||||||
|
global["__file__"] = std::move(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result
|
||||||
|
= PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), local.ptr(), closeFile);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
return reinterpret_steal<object>(result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
137
3rdparty/pybind11/include/pybind11/functional.h
vendored
Normal file
137
3rdparty/pybind11/include/pybind11/functional.h
vendored
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
pybind11/functional.h: std::function<> support
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pybind11.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <typename Return, typename... Args>
|
||||||
|
struct type_caster<std::function<Return(Args...)>> {
|
||||||
|
using type = std::function<Return(Args...)>;
|
||||||
|
using retval_type = conditional_t<std::is_same<Return, void>::value, void_type, Return>;
|
||||||
|
using function_type = Return (*)(Args...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
if (src.is_none()) {
|
||||||
|
// Defer accepting None to other overloads (if we aren't in convert mode):
|
||||||
|
if (!convert) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isinstance<function>(src)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto func = reinterpret_borrow<function>(src);
|
||||||
|
|
||||||
|
/*
|
||||||
|
When passing a C++ function as an argument to another C++
|
||||||
|
function via Python, every function call would normally involve
|
||||||
|
a full C++ -> Python -> C++ roundtrip, which can be prohibitive.
|
||||||
|
Here, we try to at least detect the case where the function is
|
||||||
|
stateless (i.e. function pointer or lambda function without
|
||||||
|
captured variables), in which case the roundtrip can be avoided.
|
||||||
|
*/
|
||||||
|
if (auto cfunc = func.cpp_function()) {
|
||||||
|
auto *cfunc_self = PyCFunction_GET_SELF(cfunc.ptr());
|
||||||
|
if (cfunc_self == nullptr) {
|
||||||
|
PyErr_Clear();
|
||||||
|
} else if (isinstance<capsule>(cfunc_self)) {
|
||||||
|
auto c = reinterpret_borrow<capsule>(cfunc_self);
|
||||||
|
|
||||||
|
function_record *rec = nullptr;
|
||||||
|
// Check that we can safely reinterpret the capsule into a function_record
|
||||||
|
if (detail::is_function_record_capsule(c)) {
|
||||||
|
rec = c.get_pointer<function_record>();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rec != nullptr) {
|
||||||
|
if (rec->is_stateless
|
||||||
|
&& same_type(typeid(function_type),
|
||||||
|
*reinterpret_cast<const std::type_info *>(rec->data[1]))) {
|
||||||
|
struct capture {
|
||||||
|
function_type f;
|
||||||
|
};
|
||||||
|
value = ((capture *) &rec->data)->f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
rec = rec->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// PYPY segfaults here when passing builtin function like sum.
|
||||||
|
// Raising an fail exception here works to prevent the segfault, but only on gcc.
|
||||||
|
// See PR #1413 for full details
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure GIL is held during functor destruction
|
||||||
|
struct func_handle {
|
||||||
|
function f;
|
||||||
|
#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17))
|
||||||
|
// This triggers a syntax error under very special conditions (very weird indeed).
|
||||||
|
explicit
|
||||||
|
#endif
|
||||||
|
func_handle(function &&f_) noexcept
|
||||||
|
: f(std::move(f_)) {
|
||||||
|
}
|
||||||
|
func_handle(const func_handle &f_) { operator=(f_); }
|
||||||
|
func_handle &operator=(const func_handle &f_) {
|
||||||
|
gil_scoped_acquire acq;
|
||||||
|
f = f_.f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
~func_handle() {
|
||||||
|
gil_scoped_acquire acq;
|
||||||
|
function kill_f(std::move(f));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// to emulate 'move initialization capture' in C++11
|
||||||
|
struct func_wrapper {
|
||||||
|
func_handle hfunc;
|
||||||
|
explicit func_wrapper(func_handle &&hf) noexcept : hfunc(std::move(hf)) {}
|
||||||
|
Return operator()(Args... args) const {
|
||||||
|
gil_scoped_acquire acq;
|
||||||
|
// casts the returned object as a rvalue to the return type
|
||||||
|
return hfunc.f(std::forward<Args>(args)...).template cast<Return>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
value = func_wrapper(func_handle(std::move(func)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) {
|
||||||
|
if (!f_) {
|
||||||
|
return none().release();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = f_.template target<function_type>();
|
||||||
|
if (result) {
|
||||||
|
return cpp_function(*result, policy).release();
|
||||||
|
}
|
||||||
|
return cpp_function(std::forward<Func>(f_), policy).release();
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(type,
|
||||||
|
const_name("Callable[[") + concat(make_caster<Args>::name...)
|
||||||
|
+ const_name("], ") + make_caster<retval_type>::name
|
||||||
|
+ const_name("]"));
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
239
3rdparty/pybind11/include/pybind11/gil.h
vendored
Normal file
239
3rdparty/pybind11/include/pybind11/gil.h
vendored
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
pybind11/gil.h: RAII helpers for managing the GIL
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "detail/common.h"
|
||||||
|
|
||||||
|
#if defined(WITH_THREAD) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||||
|
# include "detail/internals.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
PyThreadState *get_thread_state_unchecked();
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
#if defined(WITH_THREAD)
|
||||||
|
|
||||||
|
# if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||||
|
|
||||||
|
/* The functions below essentially reproduce the PyGILState_* API using a RAII
|
||||||
|
* pattern, but there are a few important differences:
|
||||||
|
*
|
||||||
|
* 1. When acquiring the GIL from an non-main thread during the finalization
|
||||||
|
* phase, the GILState API blindly terminates the calling thread, which
|
||||||
|
* is often not what is wanted. This API does not do this.
|
||||||
|
*
|
||||||
|
* 2. The gil_scoped_release function can optionally cut the relationship
|
||||||
|
* of a PyThreadState and its associated thread, which allows moving it to
|
||||||
|
* another thread (this is a fairly rare/advanced use case).
|
||||||
|
*
|
||||||
|
* 3. The reference count of an acquired thread state can be controlled. This
|
||||||
|
* can be handy to prevent cases where callbacks issued from an external
|
||||||
|
* thread would otherwise constantly construct and destroy thread state data
|
||||||
|
* structures.
|
||||||
|
*
|
||||||
|
* See the Python bindings of NanoGUI (http://github.com/wjakob/nanogui) for an
|
||||||
|
* example which uses features 2 and 3 to migrate the Python thread of
|
||||||
|
* execution to another thread (to run the event loop on the original thread,
|
||||||
|
* in this case).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class gil_scoped_acquire {
|
||||||
|
public:
|
||||||
|
PYBIND11_NOINLINE gil_scoped_acquire() {
|
||||||
|
auto &internals = detail::get_internals();
|
||||||
|
tstate = (PyThreadState *) PYBIND11_TLS_GET_VALUE(internals.tstate);
|
||||||
|
|
||||||
|
if (!tstate) {
|
||||||
|
/* Check if the GIL was acquired using the PyGILState_* API instead (e.g. if
|
||||||
|
calling from a Python thread). Since we use a different key, this ensures
|
||||||
|
we don't create a new thread state and deadlock in PyEval_AcquireThread
|
||||||
|
below. Note we don't save this state with internals.tstate, since we don't
|
||||||
|
create it we would fail to clear it (its reference count should be > 0). */
|
||||||
|
tstate = PyGILState_GetThisThreadState();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tstate) {
|
||||||
|
tstate = PyThreadState_New(internals.istate);
|
||||||
|
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||||
|
if (!tstate) {
|
||||||
|
pybind11_fail("scoped_acquire: could not create thread state!");
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
tstate->gilstate_counter = 0;
|
||||||
|
PYBIND11_TLS_REPLACE_VALUE(internals.tstate, tstate);
|
||||||
|
} else {
|
||||||
|
release = detail::get_thread_state_unchecked() != tstate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (release) {
|
||||||
|
PyEval_AcquireThread(tstate);
|
||||||
|
}
|
||||||
|
|
||||||
|
inc_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
|
||||||
|
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
|
||||||
|
|
||||||
|
void inc_ref() { ++tstate->gilstate_counter; }
|
||||||
|
|
||||||
|
PYBIND11_NOINLINE void dec_ref() {
|
||||||
|
--tstate->gilstate_counter;
|
||||||
|
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||||
|
if (detail::get_thread_state_unchecked() != tstate) {
|
||||||
|
pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!");
|
||||||
|
}
|
||||||
|
if (tstate->gilstate_counter < 0) {
|
||||||
|
pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!");
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
if (tstate->gilstate_counter == 0) {
|
||||||
|
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||||
|
if (!release) {
|
||||||
|
pybind11_fail("scoped_acquire::dec_ref(): internal error!");
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
PyThreadState_Clear(tstate);
|
||||||
|
if (active) {
|
||||||
|
PyThreadState_DeleteCurrent();
|
||||||
|
}
|
||||||
|
PYBIND11_TLS_DELETE_VALUE(detail::get_internals().tstate);
|
||||||
|
release = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method will disable the PyThreadState_DeleteCurrent call and the
|
||||||
|
/// GIL won't be acquired. This method should be used if the interpreter
|
||||||
|
/// could be shutting down when this is called, as thread deletion is not
|
||||||
|
/// allowed during shutdown. Check _Py_IsFinalizing() on Python 3.7+, and
|
||||||
|
/// protect subsequent code.
|
||||||
|
PYBIND11_NOINLINE void disarm() { active = false; }
|
||||||
|
|
||||||
|
PYBIND11_NOINLINE ~gil_scoped_acquire() {
|
||||||
|
dec_ref();
|
||||||
|
if (release) {
|
||||||
|
PyEval_SaveThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PyThreadState *tstate = nullptr;
|
||||||
|
bool release = true;
|
||||||
|
bool active = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
class gil_scoped_release {
|
||||||
|
public:
|
||||||
|
explicit gil_scoped_release(bool disassoc = false) : disassoc(disassoc) {
|
||||||
|
// `get_internals()` must be called here unconditionally in order to initialize
|
||||||
|
// `internals.tstate` for subsequent `gil_scoped_acquire` calls. Otherwise, an
|
||||||
|
// initialization race could occur as multiple threads try `gil_scoped_acquire`.
|
||||||
|
auto &internals = detail::get_internals();
|
||||||
|
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||||
|
tstate = PyEval_SaveThread();
|
||||||
|
if (disassoc) {
|
||||||
|
// Python >= 3.7 can remove this, it's an int before 3.7
|
||||||
|
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||||
|
auto key = internals.tstate;
|
||||||
|
PYBIND11_TLS_DELETE_VALUE(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gil_scoped_release(const gil_scoped_release &) = delete;
|
||||||
|
gil_scoped_release &operator=(const gil_scoped_release &) = delete;
|
||||||
|
|
||||||
|
/// This method will disable the PyThreadState_DeleteCurrent call and the
|
||||||
|
/// GIL won't be acquired. This method should be used if the interpreter
|
||||||
|
/// could be shutting down when this is called, as thread deletion is not
|
||||||
|
/// allowed during shutdown. Check _Py_IsFinalizing() on Python 3.7+, and
|
||||||
|
/// protect subsequent code.
|
||||||
|
PYBIND11_NOINLINE void disarm() { active = false; }
|
||||||
|
|
||||||
|
~gil_scoped_release() {
|
||||||
|
if (!tstate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// `PyEval_RestoreThread()` should not be called if runtime is finalizing
|
||||||
|
if (active) {
|
||||||
|
PyEval_RestoreThread(tstate);
|
||||||
|
}
|
||||||
|
if (disassoc) {
|
||||||
|
// Python >= 3.7 can remove this, it's an int before 3.7
|
||||||
|
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||||
|
auto key = detail::get_internals().tstate;
|
||||||
|
PYBIND11_TLS_REPLACE_VALUE(key, tstate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PyThreadState *tstate;
|
||||||
|
bool disassoc;
|
||||||
|
bool active = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# else // PYBIND11_SIMPLE_GIL_MANAGEMENT
|
||||||
|
|
||||||
|
class gil_scoped_acquire {
|
||||||
|
PyGILState_STATE state;
|
||||||
|
|
||||||
|
public:
|
||||||
|
gil_scoped_acquire() : state{PyGILState_Ensure()} {}
|
||||||
|
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
|
||||||
|
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
|
||||||
|
~gil_scoped_acquire() { PyGILState_Release(state); }
|
||||||
|
void disarm() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class gil_scoped_release {
|
||||||
|
PyThreadState *state;
|
||||||
|
|
||||||
|
public:
|
||||||
|
gil_scoped_release() : state{PyEval_SaveThread()} {}
|
||||||
|
gil_scoped_release(const gil_scoped_release &) = delete;
|
||||||
|
gil_scoped_release &operator=(const gil_scoped_release &) = delete;
|
||||||
|
~gil_scoped_release() { PyEval_RestoreThread(state); }
|
||||||
|
void disarm() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
# endif // PYBIND11_SIMPLE_GIL_MANAGEMENT
|
||||||
|
|
||||||
|
#else // WITH_THREAD
|
||||||
|
|
||||||
|
class gil_scoped_acquire {
|
||||||
|
public:
|
||||||
|
gil_scoped_acquire() {
|
||||||
|
// Trick to suppress `unused variable` error messages (at call sites).
|
||||||
|
(void) (this != (this + 1));
|
||||||
|
}
|
||||||
|
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
|
||||||
|
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
|
||||||
|
void disarm() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class gil_scoped_release {
|
||||||
|
public:
|
||||||
|
gil_scoped_release() {
|
||||||
|
// Trick to suppress `unused variable` error messages (at call sites).
|
||||||
|
(void) (this != (this + 1));
|
||||||
|
}
|
||||||
|
gil_scoped_release(const gil_scoped_release &) = delete;
|
||||||
|
gil_scoped_release &operator=(const gil_scoped_release &) = delete;
|
||||||
|
void disarm() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WITH_THREAD
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
265
3rdparty/pybind11/include/pybind11/iostream.h
vendored
Normal file
265
3rdparty/pybind11/include/pybind11/iostream.h
vendored
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
pybind11/iostream.h -- Tools to assist with redirecting cout and cerr to Python
|
||||||
|
|
||||||
|
Copyright (c) 2017 Henry F. Schreiner
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
WARNING: The implementation in this file is NOT thread safe. Multiple
|
||||||
|
threads writing to a redirected ostream concurrently cause data races
|
||||||
|
and potentially buffer overflows. Therefore it is currently a requirement
|
||||||
|
that all (possibly) concurrent redirected ostream writes are protected by
|
||||||
|
a mutex.
|
||||||
|
#HelpAppreciated: Work on iostream.h thread safety.
|
||||||
|
For more background see the discussions under
|
||||||
|
https://github.com/pybind/pybind11/pull/2982 and
|
||||||
|
https://github.com/pybind/pybind11/pull/2995.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pybind11.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
|
#include <streambuf>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
// Buffer that writes to Python instead of C++
|
||||||
|
class pythonbuf : public std::streambuf {
|
||||||
|
private:
|
||||||
|
using traits_type = std::streambuf::traits_type;
|
||||||
|
|
||||||
|
const size_t buf_size;
|
||||||
|
std::unique_ptr<char[]> d_buffer;
|
||||||
|
object pywrite;
|
||||||
|
object pyflush;
|
||||||
|
|
||||||
|
int overflow(int c) override {
|
||||||
|
if (!traits_type::eq_int_type(c, traits_type::eof())) {
|
||||||
|
*pptr() = traits_type::to_char_type(c);
|
||||||
|
pbump(1);
|
||||||
|
}
|
||||||
|
return sync() == 0 ? traits_type::not_eof(c) : traits_type::eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Computes how many bytes at the end of the buffer are part of an
|
||||||
|
// incomplete sequence of UTF-8 bytes.
|
||||||
|
// Precondition: pbase() < pptr()
|
||||||
|
size_t utf8_remainder() const {
|
||||||
|
const auto rbase = std::reverse_iterator<char *>(pbase());
|
||||||
|
const auto rpptr = std::reverse_iterator<char *>(pptr());
|
||||||
|
auto is_ascii = [](char c) { return (static_cast<unsigned char>(c) & 0x80) == 0x00; };
|
||||||
|
auto is_leading = [](char c) { return (static_cast<unsigned char>(c) & 0xC0) == 0xC0; };
|
||||||
|
auto is_leading_2b = [](char c) { return static_cast<unsigned char>(c) <= 0xDF; };
|
||||||
|
auto is_leading_3b = [](char c) { return static_cast<unsigned char>(c) <= 0xEF; };
|
||||||
|
// If the last character is ASCII, there are no incomplete code points
|
||||||
|
if (is_ascii(*rpptr)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Otherwise, work back from the end of the buffer and find the first
|
||||||
|
// UTF-8 leading byte
|
||||||
|
const auto rpend = rbase - rpptr >= 3 ? rpptr + 3 : rbase;
|
||||||
|
const auto leading = std::find_if(rpptr, rpend, is_leading);
|
||||||
|
if (leading == rbase) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const auto dist = static_cast<size_t>(leading - rpptr);
|
||||||
|
size_t remainder = 0;
|
||||||
|
|
||||||
|
if (dist == 0) {
|
||||||
|
remainder = 1; // 1-byte code point is impossible
|
||||||
|
} else if (dist == 1) {
|
||||||
|
remainder = is_leading_2b(*leading) ? 0 : dist + 1;
|
||||||
|
} else if (dist == 2) {
|
||||||
|
remainder = is_leading_3b(*leading) ? 0 : dist + 1;
|
||||||
|
}
|
||||||
|
// else if (dist >= 3), at least 4 bytes before encountering an UTF-8
|
||||||
|
// leading byte, either no remainder or invalid UTF-8.
|
||||||
|
// Invalid UTF-8 will cause an exception later when converting
|
||||||
|
// to a Python string, so that's not handled here.
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function must be non-virtual to be called in a destructor.
|
||||||
|
int _sync() {
|
||||||
|
if (pbase() != pptr()) { // If buffer is not empty
|
||||||
|
gil_scoped_acquire tmp;
|
||||||
|
// This subtraction cannot be negative, so dropping the sign.
|
||||||
|
auto size = static_cast<size_t>(pptr() - pbase());
|
||||||
|
size_t remainder = utf8_remainder();
|
||||||
|
|
||||||
|
if (size > remainder) {
|
||||||
|
str line(pbase(), size - remainder);
|
||||||
|
pywrite(std::move(line));
|
||||||
|
pyflush();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the remainder at the end of the buffer to the beginning:
|
||||||
|
if (remainder > 0) {
|
||||||
|
std::memmove(pbase(), pptr() - remainder, remainder);
|
||||||
|
}
|
||||||
|
setp(pbase(), epptr());
|
||||||
|
pbump(static_cast<int>(remainder));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sync() override { return _sync(); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit pythonbuf(const object &pyostream, size_t buffer_size = 1024)
|
||||||
|
: buf_size(buffer_size), d_buffer(new char[buf_size]), pywrite(pyostream.attr("write")),
|
||||||
|
pyflush(pyostream.attr("flush")) {
|
||||||
|
setp(d_buffer.get(), d_buffer.get() + buf_size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pythonbuf(pythonbuf &&) = default;
|
||||||
|
|
||||||
|
/// Sync before destroy
|
||||||
|
~pythonbuf() override { _sync(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
/** \rst
|
||||||
|
This a move-only guard that redirects output.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/iostream.h>
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
{
|
||||||
|
py::scoped_ostream_redirect output;
|
||||||
|
std::cout << "Hello, World!"; // Python stdout
|
||||||
|
} // <-- return std::cout to normal
|
||||||
|
|
||||||
|
You can explicitly pass the c++ stream and the python object,
|
||||||
|
for example to guard stderr instead.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
{
|
||||||
|
py::scoped_ostream_redirect output{
|
||||||
|
std::cerr, py::module::import("sys").attr("stderr")};
|
||||||
|
std::cout << "Hello, World!";
|
||||||
|
}
|
||||||
|
\endrst */
|
||||||
|
class scoped_ostream_redirect {
|
||||||
|
protected:
|
||||||
|
std::streambuf *old;
|
||||||
|
std::ostream &costream;
|
||||||
|
detail::pythonbuf buffer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit scoped_ostream_redirect(std::ostream &costream = std::cout,
|
||||||
|
const object &pyostream
|
||||||
|
= module_::import("sys").attr("stdout"))
|
||||||
|
: costream(costream), buffer(pyostream) {
|
||||||
|
old = costream.rdbuf(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_ostream_redirect() { costream.rdbuf(old); }
|
||||||
|
|
||||||
|
scoped_ostream_redirect(const scoped_ostream_redirect &) = delete;
|
||||||
|
scoped_ostream_redirect(scoped_ostream_redirect &&other) = default;
|
||||||
|
scoped_ostream_redirect &operator=(const scoped_ostream_redirect &) = delete;
|
||||||
|
scoped_ostream_redirect &operator=(scoped_ostream_redirect &&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \rst
|
||||||
|
Like `scoped_ostream_redirect`, but redirects cerr by default. This class
|
||||||
|
is provided primary to make ``py::call_guard`` easier to make.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("noisy_func", &noisy_func,
|
||||||
|
py::call_guard<scoped_ostream_redirect,
|
||||||
|
scoped_estream_redirect>());
|
||||||
|
|
||||||
|
\endrst */
|
||||||
|
class scoped_estream_redirect : public scoped_ostream_redirect {
|
||||||
|
public:
|
||||||
|
explicit scoped_estream_redirect(std::ostream &costream = std::cerr,
|
||||||
|
const object &pyostream
|
||||||
|
= module_::import("sys").attr("stderr"))
|
||||||
|
: scoped_ostream_redirect(costream, pyostream) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
// Class to redirect output as a context manager. C++ backend.
|
||||||
|
class OstreamRedirect {
|
||||||
|
bool do_stdout_;
|
||||||
|
bool do_stderr_;
|
||||||
|
std::unique_ptr<scoped_ostream_redirect> redirect_stdout;
|
||||||
|
std::unique_ptr<scoped_estream_redirect> redirect_stderr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit OstreamRedirect(bool do_stdout = true, bool do_stderr = true)
|
||||||
|
: do_stdout_(do_stdout), do_stderr_(do_stderr) {}
|
||||||
|
|
||||||
|
void enter() {
|
||||||
|
if (do_stdout_) {
|
||||||
|
redirect_stdout.reset(new scoped_ostream_redirect());
|
||||||
|
}
|
||||||
|
if (do_stderr_) {
|
||||||
|
redirect_stderr.reset(new scoped_estream_redirect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit() {
|
||||||
|
redirect_stdout.reset();
|
||||||
|
redirect_stderr.reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
/** \rst
|
||||||
|
This is a helper function to add a C++ redirect context manager to Python
|
||||||
|
instead of using a C++ guard. To use it, add the following to your binding code:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/iostream.h>
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
py::add_ostream_redirect(m, "ostream_redirect");
|
||||||
|
|
||||||
|
You now have a Python context manager that redirects your output:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
with m.ostream_redirect():
|
||||||
|
m.print_to_cout_function()
|
||||||
|
|
||||||
|
This manager can optionally be told which streams to operate on:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
with m.ostream_redirect(stdout=true, stderr=true):
|
||||||
|
m.noisy_function_with_error_printing()
|
||||||
|
|
||||||
|
\endrst */
|
||||||
|
inline class_<detail::OstreamRedirect>
|
||||||
|
add_ostream_redirect(module_ m, const std::string &name = "ostream_redirect") {
|
||||||
|
return class_<detail::OstreamRedirect>(std::move(m), name.c_str(), module_local())
|
||||||
|
.def(init<bool, bool>(), arg("stdout") = true, arg("stderr") = true)
|
||||||
|
.def("__enter__", &detail::OstreamRedirect::enter)
|
||||||
|
.def("__exit__", [](detail::OstreamRedirect &self_, const args &) { self_.exit(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
1998
3rdparty/pybind11/include/pybind11/numpy.h
vendored
Normal file
1998
3rdparty/pybind11/include/pybind11/numpy.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
202
3rdparty/pybind11/include/pybind11/operators.h
vendored
Normal file
202
3rdparty/pybind11/include/pybind11/operators.h
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
pybind11/operator.h: Metatemplates for operator overloading
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pybind11.h"
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
/// Enumeration with all supported operator types
|
||||||
|
enum op_id : int {
|
||||||
|
op_add,
|
||||||
|
op_sub,
|
||||||
|
op_mul,
|
||||||
|
op_div,
|
||||||
|
op_mod,
|
||||||
|
op_divmod,
|
||||||
|
op_pow,
|
||||||
|
op_lshift,
|
||||||
|
op_rshift,
|
||||||
|
op_and,
|
||||||
|
op_xor,
|
||||||
|
op_or,
|
||||||
|
op_neg,
|
||||||
|
op_pos,
|
||||||
|
op_abs,
|
||||||
|
op_invert,
|
||||||
|
op_int,
|
||||||
|
op_long,
|
||||||
|
op_float,
|
||||||
|
op_str,
|
||||||
|
op_cmp,
|
||||||
|
op_gt,
|
||||||
|
op_ge,
|
||||||
|
op_lt,
|
||||||
|
op_le,
|
||||||
|
op_eq,
|
||||||
|
op_ne,
|
||||||
|
op_iadd,
|
||||||
|
op_isub,
|
||||||
|
op_imul,
|
||||||
|
op_idiv,
|
||||||
|
op_imod,
|
||||||
|
op_ilshift,
|
||||||
|
op_irshift,
|
||||||
|
op_iand,
|
||||||
|
op_ixor,
|
||||||
|
op_ior,
|
||||||
|
op_complex,
|
||||||
|
op_bool,
|
||||||
|
op_nonzero,
|
||||||
|
op_repr,
|
||||||
|
op_truediv,
|
||||||
|
op_itruediv,
|
||||||
|
op_hash
|
||||||
|
};
|
||||||
|
|
||||||
|
enum op_type : int {
|
||||||
|
op_l, /* base type on left */
|
||||||
|
op_r, /* base type on right */
|
||||||
|
op_u /* unary operator */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct self_t {};
|
||||||
|
static const self_t self = self_t();
|
||||||
|
|
||||||
|
/// Type for an unused type slot
|
||||||
|
struct undefined_t {};
|
||||||
|
|
||||||
|
/// Don't warn about an unused variable
|
||||||
|
inline self_t __self() { return self; }
|
||||||
|
|
||||||
|
/// base template of operator implementations
|
||||||
|
template <op_id, op_type, typename B, typename L, typename R>
|
||||||
|
struct op_impl {};
|
||||||
|
|
||||||
|
/// Operator implementation generator
|
||||||
|
template <op_id id, op_type ot, typename L, typename R>
|
||||||
|
struct op_ {
|
||||||
|
static constexpr bool op_enable_if_hook = true;
|
||||||
|
template <typename Class, typename... Extra>
|
||||||
|
void execute(Class &cl, const Extra &...extra) const {
|
||||||
|
using Base = typename Class::type;
|
||||||
|
using L_type = conditional_t<std::is_same<L, self_t>::value, Base, L>;
|
||||||
|
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
|
||||||
|
using op = op_impl<id, ot, Base, L_type, R_type>;
|
||||||
|
cl.def(op::name(), &op::execute, is_operator(), extra...);
|
||||||
|
}
|
||||||
|
template <typename Class, typename... Extra>
|
||||||
|
void execute_cast(Class &cl, const Extra &...extra) const {
|
||||||
|
using Base = typename Class::type;
|
||||||
|
using L_type = conditional_t<std::is_same<L, self_t>::value, Base, L>;
|
||||||
|
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
|
||||||
|
using op = op_impl<id, ot, Base, L_type, R_type>;
|
||||||
|
cl.def(op::name(), &op::execute_cast, is_operator(), extra...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PYBIND11_BINARY_OPERATOR(id, rid, op, expr) \
|
||||||
|
template <typename B, typename L, typename R> \
|
||||||
|
struct op_impl<op_##id, op_l, B, L, R> { \
|
||||||
|
static char const *name() { return "__" #id "__"; } \
|
||||||
|
static auto execute(const L &l, const R &r) -> decltype(expr) { return (expr); } \
|
||||||
|
static B execute_cast(const L &l, const R &r) { return B(expr); } \
|
||||||
|
}; \
|
||||||
|
template <typename B, typename L, typename R> \
|
||||||
|
struct op_impl<op_##id, op_r, B, L, R> { \
|
||||||
|
static char const *name() { return "__" #rid "__"; } \
|
||||||
|
static auto execute(const R &r, const L &l) -> decltype(expr) { return (expr); } \
|
||||||
|
static B execute_cast(const R &r, const L &l) { return B(expr); } \
|
||||||
|
}; \
|
||||||
|
inline op_<op_##id, op_l, self_t, self_t> op(const self_t &, const self_t &) { \
|
||||||
|
return op_<op_##id, op_l, self_t, self_t>(); \
|
||||||
|
} \
|
||||||
|
template <typename T> \
|
||||||
|
op_<op_##id, op_l, self_t, T> op(const self_t &, const T &) { \
|
||||||
|
return op_<op_##id, op_l, self_t, T>(); \
|
||||||
|
} \
|
||||||
|
template <typename T> \
|
||||||
|
op_<op_##id, op_r, T, self_t> op(const T &, const self_t &) { \
|
||||||
|
return op_<op_##id, op_r, T, self_t>(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PYBIND11_INPLACE_OPERATOR(id, op, expr) \
|
||||||
|
template <typename B, typename L, typename R> \
|
||||||
|
struct op_impl<op_##id, op_l, B, L, R> { \
|
||||||
|
static char const *name() { return "__" #id "__"; } \
|
||||||
|
static auto execute(L &l, const R &r) -> decltype(expr) { return expr; } \
|
||||||
|
static B execute_cast(L &l, const R &r) { return B(expr); } \
|
||||||
|
}; \
|
||||||
|
template <typename T> \
|
||||||
|
op_<op_##id, op_l, self_t, T> op(const self_t &, const T &) { \
|
||||||
|
return op_<op_##id, op_l, self_t, T>(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PYBIND11_UNARY_OPERATOR(id, op, expr) \
|
||||||
|
template <typename B, typename L> \
|
||||||
|
struct op_impl<op_##id, op_u, B, L, undefined_t> { \
|
||||||
|
static char const *name() { return "__" #id "__"; } \
|
||||||
|
static auto execute(const L &l) -> decltype(expr) { return expr; } \
|
||||||
|
static B execute_cast(const L &l) { return B(expr); } \
|
||||||
|
}; \
|
||||||
|
inline op_<op_##id, op_u, self_t, undefined_t> op(const self_t &) { \
|
||||||
|
return op_<op_##id, op_u, self_t, undefined_t>(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_BINARY_OPERATOR(sub, rsub, operator-, l - r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(add, radd, operator+, l + r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(mul, rmul, operator*, l *r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(truediv, rtruediv, operator/, l / r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(mod, rmod, operator%, l % r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(lshift, rlshift, operator<<, l << r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(rshift, rrshift, operator>>, l >> r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(and, rand, operator&, l &r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(xor, rxor, operator^, l ^ r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(eq, eq, operator==, l == r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(ne, ne, operator!=, l != r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(or, ror, operator|, l | r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(gt, lt, operator>, l > r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(ge, le, operator>=, l >= r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(lt, gt, operator<, l < r)
|
||||||
|
PYBIND11_BINARY_OPERATOR(le, ge, operator<=, l <= r)
|
||||||
|
// PYBIND11_BINARY_OPERATOR(pow, rpow, pow, std::pow(l, r))
|
||||||
|
PYBIND11_INPLACE_OPERATOR(iadd, operator+=, l += r)
|
||||||
|
PYBIND11_INPLACE_OPERATOR(isub, operator-=, l -= r)
|
||||||
|
PYBIND11_INPLACE_OPERATOR(imul, operator*=, l *= r)
|
||||||
|
PYBIND11_INPLACE_OPERATOR(itruediv, operator/=, l /= r)
|
||||||
|
PYBIND11_INPLACE_OPERATOR(imod, operator%=, l %= r)
|
||||||
|
PYBIND11_INPLACE_OPERATOR(ilshift, operator<<=, l <<= r)
|
||||||
|
PYBIND11_INPLACE_OPERATOR(irshift, operator>>=, l >>= r)
|
||||||
|
PYBIND11_INPLACE_OPERATOR(iand, operator&=, l &= r)
|
||||||
|
PYBIND11_INPLACE_OPERATOR(ixor, operator^=, l ^= r)
|
||||||
|
PYBIND11_INPLACE_OPERATOR(ior, operator|=, l |= r)
|
||||||
|
PYBIND11_UNARY_OPERATOR(neg, operator-, -l)
|
||||||
|
PYBIND11_UNARY_OPERATOR(pos, operator+, +l)
|
||||||
|
// WARNING: This usage of `abs` should only be done for existing STL overloads.
|
||||||
|
// Adding overloads directly in to the `std::` namespace is advised against:
|
||||||
|
// https://en.cppreference.com/w/cpp/language/extending_std
|
||||||
|
PYBIND11_UNARY_OPERATOR(abs, abs, std::abs(l))
|
||||||
|
PYBIND11_UNARY_OPERATOR(hash, hash, std::hash<L>()(l))
|
||||||
|
PYBIND11_UNARY_OPERATOR(invert, operator~, (~l))
|
||||||
|
PYBIND11_UNARY_OPERATOR(bool, operator!, !!l)
|
||||||
|
PYBIND11_UNARY_OPERATOR(int, int_, (int) l)
|
||||||
|
PYBIND11_UNARY_OPERATOR(float, float_, (double) l)
|
||||||
|
|
||||||
|
#undef PYBIND11_BINARY_OPERATOR
|
||||||
|
#undef PYBIND11_INPLACE_OPERATOR
|
||||||
|
#undef PYBIND11_UNARY_OPERATOR
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
using detail::self;
|
||||||
|
// Add named operators so that they are accessible via `py::`.
|
||||||
|
using detail::hash;
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
92
3rdparty/pybind11/include/pybind11/options.h
vendored
Normal file
92
3rdparty/pybind11/include/pybind11/options.h
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
pybind11/options.h: global settings that are configurable at runtime.
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "detail/common.h"
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
|
class options {
|
||||||
|
public:
|
||||||
|
// Default RAII constructor, which leaves settings as they currently are.
|
||||||
|
options() : previous_state(global_state()) {}
|
||||||
|
|
||||||
|
// Class is non-copyable.
|
||||||
|
options(const options &) = delete;
|
||||||
|
options &operator=(const options &) = delete;
|
||||||
|
|
||||||
|
// Destructor, which restores settings that were in effect before.
|
||||||
|
~options() { global_state() = previous_state; }
|
||||||
|
|
||||||
|
// Setter methods (affect the global state):
|
||||||
|
|
||||||
|
options &disable_user_defined_docstrings() & {
|
||||||
|
global_state().show_user_defined_docstrings = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
options &enable_user_defined_docstrings() & {
|
||||||
|
global_state().show_user_defined_docstrings = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
options &disable_function_signatures() & {
|
||||||
|
global_state().show_function_signatures = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
options &enable_function_signatures() & {
|
||||||
|
global_state().show_function_signatures = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
options &disable_enum_members_docstring() & {
|
||||||
|
global_state().show_enum_members_docstring = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
options &enable_enum_members_docstring() & {
|
||||||
|
global_state().show_enum_members_docstring = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter methods (return the global state):
|
||||||
|
|
||||||
|
static bool show_user_defined_docstrings() {
|
||||||
|
return global_state().show_user_defined_docstrings;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool show_function_signatures() { return global_state().show_function_signatures; }
|
||||||
|
|
||||||
|
static bool show_enum_members_docstring() {
|
||||||
|
return global_state().show_enum_members_docstring;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This type is not meant to be allocated on the heap.
|
||||||
|
void *operator new(size_t) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct state {
|
||||||
|
bool show_user_defined_docstrings = true; //< Include user-supplied texts in docstrings.
|
||||||
|
bool show_function_signatures = true; //< Include auto-generated function signatures
|
||||||
|
// in docstrings.
|
||||||
|
bool show_enum_members_docstring = true; //< Include auto-generated member list in enum
|
||||||
|
// docstrings.
|
||||||
|
};
|
||||||
|
|
||||||
|
static state &global_state() {
|
||||||
|
static state instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
state previous_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
2890
3rdparty/pybind11/include/pybind11/pybind11.h
vendored
Normal file
2890
3rdparty/pybind11/include/pybind11/pybind11.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2557
3rdparty/pybind11/include/pybind11/pytypes.h
vendored
Normal file
2557
3rdparty/pybind11/include/pybind11/pytypes.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
447
3rdparty/pybind11/include/pybind11/stl.h
vendored
Normal file
447
3rdparty/pybind11/include/pybind11/stl.h
vendored
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
/*
|
||||||
|
pybind11/stl.h: Transparent conversion for STL data types
|
||||||
|
|
||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pybind11.h"
|
||||||
|
#include "detail/common.h"
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <ostream>
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <valarray>
|
||||||
|
|
||||||
|
// See `detail/common.h` for implementation of these guards.
|
||||||
|
#if defined(PYBIND11_HAS_OPTIONAL)
|
||||||
|
# include <optional>
|
||||||
|
#elif defined(PYBIND11_HAS_EXP_OPTIONAL)
|
||||||
|
# include <experimental/optional>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PYBIND11_HAS_VARIANT)
|
||||||
|
# include <variant>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
/// Extracts an const lvalue reference or rvalue reference for U based on the type of T (e.g. for
|
||||||
|
/// forwarding a container element). Typically used indirect via forwarded_type(), below.
|
||||||
|
template <typename T, typename U>
|
||||||
|
using forwarded_type = conditional_t<std::is_lvalue_reference<T>::value,
|
||||||
|
remove_reference_t<U> &,
|
||||||
|
remove_reference_t<U> &&>;
|
||||||
|
|
||||||
|
/// Forwards a value U as rvalue or lvalue according to whether T is rvalue or lvalue; typically
|
||||||
|
/// used for forwarding a container's elements.
|
||||||
|
template <typename T, typename U>
|
||||||
|
constexpr forwarded_type<T, U> forward_like(U &&u) {
|
||||||
|
return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if a container has a STL style reserve method.
|
||||||
|
// This will only return true for a `reserve()` with a `void` return.
|
||||||
|
template <typename C>
|
||||||
|
using has_reserve_method = std::is_same<decltype(std::declval<C>().reserve(0)), void>;
|
||||||
|
|
||||||
|
template <typename Type, typename Key>
|
||||||
|
struct set_caster {
|
||||||
|
using type = Type;
|
||||||
|
using key_conv = make_caster<Key>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
|
||||||
|
void reserve_maybe(const anyset &s, Type *) {
|
||||||
|
value.reserve(s.size());
|
||||||
|
}
|
||||||
|
void reserve_maybe(const anyset &, void *) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
if (!isinstance<anyset>(src)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto s = reinterpret_borrow<anyset>(src);
|
||||||
|
value.clear();
|
||||||
|
reserve_maybe(s, &value);
|
||||||
|
for (auto entry : s) {
|
||||||
|
key_conv conv;
|
||||||
|
if (!conv.load(entry, convert)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value.insert(cast_op<Key &&>(std::move(conv)));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||||
|
if (!std::is_lvalue_reference<T>::value) {
|
||||||
|
policy = return_value_policy_override<Key>::policy(policy);
|
||||||
|
}
|
||||||
|
pybind11::set s;
|
||||||
|
for (auto &&value : src) {
|
||||||
|
auto value_ = reinterpret_steal<object>(
|
||||||
|
key_conv::cast(detail::forward_like<T>(value), policy, parent));
|
||||||
|
if (!value_ || !s.add(std::move(value_))) {
|
||||||
|
return handle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(type, const_name("Set[") + key_conv::name + const_name("]"));
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type, typename Key, typename Value>
|
||||||
|
struct map_caster {
|
||||||
|
using key_conv = make_caster<Key>;
|
||||||
|
using value_conv = make_caster<Value>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
|
||||||
|
void reserve_maybe(const dict &d, Type *) {
|
||||||
|
value.reserve(d.size());
|
||||||
|
}
|
||||||
|
void reserve_maybe(const dict &, void *) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
if (!isinstance<dict>(src)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto d = reinterpret_borrow<dict>(src);
|
||||||
|
value.clear();
|
||||||
|
reserve_maybe(d, &value);
|
||||||
|
for (auto it : d) {
|
||||||
|
key_conv kconv;
|
||||||
|
value_conv vconv;
|
||||||
|
if (!kconv.load(it.first.ptr(), convert) || !vconv.load(it.second.ptr(), convert)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv)));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||||
|
dict d;
|
||||||
|
return_value_policy policy_key = policy;
|
||||||
|
return_value_policy policy_value = policy;
|
||||||
|
if (!std::is_lvalue_reference<T>::value) {
|
||||||
|
policy_key = return_value_policy_override<Key>::policy(policy_key);
|
||||||
|
policy_value = return_value_policy_override<Value>::policy(policy_value);
|
||||||
|
}
|
||||||
|
for (auto &&kv : src) {
|
||||||
|
auto key = reinterpret_steal<object>(
|
||||||
|
key_conv::cast(detail::forward_like<T>(kv.first), policy_key, parent));
|
||||||
|
auto value = reinterpret_steal<object>(
|
||||||
|
value_conv::cast(detail::forward_like<T>(kv.second), policy_value, parent));
|
||||||
|
if (!key || !value) {
|
||||||
|
return handle();
|
||||||
|
}
|
||||||
|
d[std::move(key)] = std::move(value);
|
||||||
|
}
|
||||||
|
return d.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(Type,
|
||||||
|
const_name("Dict[") + key_conv::name + const_name(", ") + value_conv::name
|
||||||
|
+ const_name("]"));
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type, typename Value>
|
||||||
|
struct list_caster {
|
||||||
|
using value_conv = make_caster<Value>;
|
||||||
|
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
if (!isinstance<sequence>(src) || isinstance<bytes>(src) || isinstance<str>(src)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto s = reinterpret_borrow<sequence>(src);
|
||||||
|
value.clear();
|
||||||
|
reserve_maybe(s, &value);
|
||||||
|
for (auto it : s) {
|
||||||
|
value_conv conv;
|
||||||
|
if (!conv.load(it, convert)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value.push_back(cast_op<Value &&>(std::move(conv)));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
|
||||||
|
void reserve_maybe(const sequence &s, Type *) {
|
||||||
|
value.reserve(s.size());
|
||||||
|
}
|
||||||
|
void reserve_maybe(const sequence &, void *) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||||
|
if (!std::is_lvalue_reference<T>::value) {
|
||||||
|
policy = return_value_policy_override<Value>::policy(policy);
|
||||||
|
}
|
||||||
|
list l(src.size());
|
||||||
|
ssize_t index = 0;
|
||||||
|
for (auto &&value : src) {
|
||||||
|
auto value_ = reinterpret_steal<object>(
|
||||||
|
value_conv::cast(detail::forward_like<T>(value), policy, parent));
|
||||||
|
if (!value_) {
|
||||||
|
return handle();
|
||||||
|
}
|
||||||
|
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
|
||||||
|
}
|
||||||
|
return l.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(Type, const_name("List[") + value_conv::name + const_name("]"));
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type, typename Alloc>
|
||||||
|
struct type_caster<std::vector<Type, Alloc>> : list_caster<std::vector<Type, Alloc>, Type> {};
|
||||||
|
|
||||||
|
template <typename Type, typename Alloc>
|
||||||
|
struct type_caster<std::deque<Type, Alloc>> : list_caster<std::deque<Type, Alloc>, Type> {};
|
||||||
|
|
||||||
|
template <typename Type, typename Alloc>
|
||||||
|
struct type_caster<std::list<Type, Alloc>> : list_caster<std::list<Type, Alloc>, Type> {};
|
||||||
|
|
||||||
|
template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0>
|
||||||
|
struct array_caster {
|
||||||
|
using value_conv = make_caster<Value>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <bool R = Resizable>
|
||||||
|
bool require_size(enable_if_t<R, size_t> size) {
|
||||||
|
if (value.size() != size) {
|
||||||
|
value.resize(size);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template <bool R = Resizable>
|
||||||
|
bool require_size(enable_if_t<!R, size_t> size) {
|
||||||
|
return size == Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
if (!isinstance<sequence>(src)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto l = reinterpret_borrow<sequence>(src);
|
||||||
|
if (!require_size(l.size())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
size_t ctr = 0;
|
||||||
|
for (auto it : l) {
|
||||||
|
value_conv conv;
|
||||||
|
if (!conv.load(it, convert)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value[ctr++] = cast_op<Value &&>(std::move(conv));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||||
|
list l(src.size());
|
||||||
|
ssize_t index = 0;
|
||||||
|
for (auto &&value : src) {
|
||||||
|
auto value_ = reinterpret_steal<object>(
|
||||||
|
value_conv::cast(detail::forward_like<T>(value), policy, parent));
|
||||||
|
if (!value_) {
|
||||||
|
return handle();
|
||||||
|
}
|
||||||
|
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
|
||||||
|
}
|
||||||
|
return l.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(ArrayType,
|
||||||
|
const_name<Resizable>(const_name(""), const_name("Annotated["))
|
||||||
|
+ const_name("List[") + value_conv::name + const_name("]")
|
||||||
|
+ const_name<Resizable>(const_name(""),
|
||||||
|
const_name(", FixedSize(")
|
||||||
|
+ const_name<Size>() + const_name(")]")));
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type, size_t Size>
|
||||||
|
struct type_caster<std::array<Type, Size>>
|
||||||
|
: array_caster<std::array<Type, Size>, Type, false, Size> {};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
struct type_caster<std::valarray<Type>> : array_caster<std::valarray<Type>, Type, true> {};
|
||||||
|
|
||||||
|
template <typename Key, typename Compare, typename Alloc>
|
||||||
|
struct type_caster<std::set<Key, Compare, Alloc>>
|
||||||
|
: set_caster<std::set<Key, Compare, Alloc>, Key> {};
|
||||||
|
|
||||||
|
template <typename Key, typename Hash, typename Equal, typename Alloc>
|
||||||
|
struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
|
||||||
|
: set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> {};
|
||||||
|
|
||||||
|
template <typename Key, typename Value, typename Compare, typename Alloc>
|
||||||
|
struct type_caster<std::map<Key, Value, Compare, Alloc>>
|
||||||
|
: map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> {};
|
||||||
|
|
||||||
|
template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc>
|
||||||
|
struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
|
||||||
|
: map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> {};
|
||||||
|
|
||||||
|
// This type caster is intended to be used for std::optional and std::experimental::optional
|
||||||
|
template <typename Type, typename Value = typename Type::value_type>
|
||||||
|
struct optional_caster {
|
||||||
|
using value_conv = make_caster<Value>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||||
|
if (!src) {
|
||||||
|
return none().release();
|
||||||
|
}
|
||||||
|
if (!std::is_lvalue_reference<T>::value) {
|
||||||
|
policy = return_value_policy_override<Value>::policy(policy);
|
||||||
|
}
|
||||||
|
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
|
||||||
|
return value_conv::cast(*std::forward<T>(src), policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
if (!src) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (src.is_none()) {
|
||||||
|
return true; // default-constructed value is already empty
|
||||||
|
}
|
||||||
|
value_conv inner_caster;
|
||||||
|
if (!inner_caster.load(src, convert)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value.emplace(cast_op<Value &&>(std::move(inner_caster)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(Type, const_name("Optional[") + value_conv::name + const_name("]"));
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(PYBIND11_HAS_OPTIONAL)
|
||||||
|
template <typename T>
|
||||||
|
struct type_caster<std::optional<T>> : public optional_caster<std::optional<T>> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct type_caster<std::nullopt_t> : public void_caster<std::nullopt_t> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PYBIND11_HAS_EXP_OPTIONAL)
|
||||||
|
template <typename T>
|
||||||
|
struct type_caster<std::experimental::optional<T>>
|
||||||
|
: public optional_caster<std::experimental::optional<T>> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct type_caster<std::experimental::nullopt_t>
|
||||||
|
: public void_caster<std::experimental::nullopt_t> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Visit a variant and cast any found type to Python
|
||||||
|
struct variant_caster_visitor {
|
||||||
|
return_value_policy policy;
|
||||||
|
handle parent;
|
||||||
|
|
||||||
|
using result_type = handle; // required by boost::variant in C++11
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
result_type operator()(T &&src) const {
|
||||||
|
return make_caster<T>::cast(std::forward<T>(src), policy, parent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Helper class which abstracts away variant's `visit` function. `std::variant` and similar
|
||||||
|
/// `namespace::variant` types which provide a `namespace::visit()` function are handled here
|
||||||
|
/// automatically using argument-dependent lookup. Users can provide specializations for other
|
||||||
|
/// variant-like classes, e.g. `boost::variant` and `boost::apply_visitor`.
|
||||||
|
template <template <typename...> class Variant>
|
||||||
|
struct visit_helper {
|
||||||
|
template <typename... Args>
|
||||||
|
static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) {
|
||||||
|
return visit(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Generic variant caster
|
||||||
|
template <typename Variant>
|
||||||
|
struct variant_caster;
|
||||||
|
|
||||||
|
template <template <typename...> class V, typename... Ts>
|
||||||
|
struct variant_caster<V<Ts...>> {
|
||||||
|
static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative.");
|
||||||
|
|
||||||
|
template <typename U, typename... Us>
|
||||||
|
bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
|
||||||
|
auto caster = make_caster<U>();
|
||||||
|
if (caster.load(src, convert)) {
|
||||||
|
value = cast_op<U>(std::move(caster));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return load_alternative(src, convert, type_list<Us...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_alternative(handle, bool, type_list<>) { return false; }
|
||||||
|
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
// Do a first pass without conversions to improve constructor resolution.
|
||||||
|
// E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int`
|
||||||
|
// slot of the variant. Without two-pass loading `double` would be filled
|
||||||
|
// because it appears first and a conversion is possible.
|
||||||
|
if (convert && load_alternative(src, false, type_list<Ts...>{})) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return load_alternative(src, convert, type_list<Ts...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Variant>
|
||||||
|
static handle cast(Variant &&src, return_value_policy policy, handle parent) {
|
||||||
|
return visit_helper<V>::call(variant_caster_visitor{policy, parent},
|
||||||
|
std::forward<Variant>(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
using Type = V<Ts...>;
|
||||||
|
PYBIND11_TYPE_CASTER(Type,
|
||||||
|
const_name("Union[") + detail::concat(make_caster<Ts>::name...)
|
||||||
|
+ const_name("]"));
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(PYBIND11_HAS_VARIANT)
|
||||||
|
template <typename... Ts>
|
||||||
|
struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct type_caster<std::monostate> : public void_caster<std::monostate> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
|
||||||
|
#ifdef PYBIND11_HAS_STRING_VIEW
|
||||||
|
os << str(obj).cast<std::string_view>();
|
||||||
|
#else
|
||||||
|
os << (std::string) str(obj);
|
||||||
|
#endif
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
116
3rdparty/pybind11/include/pybind11/stl/filesystem.h
vendored
Normal file
116
3rdparty/pybind11/include/pybind11/stl/filesystem.h
vendored
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Copyright (c) 2021 The Pybind Development Team.
|
||||||
|
// All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../pybind11.h"
|
||||||
|
#include "../detail/common.h"
|
||||||
|
#include "../detail/descr.h"
|
||||||
|
#include "../cast.h"
|
||||||
|
#include "../pytypes.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef __has_include
|
||||||
|
# if defined(PYBIND11_CPP17)
|
||||||
|
# if __has_include(<filesystem>) && \
|
||||||
|
PY_VERSION_HEX >= 0x03060000
|
||||||
|
# include <filesystem>
|
||||||
|
# define PYBIND11_HAS_FILESYSTEM 1
|
||||||
|
# elif __has_include(<experimental/filesystem>)
|
||||||
|
# include <experimental/filesystem>
|
||||||
|
# define PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM 1
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(PYBIND11_HAS_FILESYSTEM) && !defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM) \
|
||||||
|
&& !defined(PYBIND11_HAS_FILESYSTEM_IS_OPTIONAL)
|
||||||
|
# error \
|
||||||
|
"Neither #include <filesystem> nor #include <experimental/filesystem is available. (Use -DPYBIND11_HAS_FILESYSTEM_IS_OPTIONAL to ignore.)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
#if defined(PYBIND11_HAS_FILESYSTEM) || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
|
||||||
|
template <typename T>
|
||||||
|
struct path_caster {
|
||||||
|
|
||||||
|
private:
|
||||||
|
static PyObject *unicode_from_fs_native(const std::string &w) {
|
||||||
|
# if !defined(PYPY_VERSION)
|
||||||
|
return PyUnicode_DecodeFSDefaultAndSize(w.c_str(), ssize_t(w.size()));
|
||||||
|
# else
|
||||||
|
// PyPy mistakenly declares the first parameter as non-const.
|
||||||
|
return PyUnicode_DecodeFSDefaultAndSize(const_cast<char *>(w.c_str()), ssize_t(w.size()));
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *unicode_from_fs_native(const std::wstring &w) {
|
||||||
|
return PyUnicode_FromWideChar(w.c_str(), ssize_t(w.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static handle cast(const T &path, return_value_policy, handle) {
|
||||||
|
if (auto py_str = unicode_from_fs_native(path.native())) {
|
||||||
|
return module_::import("pathlib")
|
||||||
|
.attr("Path")(reinterpret_steal<object>(py_str))
|
||||||
|
.release();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load(handle handle, bool) {
|
||||||
|
// PyUnicode_FSConverter and PyUnicode_FSDecoder normally take care of
|
||||||
|
// calling PyOS_FSPath themselves, but that's broken on PyPy (PyPy
|
||||||
|
// issue #3168) so we do it ourselves instead.
|
||||||
|
PyObject *buf = PyOS_FSPath(handle.ptr());
|
||||||
|
if (!buf) {
|
||||||
|
PyErr_Clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PyObject *native = nullptr;
|
||||||
|
if constexpr (std::is_same_v<typename T::value_type, char>) {
|
||||||
|
if (PyUnicode_FSConverter(buf, &native) != 0) {
|
||||||
|
if (auto *c_str = PyBytes_AsString(native)) {
|
||||||
|
// AsString returns a pointer to the internal buffer, which
|
||||||
|
// must not be free'd.
|
||||||
|
value = c_str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if constexpr (std::is_same_v<typename T::value_type, wchar_t>) {
|
||||||
|
if (PyUnicode_FSDecoder(buf, &native) != 0) {
|
||||||
|
if (auto *c_str = PyUnicode_AsWideCharString(native, nullptr)) {
|
||||||
|
// AsWideCharString returns a new string that must be free'd.
|
||||||
|
value = c_str; // Copies the string.
|
||||||
|
PyMem_Free(c_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_XDECREF(native);
|
||||||
|
Py_DECREF(buf);
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
PyErr_Clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(T, const_name("os.PathLike"));
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PYBIND11_HAS_FILESYSTEM || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
|
||||||
|
|
||||||
|
#if defined(PYBIND11_HAS_FILESYSTEM)
|
||||||
|
template <>
|
||||||
|
struct type_caster<std::filesystem::path> : public path_caster<std::filesystem::path> {};
|
||||||
|
#elif defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
|
||||||
|
template <>
|
||||||
|
struct type_caster<std::experimental::filesystem::path>
|
||||||
|
: public path_caster<std::experimental::filesystem::path> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
851
3rdparty/pybind11/include/pybind11/stl_bind.h
vendored
Normal file
851
3rdparty/pybind11/include/pybind11/stl_bind.h
vendored
Normal file
@ -0,0 +1,851 @@
|
|||||||
|
/*
|
||||||
|
pybind11/std_bind.h: Binding generators for STL data types
|
||||||
|
|
||||||
|
Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob
|
||||||
|
|
||||||
|
All rights reserved. Use of this source code is governed by a
|
||||||
|
BSD-style license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "detail/common.h"
|
||||||
|
#include "detail/type_caster_base.h"
|
||||||
|
#include "cast.h"
|
||||||
|
#include "operators.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
/* SFINAE helper class used by 'is_comparable */
|
||||||
|
template <typename T>
|
||||||
|
struct container_traits {
|
||||||
|
template <typename T2>
|
||||||
|
static std::true_type
|
||||||
|
test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>()) *);
|
||||||
|
template <typename T2>
|
||||||
|
static std::false_type test_comparable(...);
|
||||||
|
template <typename T2>
|
||||||
|
static std::true_type test_value(typename T2::value_type *);
|
||||||
|
template <typename T2>
|
||||||
|
static std::false_type test_value(...);
|
||||||
|
template <typename T2>
|
||||||
|
static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *);
|
||||||
|
template <typename T2>
|
||||||
|
static std::false_type test_pair(...);
|
||||||
|
|
||||||
|
static constexpr const bool is_comparable
|
||||||
|
= std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value;
|
||||||
|
static constexpr const bool is_pair
|
||||||
|
= std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value;
|
||||||
|
static constexpr const bool is_vector
|
||||||
|
= std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value;
|
||||||
|
static constexpr const bool is_element = !is_pair && !is_vector;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Default: is_comparable -> std::false_type */
|
||||||
|
template <typename T, typename SFINAE = void>
|
||||||
|
struct is_comparable : std::false_type {};
|
||||||
|
|
||||||
|
/* For non-map data structures, check whether operator== can be instantiated */
|
||||||
|
template <typename T>
|
||||||
|
struct is_comparable<
|
||||||
|
T,
|
||||||
|
enable_if_t<container_traits<T>::is_element && container_traits<T>::is_comparable>>
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
/* For a vector/map data structure, recursively check the value type
|
||||||
|
(which is std::pair for maps) */
|
||||||
|
template <typename T>
|
||||||
|
struct is_comparable<T, enable_if_t<container_traits<T>::is_vector>>
|
||||||
|
: is_comparable<typename recursive_container_traits<T>::type_to_check_recursively> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_comparable<recursive_bottom> : std::true_type {};
|
||||||
|
|
||||||
|
/* For pairs, recursively check the two data types */
|
||||||
|
template <typename T>
|
||||||
|
struct is_comparable<T, enable_if_t<container_traits<T>::is_pair>> {
|
||||||
|
static constexpr const bool value = is_comparable<typename T::first_type>::value
|
||||||
|
&& is_comparable<typename T::second_type>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Fallback functions */
|
||||||
|
template <typename, typename, typename... Args>
|
||||||
|
void vector_if_copy_constructible(const Args &...) {}
|
||||||
|
template <typename, typename, typename... Args>
|
||||||
|
void vector_if_equal_operator(const Args &...) {}
|
||||||
|
template <typename, typename, typename... Args>
|
||||||
|
void vector_if_insertion_operator(const Args &...) {}
|
||||||
|
template <typename, typename, typename... Args>
|
||||||
|
void vector_modifiers(const Args &...) {}
|
||||||
|
|
||||||
|
template <typename Vector, typename Class_>
|
||||||
|
void vector_if_copy_constructible(enable_if_t<is_copy_constructible<Vector>::value, Class_> &cl) {
|
||||||
|
cl.def(init<const Vector &>(), "Copy constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Vector, typename Class_>
|
||||||
|
void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_> &cl) {
|
||||||
|
using T = typename Vector::value_type;
|
||||||
|
|
||||||
|
cl.def(self == self);
|
||||||
|
cl.def(self != self);
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"count",
|
||||||
|
[](const Vector &v, const T &x) { return std::count(v.begin(), v.end(), x); },
|
||||||
|
arg("x"),
|
||||||
|
"Return the number of times ``x`` appears in the list");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"remove",
|
||||||
|
[](Vector &v, const T &x) {
|
||||||
|
auto p = std::find(v.begin(), v.end(), x);
|
||||||
|
if (p != v.end()) {
|
||||||
|
v.erase(p);
|
||||||
|
} else {
|
||||||
|
throw value_error();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
arg("x"),
|
||||||
|
"Remove the first item from the list whose value is x. "
|
||||||
|
"It is an error if there is no such item.");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__contains__",
|
||||||
|
[](const Vector &v, const T &x) { return std::find(v.begin(), v.end(), x) != v.end(); },
|
||||||
|
arg("x"),
|
||||||
|
"Return true the container contains ``x``");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vector modifiers -- requires a copyable vector_type:
|
||||||
|
// (Technically, some of these (pop and __delitem__) don't actually require copyability, but it
|
||||||
|
// seems silly to allow deletion but not insertion, so include them here too.)
|
||||||
|
template <typename Vector, typename Class_>
|
||||||
|
void vector_modifiers(
|
||||||
|
enable_if_t<is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) {
|
||||||
|
using T = typename Vector::value_type;
|
||||||
|
using SizeType = typename Vector::size_type;
|
||||||
|
using DiffType = typename Vector::difference_type;
|
||||||
|
|
||||||
|
auto wrap_i = [](DiffType i, SizeType n) {
|
||||||
|
if (i < 0) {
|
||||||
|
i += n;
|
||||||
|
}
|
||||||
|
if (i < 0 || (SizeType) i >= n) {
|
||||||
|
throw index_error();
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"append",
|
||||||
|
[](Vector &v, const T &value) { v.push_back(value); },
|
||||||
|
arg("x"),
|
||||||
|
"Add an item to the end of the list");
|
||||||
|
|
||||||
|
cl.def(init([](const iterable &it) {
|
||||||
|
auto v = std::unique_ptr<Vector>(new Vector());
|
||||||
|
v->reserve(len_hint(it));
|
||||||
|
for (handle h : it) {
|
||||||
|
v->push_back(h.cast<T>());
|
||||||
|
}
|
||||||
|
return v.release();
|
||||||
|
}));
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"clear", [](Vector &v) { v.clear(); }, "Clear the contents");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"extend",
|
||||||
|
[](Vector &v, const Vector &src) { v.insert(v.end(), src.begin(), src.end()); },
|
||||||
|
arg("L"),
|
||||||
|
"Extend the list by appending all the items in the given list");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"extend",
|
||||||
|
[](Vector &v, const iterable &it) {
|
||||||
|
const size_t old_size = v.size();
|
||||||
|
v.reserve(old_size + len_hint(it));
|
||||||
|
try {
|
||||||
|
for (handle h : it) {
|
||||||
|
v.push_back(h.cast<T>());
|
||||||
|
}
|
||||||
|
} catch (const cast_error &) {
|
||||||
|
v.erase(v.begin() + static_cast<typename Vector::difference_type>(old_size),
|
||||||
|
v.end());
|
||||||
|
try {
|
||||||
|
v.shrink_to_fit();
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
arg("L"),
|
||||||
|
"Extend the list by appending all the items in the given list");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"insert",
|
||||||
|
[](Vector &v, DiffType i, const T &x) {
|
||||||
|
// Can't use wrap_i; i == v.size() is OK
|
||||||
|
if (i < 0) {
|
||||||
|
i += v.size();
|
||||||
|
}
|
||||||
|
if (i < 0 || (SizeType) i > v.size()) {
|
||||||
|
throw index_error();
|
||||||
|
}
|
||||||
|
v.insert(v.begin() + i, x);
|
||||||
|
},
|
||||||
|
arg("i"),
|
||||||
|
arg("x"),
|
||||||
|
"Insert an item at a given position.");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"pop",
|
||||||
|
[](Vector &v) {
|
||||||
|
if (v.empty()) {
|
||||||
|
throw index_error();
|
||||||
|
}
|
||||||
|
T t = std::move(v.back());
|
||||||
|
v.pop_back();
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
"Remove and return the last item");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"pop",
|
||||||
|
[wrap_i](Vector &v, DiffType i) {
|
||||||
|
i = wrap_i(i, v.size());
|
||||||
|
T t = std::move(v[(SizeType) i]);
|
||||||
|
v.erase(std::next(v.begin(), i));
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
arg("i"),
|
||||||
|
"Remove and return the item at index ``i``");
|
||||||
|
|
||||||
|
cl.def("__setitem__", [wrap_i](Vector &v, DiffType i, const T &t) {
|
||||||
|
i = wrap_i(i, v.size());
|
||||||
|
v[(SizeType) i] = t;
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Slicing protocol
|
||||||
|
cl.def(
|
||||||
|
"__getitem__",
|
||||||
|
[](const Vector &v, const slice &slice) -> Vector * {
|
||||||
|
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||||
|
|
||||||
|
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *seq = new Vector();
|
||||||
|
seq->reserve((size_t) slicelength);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < slicelength; ++i) {
|
||||||
|
seq->push_back(v[start]);
|
||||||
|
start += step;
|
||||||
|
}
|
||||||
|
return seq;
|
||||||
|
},
|
||||||
|
arg("s"),
|
||||||
|
"Retrieve list elements using a slice object");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__setitem__",
|
||||||
|
[](Vector &v, const slice &slice, const Vector &value) {
|
||||||
|
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||||
|
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slicelength != value.size()) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Left and right hand size of slice assignment have different sizes!");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < slicelength; ++i) {
|
||||||
|
v[start] = value[i];
|
||||||
|
start += step;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Assign list elements using a slice object");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__delitem__",
|
||||||
|
[wrap_i](Vector &v, DiffType i) {
|
||||||
|
i = wrap_i(i, v.size());
|
||||||
|
v.erase(v.begin() + i);
|
||||||
|
},
|
||||||
|
"Delete the list elements at index ``i``");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__delitem__",
|
||||||
|
[](Vector &v, const slice &slice) {
|
||||||
|
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||||
|
|
||||||
|
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (step == 1 && false) {
|
||||||
|
v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength));
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < slicelength; ++i) {
|
||||||
|
v.erase(v.begin() + DiffType(start));
|
||||||
|
start += step - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Delete list elements using a slice object");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the type has an operator[] that doesn't return a reference (most notably std::vector<bool>),
|
||||||
|
// we have to access by copying; otherwise we return by reference.
|
||||||
|
template <typename Vector>
|
||||||
|
using vector_needs_copy
|
||||||
|
= negation<std::is_same<decltype(std::declval<Vector>()[typename Vector::size_type()]),
|
||||||
|
typename Vector::value_type &>>;
|
||||||
|
|
||||||
|
// The usual case: access and iterate by reference
|
||||||
|
template <typename Vector, typename Class_>
|
||||||
|
void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl) {
|
||||||
|
using T = typename Vector::value_type;
|
||||||
|
using SizeType = typename Vector::size_type;
|
||||||
|
using DiffType = typename Vector::difference_type;
|
||||||
|
using ItType = typename Vector::iterator;
|
||||||
|
|
||||||
|
auto wrap_i = [](DiffType i, SizeType n) {
|
||||||
|
if (i < 0) {
|
||||||
|
i += n;
|
||||||
|
}
|
||||||
|
if (i < 0 || (SizeType) i >= n) {
|
||||||
|
throw index_error();
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__getitem__",
|
||||||
|
[wrap_i](Vector &v, DiffType i) -> T & {
|
||||||
|
i = wrap_i(i, v.size());
|
||||||
|
return v[(SizeType) i];
|
||||||
|
},
|
||||||
|
return_value_policy::reference_internal // ref + keepalive
|
||||||
|
);
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__iter__",
|
||||||
|
[](Vector &v) {
|
||||||
|
return make_iterator<return_value_policy::reference_internal, ItType, ItType, T &>(
|
||||||
|
v.begin(), v.end());
|
||||||
|
},
|
||||||
|
keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The case for special objects, like std::vector<bool>, that have to be returned-by-copy:
|
||||||
|
template <typename Vector, typename Class_>
|
||||||
|
void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl) {
|
||||||
|
using T = typename Vector::value_type;
|
||||||
|
using SizeType = typename Vector::size_type;
|
||||||
|
using DiffType = typename Vector::difference_type;
|
||||||
|
using ItType = typename Vector::iterator;
|
||||||
|
cl.def("__getitem__", [](const Vector &v, DiffType i) -> T {
|
||||||
|
if (i < 0) {
|
||||||
|
i += v.size();
|
||||||
|
if (i < 0) {
|
||||||
|
throw index_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto i_st = static_cast<SizeType>(i);
|
||||||
|
if (i_st >= v.size()) {
|
||||||
|
throw index_error();
|
||||||
|
}
|
||||||
|
return v[i_st];
|
||||||
|
});
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__iter__",
|
||||||
|
[](Vector &v) {
|
||||||
|
return make_iterator<return_value_policy::copy, ItType, ItType, T>(v.begin(), v.end());
|
||||||
|
},
|
||||||
|
keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Vector, typename Class_>
|
||||||
|
auto vector_if_insertion_operator(Class_ &cl, std::string const &name)
|
||||||
|
-> decltype(std::declval<std::ostream &>() << std::declval<typename Vector::value_type>(),
|
||||||
|
void()) {
|
||||||
|
using size_type = typename Vector::size_type;
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__repr__",
|
||||||
|
[name](Vector &v) {
|
||||||
|
std::ostringstream s;
|
||||||
|
s << name << '[';
|
||||||
|
for (size_type i = 0; i < v.size(); ++i) {
|
||||||
|
s << v[i];
|
||||||
|
if (i != v.size() - 1) {
|
||||||
|
s << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s << ']';
|
||||||
|
return s.str();
|
||||||
|
},
|
||||||
|
"Return the canonical string representation of this list.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide the buffer interface for vectors if we have data() and we have a format for it
|
||||||
|
// GCC seems to have "void std::vector<bool>::data()" - doing SFINAE on the existence of data()
|
||||||
|
// is insufficient, we need to check it returns an appropriate pointer
|
||||||
|
template <typename Vector, typename = void>
|
||||||
|
struct vector_has_data_and_format : std::false_type {};
|
||||||
|
template <typename Vector>
|
||||||
|
struct vector_has_data_and_format<
|
||||||
|
Vector,
|
||||||
|
enable_if_t<std::is_same<decltype(format_descriptor<typename Vector::value_type>::format(),
|
||||||
|
std::declval<Vector>().data()),
|
||||||
|
typename Vector::value_type *>::value>> : std::true_type {};
|
||||||
|
|
||||||
|
// [workaround(intel)] Separate function required here
|
||||||
|
// Workaround as the Intel compiler does not compile the enable_if_t part below
|
||||||
|
// (tested with icc (ICC) 2021.1 Beta 20200827)
|
||||||
|
template <typename... Args>
|
||||||
|
constexpr bool args_any_are_buffer() {
|
||||||
|
return detail::any_of<std::is_same<Args, buffer_protocol>...>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [workaround(intel)] Separate function required here
|
||||||
|
// [workaround(msvc)] Can't use constexpr bool in return type
|
||||||
|
|
||||||
|
// Add the buffer interface to a vector
|
||||||
|
template <typename Vector, typename Class_, typename... Args>
|
||||||
|
void vector_buffer_impl(Class_ &cl, std::true_type) {
|
||||||
|
using T = typename Vector::value_type;
|
||||||
|
|
||||||
|
static_assert(vector_has_data_and_format<Vector>::value,
|
||||||
|
"There is not an appropriate format descriptor for this vector");
|
||||||
|
|
||||||
|
// numpy.h declares this for arbitrary types, but it may raise an exception and crash hard
|
||||||
|
// at runtime if PYBIND11_NUMPY_DTYPE hasn't been called, so check here
|
||||||
|
format_descriptor<T>::format();
|
||||||
|
|
||||||
|
cl.def_buffer([](Vector &v) -> buffer_info {
|
||||||
|
return buffer_info(v.data(),
|
||||||
|
static_cast<ssize_t>(sizeof(T)),
|
||||||
|
format_descriptor<T>::format(),
|
||||||
|
1,
|
||||||
|
{v.size()},
|
||||||
|
{sizeof(T)});
|
||||||
|
});
|
||||||
|
|
||||||
|
cl.def(init([](const buffer &buf) {
|
||||||
|
auto info = buf.request();
|
||||||
|
if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T))) {
|
||||||
|
throw type_error("Only valid 1D buffers can be copied to a vector");
|
||||||
|
}
|
||||||
|
if (!detail::compare_buffer_info<T>::compare(info)
|
||||||
|
|| (ssize_t) sizeof(T) != info.itemsize) {
|
||||||
|
throw type_error("Format mismatch (Python: " + info.format
|
||||||
|
+ " C++: " + format_descriptor<T>::format() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
T *p = static_cast<T *>(info.ptr);
|
||||||
|
ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
|
||||||
|
T *end = p + info.shape[0] * step;
|
||||||
|
if (step == 1) {
|
||||||
|
return Vector(p, end);
|
||||||
|
}
|
||||||
|
Vector vec;
|
||||||
|
vec.reserve((size_t) info.shape[0]);
|
||||||
|
for (; p != end; p += step) {
|
||||||
|
vec.push_back(*p);
|
||||||
|
}
|
||||||
|
return vec;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Vector, typename Class_, typename... Args>
|
||||||
|
void vector_buffer_impl(Class_ &, std::false_type) {}
|
||||||
|
|
||||||
|
template <typename Vector, typename Class_, typename... Args>
|
||||||
|
void vector_buffer(Class_ &cl) {
|
||||||
|
vector_buffer_impl<Vector, Class_, Args...>(
|
||||||
|
cl, detail::any_of<std::is_same<Args, buffer_protocol>...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
//
|
||||||
|
// std::vector
|
||||||
|
//
|
||||||
|
template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args>
|
||||||
|
class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args &&...args) {
|
||||||
|
using Class_ = class_<Vector, holder_type>;
|
||||||
|
|
||||||
|
// If the value_type is unregistered (e.g. a converting type) or is itself registered
|
||||||
|
// module-local then make the vector binding module-local as well:
|
||||||
|
using vtype = typename Vector::value_type;
|
||||||
|
auto *vtype_info = detail::get_type_info(typeid(vtype));
|
||||||
|
bool local = !vtype_info || vtype_info->module_local;
|
||||||
|
|
||||||
|
Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
// Declare the buffer interface if a buffer_protocol() is passed in
|
||||||
|
detail::vector_buffer<Vector, Class_, Args...>(cl);
|
||||||
|
|
||||||
|
cl.def(init<>());
|
||||||
|
|
||||||
|
// Register copy constructor (if possible)
|
||||||
|
detail::vector_if_copy_constructible<Vector, Class_>(cl);
|
||||||
|
|
||||||
|
// Register comparison-related operators and functions (if possible)
|
||||||
|
detail::vector_if_equal_operator<Vector, Class_>(cl);
|
||||||
|
|
||||||
|
// Register stream insertion operator (if possible)
|
||||||
|
detail::vector_if_insertion_operator<Vector, Class_>(cl, name);
|
||||||
|
|
||||||
|
// Modifiers require copyable vector value type
|
||||||
|
detail::vector_modifiers<Vector, Class_>(cl);
|
||||||
|
|
||||||
|
// Accessor and iterator; return by value if copyable, otherwise we return by ref + keep-alive
|
||||||
|
detail::vector_accessor<Vector, Class_>(cl);
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__bool__",
|
||||||
|
[](const Vector &v) -> bool { return !v.empty(); },
|
||||||
|
"Check whether the list is nonempty");
|
||||||
|
|
||||||
|
cl.def("__len__", &Vector::size);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// C++ style functions deprecated, leaving it here as an example
|
||||||
|
cl.def(init<size_type>());
|
||||||
|
|
||||||
|
cl.def("resize",
|
||||||
|
(void (Vector::*) (size_type count)) & Vector::resize,
|
||||||
|
"changes the number of elements stored");
|
||||||
|
|
||||||
|
cl.def("erase",
|
||||||
|
[](Vector &v, SizeType i) {
|
||||||
|
if (i >= v.size())
|
||||||
|
throw index_error();
|
||||||
|
v.erase(v.begin() + i);
|
||||||
|
}, "erases element at index ``i``");
|
||||||
|
|
||||||
|
cl.def("empty", &Vector::empty, "checks whether the container is empty");
|
||||||
|
cl.def("size", &Vector::size, "returns the number of elements");
|
||||||
|
cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end");
|
||||||
|
cl.def("pop_back", &Vector::pop_back, "removes the last element");
|
||||||
|
|
||||||
|
cl.def("max_size", &Vector::max_size, "returns the maximum possible number of elements");
|
||||||
|
cl.def("reserve", &Vector::reserve, "reserves storage");
|
||||||
|
cl.def("capacity", &Vector::capacity, "returns the number of elements that can be held in currently allocated storage");
|
||||||
|
cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory");
|
||||||
|
|
||||||
|
cl.def("clear", &Vector::clear, "clears the contents");
|
||||||
|
cl.def("swap", &Vector::swap, "swaps the contents");
|
||||||
|
|
||||||
|
cl.def("front", [](Vector &v) {
|
||||||
|
if (v.size()) return v.front();
|
||||||
|
else throw index_error();
|
||||||
|
}, "access the first element");
|
||||||
|
|
||||||
|
cl.def("back", [](Vector &v) {
|
||||||
|
if (v.size()) return v.back();
|
||||||
|
else throw index_error();
|
||||||
|
}, "access the last element ");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// std::map, std::unordered_map
|
||||||
|
//
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
/* Fallback functions */
|
||||||
|
template <typename, typename, typename... Args>
|
||||||
|
void map_if_insertion_operator(const Args &...) {}
|
||||||
|
template <typename, typename, typename... Args>
|
||||||
|
void map_assignment(const Args &...) {}
|
||||||
|
|
||||||
|
// Map assignment when copy-assignable: just copy the value
|
||||||
|
template <typename Map, typename Class_>
|
||||||
|
void map_assignment(
|
||||||
|
enable_if_t<is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
|
||||||
|
using KeyType = typename Map::key_type;
|
||||||
|
using MappedType = typename Map::mapped_type;
|
||||||
|
|
||||||
|
cl.def("__setitem__", [](Map &m, const KeyType &k, const MappedType &v) {
|
||||||
|
auto it = m.find(k);
|
||||||
|
if (it != m.end()) {
|
||||||
|
it->second = v;
|
||||||
|
} else {
|
||||||
|
m.emplace(k, v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not copy-assignable, but still copy-constructible: we can update the value by erasing and
|
||||||
|
// reinserting
|
||||||
|
template <typename Map, typename Class_>
|
||||||
|
void map_assignment(enable_if_t<!is_copy_assignable<typename Map::mapped_type>::value
|
||||||
|
&& is_copy_constructible<typename Map::mapped_type>::value,
|
||||||
|
Class_> &cl) {
|
||||||
|
using KeyType = typename Map::key_type;
|
||||||
|
using MappedType = typename Map::mapped_type;
|
||||||
|
|
||||||
|
cl.def("__setitem__", [](Map &m, const KeyType &k, const MappedType &v) {
|
||||||
|
// We can't use m[k] = v; because value type might not be default constructable
|
||||||
|
auto r = m.emplace(k, v);
|
||||||
|
if (!r.second) {
|
||||||
|
// value type is not copy assignable so the only way to insert it is to erase it
|
||||||
|
// first...
|
||||||
|
m.erase(r.first);
|
||||||
|
m.emplace(k, v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Map, typename Class_>
|
||||||
|
auto map_if_insertion_operator(Class_ &cl, std::string const &name)
|
||||||
|
-> decltype(std::declval<std::ostream &>() << std::declval<typename Map::key_type>()
|
||||||
|
<< std::declval<typename Map::mapped_type>(),
|
||||||
|
void()) {
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__repr__",
|
||||||
|
[name](Map &m) {
|
||||||
|
std::ostringstream s;
|
||||||
|
s << name << '{';
|
||||||
|
bool f = false;
|
||||||
|
for (auto const &kv : m) {
|
||||||
|
if (f) {
|
||||||
|
s << ", ";
|
||||||
|
}
|
||||||
|
s << kv.first << ": " << kv.second;
|
||||||
|
f = true;
|
||||||
|
}
|
||||||
|
s << '}';
|
||||||
|
return s.str();
|
||||||
|
},
|
||||||
|
"Return the canonical string representation of this map.");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename KeyType>
|
||||||
|
struct keys_view {
|
||||||
|
virtual size_t len() = 0;
|
||||||
|
virtual iterator iter() = 0;
|
||||||
|
virtual bool contains(const KeyType &k) = 0;
|
||||||
|
virtual bool contains(const object &k) = 0;
|
||||||
|
virtual ~keys_view() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename MappedType>
|
||||||
|
struct values_view {
|
||||||
|
virtual size_t len() = 0;
|
||||||
|
virtual iterator iter() = 0;
|
||||||
|
virtual ~values_view() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename KeyType, typename MappedType>
|
||||||
|
struct items_view {
|
||||||
|
virtual size_t len() = 0;
|
||||||
|
virtual iterator iter() = 0;
|
||||||
|
virtual ~items_view() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Map, typename KeysView>
|
||||||
|
struct KeysViewImpl : public KeysView {
|
||||||
|
explicit KeysViewImpl(Map &map) : map(map) {}
|
||||||
|
size_t len() override { return map.size(); }
|
||||||
|
iterator iter() override { return make_key_iterator(map.begin(), map.end()); }
|
||||||
|
bool contains(const typename Map::key_type &k) override { return map.find(k) != map.end(); }
|
||||||
|
bool contains(const object &) override { return false; }
|
||||||
|
Map ↦
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Map, typename ValuesView>
|
||||||
|
struct ValuesViewImpl : public ValuesView {
|
||||||
|
explicit ValuesViewImpl(Map &map) : map(map) {}
|
||||||
|
size_t len() override { return map.size(); }
|
||||||
|
iterator iter() override { return make_value_iterator(map.begin(), map.end()); }
|
||||||
|
Map ↦
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Map, typename ItemsView>
|
||||||
|
struct ItemsViewImpl : public ItemsView {
|
||||||
|
explicit ItemsViewImpl(Map &map) : map(map) {}
|
||||||
|
size_t len() override { return map.size(); }
|
||||||
|
iterator iter() override { return make_iterator(map.begin(), map.end()); }
|
||||||
|
Map ↦
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
|
template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args>
|
||||||
|
class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args &&...args) {
|
||||||
|
using KeyType = typename Map::key_type;
|
||||||
|
using MappedType = typename Map::mapped_type;
|
||||||
|
using StrippedKeyType = detail::remove_cvref_t<KeyType>;
|
||||||
|
using StrippedMappedType = detail::remove_cvref_t<MappedType>;
|
||||||
|
using KeysView = detail::keys_view<StrippedKeyType>;
|
||||||
|
using ValuesView = detail::values_view<StrippedMappedType>;
|
||||||
|
using ItemsView = detail::items_view<StrippedKeyType, StrippedMappedType>;
|
||||||
|
using Class_ = class_<Map, holder_type>;
|
||||||
|
|
||||||
|
// If either type is a non-module-local bound type then make the map binding non-local as well;
|
||||||
|
// otherwise (e.g. both types are either module-local or converting) the map will be
|
||||||
|
// module-local.
|
||||||
|
auto *tinfo = detail::get_type_info(typeid(MappedType));
|
||||||
|
bool local = !tinfo || tinfo->module_local;
|
||||||
|
if (local) {
|
||||||
|
tinfo = detail::get_type_info(typeid(KeyType));
|
||||||
|
local = !tinfo || tinfo->module_local;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
|
||||||
|
static constexpr auto key_type_descr = detail::make_caster<KeyType>::name;
|
||||||
|
static constexpr auto mapped_type_descr = detail::make_caster<MappedType>::name;
|
||||||
|
std::string key_type_name(key_type_descr.text), mapped_type_name(mapped_type_descr.text);
|
||||||
|
|
||||||
|
// If key type isn't properly wrapped, fall back to C++ names
|
||||||
|
if (key_type_name == "%") {
|
||||||
|
key_type_name = detail::type_info_description(typeid(KeyType));
|
||||||
|
}
|
||||||
|
// Similarly for value type:
|
||||||
|
if (mapped_type_name == "%") {
|
||||||
|
mapped_type_name = detail::type_info_description(typeid(MappedType));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap KeysView[KeyType] if it wasn't already wrapped
|
||||||
|
if (!detail::get_type_info(typeid(KeysView))) {
|
||||||
|
class_<KeysView> keys_view(
|
||||||
|
scope, ("KeysView[" + key_type_name + "]").c_str(), pybind11::module_local(local));
|
||||||
|
keys_view.def("__len__", &KeysView::len);
|
||||||
|
keys_view.def("__iter__",
|
||||||
|
&KeysView::iter,
|
||||||
|
keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
|
||||||
|
);
|
||||||
|
keys_view.def("__contains__",
|
||||||
|
static_cast<bool (KeysView::*)(const KeyType &)>(&KeysView::contains));
|
||||||
|
// Fallback for when the object is not of the key type
|
||||||
|
keys_view.def("__contains__",
|
||||||
|
static_cast<bool (KeysView::*)(const object &)>(&KeysView::contains));
|
||||||
|
}
|
||||||
|
// Similarly for ValuesView:
|
||||||
|
if (!detail::get_type_info(typeid(ValuesView))) {
|
||||||
|
class_<ValuesView> values_view(scope,
|
||||||
|
("ValuesView[" + mapped_type_name + "]").c_str(),
|
||||||
|
pybind11::module_local(local));
|
||||||
|
values_view.def("__len__", &ValuesView::len);
|
||||||
|
values_view.def("__iter__",
|
||||||
|
&ValuesView::iter,
|
||||||
|
keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Similarly for ItemsView:
|
||||||
|
if (!detail::get_type_info(typeid(ItemsView))) {
|
||||||
|
class_<ItemsView> items_view(
|
||||||
|
scope,
|
||||||
|
("ItemsView[" + key_type_name + ", ").append(mapped_type_name + "]").c_str(),
|
||||||
|
pybind11::module_local(local));
|
||||||
|
items_view.def("__len__", &ItemsView::len);
|
||||||
|
items_view.def("__iter__",
|
||||||
|
&ItemsView::iter,
|
||||||
|
keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
cl.def(init<>());
|
||||||
|
|
||||||
|
// Register stream insertion operator (if possible)
|
||||||
|
detail::map_if_insertion_operator<Map, Class_>(cl, name);
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__bool__",
|
||||||
|
[](const Map &m) -> bool { return !m.empty(); },
|
||||||
|
"Check whether the map is nonempty");
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__iter__",
|
||||||
|
[](Map &m) { return make_key_iterator(m.begin(), m.end()); },
|
||||||
|
keep_alive<0, 1>() /* Essential: keep map alive while iterator exists */
|
||||||
|
);
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"keys",
|
||||||
|
[](Map &m) {
|
||||||
|
return std::unique_ptr<KeysView>(new detail::KeysViewImpl<Map, KeysView>(m));
|
||||||
|
},
|
||||||
|
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
|
||||||
|
);
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"values",
|
||||||
|
[](Map &m) {
|
||||||
|
return std::unique_ptr<ValuesView>(new detail::ValuesViewImpl<Map, ValuesView>(m));
|
||||||
|
},
|
||||||
|
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
|
||||||
|
);
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"items",
|
||||||
|
[](Map &m) {
|
||||||
|
return std::unique_ptr<ItemsView>(new detail::ItemsViewImpl<Map, ItemsView>(m));
|
||||||
|
},
|
||||||
|
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
|
||||||
|
);
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
"__getitem__",
|
||||||
|
[](Map &m, const KeyType &k) -> MappedType & {
|
||||||
|
auto it = m.find(k);
|
||||||
|
if (it == m.end()) {
|
||||||
|
throw key_error();
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
},
|
||||||
|
return_value_policy::reference_internal // ref + keepalive
|
||||||
|
);
|
||||||
|
|
||||||
|
cl.def("__contains__", [](Map &m, const KeyType &k) -> bool {
|
||||||
|
auto it = m.find(k);
|
||||||
|
if (it == m.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
// Fallback for when the object is not of the key type
|
||||||
|
cl.def("__contains__", [](Map &, const object &) -> bool { return false; });
|
||||||
|
|
||||||
|
// Assignment provided only if the type is copyable
|
||||||
|
detail::map_assignment<Map, Class_>(cl);
|
||||||
|
|
||||||
|
cl.def("__delitem__", [](Map &m, const KeyType &k) {
|
||||||
|
auto it = m.find(k);
|
||||||
|
if (it == m.end()) {
|
||||||
|
throw key_error();
|
||||||
|
}
|
||||||
|
m.erase(it);
|
||||||
|
});
|
||||||
|
|
||||||
|
cl.def("__len__", &Map::size);
|
||||||
|
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
61
3rdparty/pybind11/include/pybind11/type_caster_pyobject_ptr.h
vendored
Normal file
61
3rdparty/pybind11/include/pybind11/type_caster_pyobject_ptr.h
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright (c) 2023 The pybind Community.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "detail/common.h"
|
||||||
|
#include "detail/descr.h"
|
||||||
|
#include "cast.h"
|
||||||
|
#include "pytypes.h"
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class type_caster<PyObject> {
|
||||||
|
public:
|
||||||
|
static constexpr auto name = const_name("object"); // See discussion under PR #4601.
|
||||||
|
|
||||||
|
// This overload is purely to guard against accidents.
|
||||||
|
template <typename T,
|
||||||
|
detail::enable_if_t<!is_same_ignoring_cvref<T, PyObject *>::value, int> = 0>
|
||||||
|
static handle cast(T &&, return_value_policy, handle /*parent*/) {
|
||||||
|
static_assert(is_same_ignoring_cvref<T, PyObject *>::value,
|
||||||
|
"Invalid C++ type T for to-Python conversion (type_caster<PyObject>).");
|
||||||
|
return nullptr; // Unreachable.
|
||||||
|
}
|
||||||
|
|
||||||
|
static handle cast(PyObject *src, return_value_policy policy, handle /*parent*/) {
|
||||||
|
if (src == nullptr) {
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
raise_from(PyExc_SystemError, "src != nullptr but PyErr_Occurred()");
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
if (policy == return_value_policy::take_ownership) {
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
if (policy == return_value_policy::reference
|
||||||
|
|| policy == return_value_policy::automatic_reference) {
|
||||||
|
return handle(src).inc_ref();
|
||||||
|
}
|
||||||
|
pybind11_fail("type_caster<PyObject>::cast(): unsupported return_value_policy: "
|
||||||
|
+ std::to_string(static_cast<int>(policy)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load(handle src, bool) {
|
||||||
|
value = reinterpret_borrow<object>(src);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using cast_op_type = PyObject *;
|
||||||
|
|
||||||
|
explicit operator PyObject *() { return value.ptr(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
object value;
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
284
3rdparty/waitingspinnerwidget.cpp
vendored
284
3rdparty/waitingspinnerwidget.cpp
vendored
@ -1,284 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2012-2014 Alexander Turkin
|
|
||||||
* SPDX-FileCopyrightText: 2014 William Hallatt
|
|
||||||
* SPDX-FileCopyrightText: 2015 Jacob Dawid
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Original Work Copyright (c) 2012-2014 Alexander Turkin
|
|
||||||
Modified 2014 by William Hallatt
|
|
||||||
Modified 2015 by Jacob Dawid
|
|
||||||
|
|
||||||
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,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Own includes
|
|
||||||
#include "waitingspinnerwidget.h"
|
|
||||||
|
|
||||||
// Standard includes
|
|
||||||
#include <cmath>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
// Qt includes
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
WaitingSpinnerWidget::WaitingSpinnerWidget(QWidget *parent,
|
|
||||||
bool centerOnParent,
|
|
||||||
bool disableParentWhenSpinning)
|
|
||||||
: QWidget(parent),
|
|
||||||
_centerOnParent(centerOnParent),
|
|
||||||
_disableParentWhenSpinning(disableParentWhenSpinning) {
|
|
||||||
initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitingSpinnerWidget::WaitingSpinnerWidget(Qt::WindowModality modality,
|
|
||||||
QWidget *parent,
|
|
||||||
bool centerOnParent,
|
|
||||||
bool disableParentWhenSpinning)
|
|
||||||
: QWidget(parent, Qt::Dialog | Qt::FramelessWindowHint),
|
|
||||||
_centerOnParent(centerOnParent),
|
|
||||||
_disableParentWhenSpinning(disableParentWhenSpinning){
|
|
||||||
initialize();
|
|
||||||
|
|
||||||
// We need to set the window modality AFTER we've hidden the
|
|
||||||
// widget for the first time since changing this property while
|
|
||||||
// the widget is visible has no effect.
|
|
||||||
setWindowModality(modality);
|
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::initialize() {
|
|
||||||
_color = Qt::black;
|
|
||||||
_roundness = 100.0;
|
|
||||||
_minimumTrailOpacity = 3.14159265358979323846;
|
|
||||||
_trailFadePercentage = 80.0;
|
|
||||||
_revolutionsPerSecond = 1.57079632679489661923;
|
|
||||||
_numberOfLines = 20;
|
|
||||||
_lineLength = 10;
|
|
||||||
_lineWidth = 2;
|
|
||||||
_innerRadius = 10;
|
|
||||||
_currentCounter = 0;
|
|
||||||
_isSpinning = false;
|
|
||||||
|
|
||||||
_timer = new QTimer(this);
|
|
||||||
connect(_timer, SIGNAL(timeout()), this, SLOT(rotate()));
|
|
||||||
updateSize();
|
|
||||||
updateTimer();
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::paintEvent(QPaintEvent *) {
|
|
||||||
updatePosition();
|
|
||||||
QPainter painter(this);
|
|
||||||
painter.fillRect(this->rect(), Qt::transparent);
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
|
||||||
|
|
||||||
if (_currentCounter >= _numberOfLines) {
|
|
||||||
_currentCounter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
painter.setPen(Qt::NoPen);
|
|
||||||
for (int i = 0; i < _numberOfLines; ++i) {
|
|
||||||
painter.save();
|
|
||||||
painter.translate(_innerRadius + _lineLength,
|
|
||||||
_innerRadius + _lineLength);
|
|
||||||
qreal rotateAngle =
|
|
||||||
static_cast<qreal>(360 * i) / static_cast<qreal>(_numberOfLines);
|
|
||||||
painter.rotate(rotateAngle);
|
|
||||||
painter.translate(_innerRadius, 0);
|
|
||||||
int distance =
|
|
||||||
lineCountDistanceFromPrimary(i, _currentCounter, _numberOfLines);
|
|
||||||
QColor color =
|
|
||||||
currentLineColor(distance, _numberOfLines, _trailFadePercentage,
|
|
||||||
_minimumTrailOpacity, _color);
|
|
||||||
painter.setBrush(color);
|
|
||||||
// TODO improve the way rounded rect is painted
|
|
||||||
painter.drawRoundedRect(
|
|
||||||
QRect(0, -_lineWidth / 2, _lineLength, _lineWidth), _roundness,
|
|
||||||
_roundness, Qt::RelativeSize);
|
|
||||||
painter.restore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::start() {
|
|
||||||
updatePosition();
|
|
||||||
_isSpinning = true;
|
|
||||||
show();
|
|
||||||
|
|
||||||
if(parentWidget() && _disableParentWhenSpinning) {
|
|
||||||
parentWidget()->setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_timer->isActive()) {
|
|
||||||
_timer->start();
|
|
||||||
_currentCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::stop() {
|
|
||||||
_isSpinning = false;
|
|
||||||
hide();
|
|
||||||
|
|
||||||
if(parentWidget() && _disableParentWhenSpinning) {
|
|
||||||
parentWidget()->setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_timer->isActive()) {
|
|
||||||
_timer->stop();
|
|
||||||
_currentCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::setNumberOfLines(int lines) {
|
|
||||||
_numberOfLines = lines;
|
|
||||||
_currentCounter = 0;
|
|
||||||
updateTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::setLineLength(int length) {
|
|
||||||
_lineLength = length;
|
|
||||||
updateSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::setLineWidth(int width) {
|
|
||||||
_lineWidth = width;
|
|
||||||
updateSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::setInnerRadius(int radius) {
|
|
||||||
_innerRadius = radius;
|
|
||||||
updateSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor WaitingSpinnerWidget::color() {
|
|
||||||
return _color;
|
|
||||||
}
|
|
||||||
|
|
||||||
qreal WaitingSpinnerWidget::roundness() {
|
|
||||||
return _roundness;
|
|
||||||
}
|
|
||||||
|
|
||||||
qreal WaitingSpinnerWidget::minimumTrailOpacity() {
|
|
||||||
return _minimumTrailOpacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
qreal WaitingSpinnerWidget::trailFadePercentage() {
|
|
||||||
return _trailFadePercentage;
|
|
||||||
}
|
|
||||||
|
|
||||||
qreal WaitingSpinnerWidget::revolutionsPersSecond() {
|
|
||||||
return _revolutionsPerSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WaitingSpinnerWidget::numberOfLines() {
|
|
||||||
return _numberOfLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WaitingSpinnerWidget::lineLength() {
|
|
||||||
return _lineLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WaitingSpinnerWidget::lineWidth() {
|
|
||||||
return _lineWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WaitingSpinnerWidget::innerRadius() {
|
|
||||||
return _innerRadius;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WaitingSpinnerWidget::isSpinning() const {
|
|
||||||
return _isSpinning;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::setRoundness(qreal roundness) {
|
|
||||||
_roundness = std::max(0.0, std::min(100.0, roundness));
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::setColor(QColor color) {
|
|
||||||
_color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::setRevolutionsPerSecond(qreal revolutionsPerSecond) {
|
|
||||||
_revolutionsPerSecond = revolutionsPerSecond;
|
|
||||||
updateTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::setTrailFadePercentage(qreal trail) {
|
|
||||||
_trailFadePercentage = trail;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::setMinimumTrailOpacity(qreal minimumTrailOpacity) {
|
|
||||||
_minimumTrailOpacity = minimumTrailOpacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::rotate() {
|
|
||||||
++_currentCounter;
|
|
||||||
if (_currentCounter >= _numberOfLines) {
|
|
||||||
_currentCounter = 0;
|
|
||||||
}
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::updateSize() {
|
|
||||||
int size = (_innerRadius + _lineLength) * 2;
|
|
||||||
setFixedSize(size, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::updateTimer() {
|
|
||||||
_timer->setInterval(1000 / (_numberOfLines * _revolutionsPerSecond));
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitingSpinnerWidget::updatePosition() {
|
|
||||||
if (parentWidget() && _centerOnParent) {
|
|
||||||
move(parentWidget()->width() / 2 - width() / 2,
|
|
||||||
parentWidget()->height() / 2 - height() / 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int WaitingSpinnerWidget::lineCountDistanceFromPrimary(int current, int primary,
|
|
||||||
int totalNrOfLines) {
|
|
||||||
int distance = primary - current;
|
|
||||||
if (distance < 0) {
|
|
||||||
distance += totalNrOfLines;
|
|
||||||
}
|
|
||||||
return distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor WaitingSpinnerWidget::currentLineColor(int countDistance, int totalNrOfLines,
|
|
||||||
qreal trailFadePerc, qreal minOpacity,
|
|
||||||
QColor color) {
|
|
||||||
if (countDistance == 0) {
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
const qreal minAlphaF = minOpacity / 100.0;
|
|
||||||
int distanceThreshold =
|
|
||||||
static_cast<int>(ceil((totalNrOfLines - 1) * trailFadePerc / 100.0));
|
|
||||||
if (countDistance > distanceThreshold) {
|
|
||||||
color.setAlphaF(minAlphaF);
|
|
||||||
} else {
|
|
||||||
qreal alphaDiff = color.alphaF() - minAlphaF;
|
|
||||||
qreal gradient = alphaDiff / static_cast<qreal>(distanceThreshold + 1);
|
|
||||||
qreal resultAlpha = color.alphaF() - gradient * countDistance;
|
|
||||||
|
|
||||||
// If alpha is out of bounds, clip it.
|
|
||||||
resultAlpha = std::min(1.0, std::max(0.0, resultAlpha));
|
|
||||||
color.setAlphaF(resultAlpha);
|
|
||||||
}
|
|
||||||
return color;
|
|
||||||
}
|
|
122
3rdparty/waitingspinnerwidget.h
vendored
122
3rdparty/waitingspinnerwidget.h
vendored
@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2012-2014 Alexander Turkin
|
|
||||||
* SPDX-FileCopyrightText: 2014 William Hallatt
|
|
||||||
* SPDX-FileCopyrightText: 2015 Jacob Dawid
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Original Work Copyright (c) 2012-2014 Alexander Turkin
|
|
||||||
Modified 2014 by William Hallatt
|
|
||||||
Modified 2015 by Jacob Dawid
|
|
||||||
|
|
||||||
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,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Qt includes
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QColor>
|
|
||||||
|
|
||||||
class WaitingSpinnerWidget : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
/*! Constructor for "standard" widget behaviour - use this
|
|
||||||
* constructor if you wish to, e.g. embed your widget in another. */
|
|
||||||
WaitingSpinnerWidget(QWidget *parent = nullptr,
|
|
||||||
bool centerOnParent = true,
|
|
||||||
bool disableParentWhenSpinning = true);
|
|
||||||
|
|
||||||
/*! Constructor - use this constructor to automatically create a modal
|
|
||||||
* ("blocking") spinner on top of the calling widget/window. If a valid
|
|
||||||
* parent widget is provided, "centreOnParent" will ensure that
|
|
||||||
* QtWaitingSpinner automatically centres itself on it, if not,
|
|
||||||
* "centreOnParent" is ignored. */
|
|
||||||
WaitingSpinnerWidget(Qt::WindowModality modality,
|
|
||||||
QWidget *parent = nullptr,
|
|
||||||
bool centerOnParent = true,
|
|
||||||
bool disableParentWhenSpinning = true);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void start();
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setColor(QColor color);
|
|
||||||
void setRoundness(qreal roundness);
|
|
||||||
void setMinimumTrailOpacity(qreal minimumTrailOpacity);
|
|
||||||
void setTrailFadePercentage(qreal trail);
|
|
||||||
void setRevolutionsPerSecond(qreal revolutionsPerSecond);
|
|
||||||
void setNumberOfLines(int lines);
|
|
||||||
void setLineLength(int length);
|
|
||||||
void setLineWidth(int width);
|
|
||||||
void setInnerRadius(int radius);
|
|
||||||
void setText(QString text);
|
|
||||||
|
|
||||||
QColor color();
|
|
||||||
qreal roundness();
|
|
||||||
qreal minimumTrailOpacity();
|
|
||||||
qreal trailFadePercentage();
|
|
||||||
qreal revolutionsPersSecond();
|
|
||||||
int numberOfLines();
|
|
||||||
int lineLength();
|
|
||||||
int lineWidth();
|
|
||||||
int innerRadius();
|
|
||||||
|
|
||||||
bool isSpinning() const;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void rotate();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent *paintEvent) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static int lineCountDistanceFromPrimary(int current, int primary,
|
|
||||||
int totalNrOfLines);
|
|
||||||
static QColor currentLineColor(int distance, int totalNrOfLines,
|
|
||||||
qreal trailFadePerc, qreal minOpacity,
|
|
||||||
QColor color);
|
|
||||||
|
|
||||||
void initialize();
|
|
||||||
void updateSize();
|
|
||||||
void updateTimer();
|
|
||||||
void updatePosition();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QColor _color;
|
|
||||||
qreal _roundness; // 0..100
|
|
||||||
qreal _minimumTrailOpacity;
|
|
||||||
qreal _trailFadePercentage;
|
|
||||||
qreal _revolutionsPerSecond;
|
|
||||||
int _numberOfLines;
|
|
||||||
int _lineLength;
|
|
||||||
int _lineWidth;
|
|
||||||
int _innerRadius;
|
|
||||||
|
|
||||||
private:
|
|
||||||
WaitingSpinnerWidget(const WaitingSpinnerWidget&);
|
|
||||||
WaitingSpinnerWidget& operator=(const WaitingSpinnerWidget&);
|
|
||||||
|
|
||||||
QTimer *_timer;
|
|
||||||
bool _centerOnParent;
|
|
||||||
bool _disableParentWhenSpinning;
|
|
||||||
int _currentCounter;
|
|
||||||
bool _isSpinning;
|
|
||||||
};
|
|
53
AUTHORS
53
AUTHORS
@ -4,17 +4,22 @@
|
|||||||
|
|
||||||
# MAINTAINER
|
# MAINTAINER
|
||||||
|
|
||||||
Calamares development is sponsored by Blue Systems GmbH - Liberating Software.
|
|
||||||
|
|
||||||
Calamares maintainers through the years:
|
Calamares maintainers through the years:
|
||||||
* Teo Mrnjavac <teo@kde.org> (maintainer -2017)
|
* Teo Mrnjavac <teo@kde.org> (maintainer -2017)
|
||||||
* Adriaan de Groot <groot@kde.org> (maintainer 2017-)
|
* Adriaan de Groot <groot@kde.org> (maintainer 2017-2022)
|
||||||
|
* Community (2022-)
|
||||||
|
|
||||||
|
Community maintainers are Adriaan de Groot, Anke Boersma, Evan James.
|
||||||
|
|
||||||
|
|
||||||
# CONTRIBUTORS
|
# CONTRIBUTORS
|
||||||
|
|
||||||
Calamares has received contributions of code, documentation, artwork
|
Calamares has received contributions of code, documentation, artwork
|
||||||
and moral support from (alphabetically by first name or nickname):
|
and moral support from (alphabetically by first name or nickname):
|
||||||
|
|
||||||
|
- Aaron Rainbolt
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Aleksey Samoilov
|
||||||
- Alf Gaida
|
- Alf Gaida
|
||||||
- aliveafter1000
|
- aliveafter1000
|
||||||
- Allen Welkie
|
- Allen Welkie
|
||||||
@ -25,53 +30,83 @@ and moral support from (alphabetically by first name or nickname):
|
|||||||
- Arjen Balfoort
|
- Arjen Balfoort
|
||||||
- Arnaud Ferraris
|
- Arnaud Ferraris
|
||||||
- Artem Grinev
|
- Artem Grinev
|
||||||
- artoo@cromnix.org
|
- artoo
|
||||||
- benne-dee
|
- benne-dee
|
||||||
- Bernhard Landauer
|
- Bernhard Landauer
|
||||||
- Bezzy1999
|
- Bezzy1999
|
||||||
- Bill Auger
|
- Bill Auger
|
||||||
- Bob van der Linden
|
- Bob van der Linden
|
||||||
|
- Boria138
|
||||||
|
- Brian Morison
|
||||||
- Caio Jordão Carvalho
|
- Caio Jordão Carvalho
|
||||||
- Camilo Higuita
|
- Camilo Higuita
|
||||||
|
- Christophe Marin
|
||||||
- Collabora LTD
|
- Collabora LTD
|
||||||
- Corey Lang
|
- Corey Lang
|
||||||
- crispg72
|
- crispg72
|
||||||
|
- dalto8
|
||||||
- Dan Simmons
|
- Dan Simmons
|
||||||
- demmm
|
- demmm
|
||||||
|
- DemonKiller
|
||||||
|
- Dominic Hayes
|
||||||
|
- El-Wumbus
|
||||||
|
- Emir SARI
|
||||||
- Emmanuel Arias
|
- Emmanuel Arias
|
||||||
- Enrique Medina Gremaldos
|
- Enrique Medina Gremaldos
|
||||||
- Erik Dubois
|
- Erik Dubois
|
||||||
- Dominic Hayes
|
- Evan Goode
|
||||||
- El-Wumbus
|
|
||||||
- Evan James
|
- Evan James
|
||||||
- Frede H
|
- Evan Maddock
|
||||||
|
- Ficelloo
|
||||||
|
- Frede Hundewadt
|
||||||
- Gabriel Craciunescu
|
- Gabriel Craciunescu
|
||||||
|
- Gaël PORTAY
|
||||||
|
- GeckoLinux
|
||||||
- Harald Sitter
|
- Harald Sitter
|
||||||
|
- Hector Martin
|
||||||
- Huang Jia Wen
|
- Huang Jia Wen
|
||||||
|
- huxingyi
|
||||||
|
- Ivan Borzenkov
|
||||||
|
- Jeremy Attali
|
||||||
|
- Jeremy Whiting
|
||||||
- Jerrod Frost
|
- Jerrod Frost
|
||||||
- Jia Chao
|
- Jia Chao
|
||||||
- Joe Kamprad
|
- Johannes Kamprad
|
||||||
- Jonas Strassel
|
- Jonas Strassel
|
||||||
|
- Jonathan Esk-Riddell
|
||||||
- Kai Dohmen
|
- Kai Dohmen
|
||||||
|
- Kasra Hashemi
|
||||||
- Kevin Kofler
|
- Kevin Kofler
|
||||||
- Kyle Robertze
|
- Kyle Robertze
|
||||||
- Lisa Vitolo
|
- Lisa Vitolo
|
||||||
|
- Lukas Märdian
|
||||||
|
- Mario Haustein
|
||||||
|
- Masato TOYOSHIMA
|
||||||
- Matti Hyttinen
|
- Matti Hyttinen
|
||||||
- n3rdopolis
|
- n3rdopolis
|
||||||
- Neal Gompa
|
- Neal Gompa
|
||||||
- Nico 'dr460nf1r3'
|
- Nico 'dr460nf1r3'
|
||||||
- Omer I.S.
|
- Omer I.S.
|
||||||
|
- Panda
|
||||||
|
- Paolo Dongilli
|
||||||
|
- Peter Jung
|
||||||
- Philip Müller
|
- Philip Müller
|
||||||
- Ramon Buldó
|
- Ramon Buldó
|
||||||
- Raul Rodrigo Segura
|
- Raul Rodrigo Segura
|
||||||
- Rohan Garg
|
- Rohan Garg
|
||||||
- Santosh Mahto
|
- Santosh Mahto
|
||||||
- Scott Harvey
|
- Scott Harvey
|
||||||
|
- shivanandvp
|
||||||
- Simon Quigley
|
- Simon Quigley
|
||||||
|
- Sunderland93
|
||||||
|
- Sławomir Lach
|
||||||
- Taejun Park
|
- Taejun Park
|
||||||
|
- Tj
|
||||||
- Victor Fuentes
|
- Victor Fuentes
|
||||||
|
- Vitor Lopes
|
||||||
- vtriolet
|
- vtriolet
|
||||||
- Walter Lapchynski
|
- Walter Lapchynski
|
||||||
- Waneon Kim
|
- Waneon Kim
|
||||||
|
- wiz64
|
||||||
|
|
||||||
> This list was updated to revision 6e8d820737dea0f3e08f12b10768facef19be684 on May 28th 2022.
|
> This list was updated to revision 283668cb0155c1c14739bb3b51db3d5d0b39c8e2 on February 17th 2024.
|
||||||
|
28
CHANGES-3.2
28
CHANGES-3.2
@ -8,18 +8,36 @@ changelog -- this log starts with version 3.2.0. The release notes on the
|
|||||||
website will have to do for older versions.
|
website will have to do for older versions.
|
||||||
|
|
||||||
|
|
||||||
> Note that the 3.2 series is now in LTS / bug-fix-only mode.
|
Calamares version 3.2.61 is the last one to have updated CHANGES-3.2
|
||||||
|
in the *calamares* (e.g. development, or 3.3, branch). For changes
|
||||||
|
in the stable release branch, see CHANGES-3.2 in that branch.
|
||||||
|
|
||||||
# 3.2.61 (unreleased) #
|
|
||||||
|
|
||||||
|
# 3.2.61 (2022-08-24) #
|
||||||
|
|
||||||
|
This is the second community-maintainence release of Calamares 3.2.
|
||||||
|
It corrects a handful of bugs foud in the stable release. There
|
||||||
|
are also translation updates.
|
||||||
|
|
||||||
This release contains contributions from (alphabetically by first name):
|
This release contains contributions from (alphabetically by first name):
|
||||||
- No external contributors yet
|
- Adriaan de Groot
|
||||||
|
- Anke Boersma
|
||||||
|
|
||||||
## Core ##
|
## Core ##
|
||||||
- No core changes yet
|
- The "About" and "Debug" buttons in a QWidgets-based panel were no
|
||||||
|
longer translated. This has been fixed (by re-using translations
|
||||||
|
of the same buttons from the QML module. #2030 (Thanks Anke)
|
||||||
|
|
||||||
## Modules ##
|
## Modules ##
|
||||||
- No module changes yet
|
- *bootloader* Python code slipped in that was incompatible with
|
||||||
|
the minimum required Python version. #2033 (Thanks Adriaan)
|
||||||
|
- *locale* fixes a large regression introduced with 3.2.60, where
|
||||||
|
the location picked for many locales was not the same as in 3.2.59,
|
||||||
|
and generally peculiar (e.g. picking "English" led to "en_AG" which
|
||||||
|
is nice if you are in Bermuda, but not expected in the rest of the
|
||||||
|
world). #2008
|
||||||
|
- *luksopenswaphookcfg* Remove duplicate options. #1659 (Thanks Anke)
|
||||||
|
|
||||||
|
|
||||||
# 3.2.60 (2022-06-19) #
|
# 3.2.60 (2022-06-19) #
|
||||||
|
571
CHANGES-3.3
Normal file
571
CHANGES-3.3
Normal file
@ -0,0 +1,571 @@
|
|||||||
|
<!-- SPDX-FileCopyrightText: no
|
||||||
|
SPDX-License-Identifier: CC0-1.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
This is the changelog for Calamares. For each release, the major changes and
|
||||||
|
contributors are listed. Note that Calamares does not have a historical
|
||||||
|
changelog -- this log starts with version 3.3.0. See CHANGES-3.2 for
|
||||||
|
the history of the 3.2 series (2018-05 - 2022-08).
|
||||||
|
|
||||||
|
# 3.3.12 (2024-11-21)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by given name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- This release repairs the Calamares configuration file which is
|
||||||
|
used by external Calamares modules -- calamares-extensions in particular.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *users* module always uses a 3-digit UMASK if one is specified.
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.11 (2024-11-05)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by given name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Jakob Petsovits
|
||||||
|
- Simon Quigley
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Nothing yet
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *unpackfs* now supports a `condition` configuration option for
|
||||||
|
conditional installation / unsquash. (thanks Simon)
|
||||||
|
- *unpackfsc* module imported from Calamares-extensions, and extended
|
||||||
|
with the same `condition` configuration.
|
||||||
|
- *partition* crash fixed when swap was using the wrong end-sector
|
||||||
|
in some GPT configurations. (thanks Jakob, #2367)
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.10 (2024-10-21)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by given name):
|
||||||
|
- Aaron Rainbolt
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Evan James
|
||||||
|
- Neal Gompa
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Nothing yet
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *keyboard* Repaired summary messages with strange formatting. (#2364)
|
||||||
|
- *keyboard* Can update KDE Plasma configuration in Wayland. (thanks Neal, #2264)
|
||||||
|
- *locale* Repaired summary messages with strange formatting. (#2364)
|
||||||
|
- *partition* Module fixed unwanted behavior with the encryption checkbox. (thanks Aaron, #2376)
|
||||||
|
- *umount* Correctly unmounts the root filesystem of the target. (thanks Evan)
|
||||||
|
- *users* Supports a new `home_permissions` setting to override the
|
||||||
|
distro's `useradd` configuration of the umask. Supports octal and rwx-style
|
||||||
|
specifications of permissions. Other places that use permissions now also
|
||||||
|
support octal and rwx-style. (#2362)
|
||||||
|
- *welcome* Follows system styling colors (e.g. Dark Mode).
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.9 (2024-08-12)
|
||||||
|
|
||||||
|
Please note that if you are using the *luksbootkeyfile* module,
|
||||||
|
it must be placed before the *fstab* module in settings.conf. If it comes
|
||||||
|
after, then the keyfile will be missing from crypttab and the user will be
|
||||||
|
asked for their password multiple times.
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by given name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Evan James
|
||||||
|
- Luca Matei Pintilie
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Improved schemas for configuration files
|
||||||
|
- Support for Interlingue in Qt 6.7
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- Placed *luksbootkeyfile* before *fstab* in the example `settings.conf` (#2356, Evan)
|
||||||
|
- *packages* module `xbcs` package manager now logs progress messages (#2359, Luca)
|
||||||
|
- *partition* module mentions creating a swap file in its summary (#2320, Adriaan)
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.8 (2024-07-02)
|
||||||
|
|
||||||
|
The *partition* bug described below was reported by jghodd, then carefully
|
||||||
|
described and made reproducible by Joe Kamprad, examined by Evan James
|
||||||
|
and repaired by Adriaan de Groot. Many thanks to all who participated.
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Evan James
|
||||||
|
- Lorenzo Faletra
|
||||||
|
- Tj
|
||||||
|
- Victor Fuentes
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- nothing in particular
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *contextualprocess* see *shellprocess*.
|
||||||
|
- *mount* module now correctly mounts luks and luks2-encrypted swap. (thanks Victor)
|
||||||
|
- *partition* avoids a crash with specific checkbox-presets. (thanks Evan)
|
||||||
|
- *partition* had a bug where manual partitioning on MBR systems might
|
||||||
|
skip the installation of a bootloader, even though the visible bootloader
|
||||||
|
combo-box showed that it would be installed. (see #2318)
|
||||||
|
- *partition* could calculate an incorrect partition size when installing to
|
||||||
|
very specific partition sizes, and now leaves a few more sectors for secondary
|
||||||
|
GPT tables. (thanks Tj)
|
||||||
|
- *shellprocess* now supports a *verbose* key (globally and per-command) which logs
|
||||||
|
command output line-by-line.
|
||||||
|
- *users* module defaults password salt to *yescrypt*. (thanks Lorenzo)
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.7 (2024-06-20)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Eugene San
|
||||||
|
- Evan James
|
||||||
|
- Ivan Borzenkov
|
||||||
|
- Sohrab Behdani
|
||||||
|
- Vincent Penvern
|
||||||
|
- Vladislav Nepogodin
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Updated clang-formatting
|
||||||
|
- Some C++20 future-proofing (thanks Vladislav)
|
||||||
|
- CommandList (used by *contextualprocess* and *shellprocess*) now supports
|
||||||
|
globalstorage keys as substitutable variables.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *contextualprocess* see *shellprocess*.
|
||||||
|
- *fstab* module does not add an encryption keyfile if it does
|
||||||
|
not exist. (thanks Eugene)
|
||||||
|
- *initcpiocfg* has some new configuration settings to more carefully
|
||||||
|
adjust hooks for initcpio.
|
||||||
|
- *keyboard* module handles Persian (fa) layout better. (thanks Sohrab)
|
||||||
|
- *keyboard* module handles other non-ascii layout better. (thanks Ivan)
|
||||||
|
- *partition* module did not filter out invalid fstab entries;
|
||||||
|
they were not written, either, so no net change.
|
||||||
|
- *partition* module now has a configurable default check-state
|
||||||
|
for the encryption checkbox. (thanks Vincent)
|
||||||
|
- *shellprocess* commands now support globalstorage variables, which
|
||||||
|
are written as `${gs[key]}`, where `key` is a dotted string that
|
||||||
|
selects the globalstorage key to use (like in *contextualprocess*
|
||||||
|
variable-selectors) and `${gs[` and `]}` are literal characters.
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.6 (2024-04-16)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Anke Boersma
|
||||||
|
- Eugene San
|
||||||
|
- Evan James
|
||||||
|
- Harald Sitter
|
||||||
|
- Mike Stemle
|
||||||
|
- Peter Jung
|
||||||
|
- Simon Quigley
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Various Qt6-related fixes.
|
||||||
|
- Calamares now prevents sleep and suspend while the installation is
|
||||||
|
running, so that unattended installs do not accidentally fall asleep.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *bootloader* Adds "splash" to kernel parameters if plymouth is present.
|
||||||
|
(thanks Eugene)
|
||||||
|
- *locale* Now picks the correct timezone for Dubai, Muscat, Tehran.
|
||||||
|
- *plymouthcfg* Use plymouth-set-default-theme to avoid issues with
|
||||||
|
configuration. (thanks Peter)
|
||||||
|
- *users* module now supports enrolling in Active Directory, if enabled.
|
||||||
|
(thanks Simon)
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.5 (2024-03-03)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Evan James
|
||||||
|
- Peter Jung
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Calamares logs more information about how the executable was created
|
||||||
|
in the session log on startup. This will help in recreating the specific
|
||||||
|
configuration when bug reports are filed. (thanks Evan)
|
||||||
|
- The debug window now has better Qt6 compatibility.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *displaymanager* module can configure an alternate SDDM configuration file.
|
||||||
|
- *networkcfg* a bug affecting NetPlan + NetworkManager was fixed.
|
||||||
|
- *initcpiocfg* Add microcode hook to initcpiocfg
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.4 (2024-02-27)
|
||||||
|
|
||||||
|
In this release, process jobmodules -- a particular kind of module
|
||||||
|
recognizable by `type: job` and `interface: process` in the descriptor
|
||||||
|
file -- undergo a large change to resemble *shellprocess* more.
|
||||||
|
|
||||||
|
Users of process jobmodules are encouraged to double-check the Functionality
|
||||||
|
of those modules in this release.
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Victor Fuentes
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Process jobs (a job type provided by Calamares core) now share more
|
||||||
|
code with *contextualprocess* and *shellprocess* jobs. The execution
|
||||||
|
mechanism is the same, and always invokes the shell, whether the command
|
||||||
|
runs in the host or in the target system. It is no longer necessary to
|
||||||
|
add `/bin/sh` in the *command* key -- this is always present.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *contextualprocess* and *shellprocess* can now set environment variables
|
||||||
|
as part of the configuration. See *shellprocess* documentation for details.
|
||||||
|
This is optional, and does not do anything that could not already be done
|
||||||
|
by putting `export VAR=value ;` in front of the command before.
|
||||||
|
- *partition* fixed a bug with an uninitialized variable. (thanks Victor)
|
||||||
|
- *shellprocess* (and therefore also *contextualprocess* and process
|
||||||
|
jobmodules) now substitutes `${LANG}` in commands with the language
|
||||||
|
selected in the user-interface of Calamares.
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.3 (2024-02-24)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Anke Boersma
|
||||||
|
|
||||||
|
Translations have been updated (3.3.2 skipped that step).
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Core libraries *libcalamares* and *libcalamaresui* now build with
|
||||||
|
hidden visibility by default, as a step towards ABI stability.
|
||||||
|
- A runtime crash caused by (mis?)use of Qt UniqueConnection which
|
||||||
|
shows up in Debug builds was resolved.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *interactiveterminal* can use konsole in Qt6 too. (thanks Anke)
|
||||||
|
- *plasmalnf* module ported to Plasma 6. (thanks Anke)
|
||||||
|
- *welcomeq* example extended to include Markdown syntax. (thanks Anke)
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.2 (2024-02-19)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Aaron Rainbolt
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Anke Boersma
|
||||||
|
- Evan James
|
||||||
|
- Jonathan Riddell
|
||||||
|
- Lukas Märdian
|
||||||
|
- Tj
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Slideshow support code (QML) now ported to Qt6 and made available
|
||||||
|
as two separate directories of support-code. (thanks Jon)
|
||||||
|
- Compatibility with Qt versions prior to 5.15.5 has been removed.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *fstab* bug fixed where BTRFS messes up the partition layout. (thanks Tj)
|
||||||
|
- *networkcfg* on NetPlan-enabled systems, configure NetworkManager
|
||||||
|
with the live-system's NetPlan settings. (thanks Lukas)
|
||||||
|
- *partition* module can now also define unencrypted partitions
|
||||||
|
when encryption is used. (thanks Aaron)
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.1 (2024-01-15)
|
||||||
|
|
||||||
|
This release sets `BUILD_APPDATA` and `BUILD_APSTREAM` to default to **OFF**,
|
||||||
|
where previously they defaulted to **ON**. When enabled, the dependencies for
|
||||||
|
both features are required -- previously they would silently switch off if
|
||||||
|
the dependencies were not found. Distributions are strongly advised to check
|
||||||
|
their package-building instructions.
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Aleksey Samoilov
|
||||||
|
- Emir Sari
|
||||||
|
- Simon Quigley
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- There has been internal code re-organization (e.g. not using functions
|
||||||
|
named `tr()`) to help translation tools.
|
||||||
|
- Strings everywhere have been given more context. (thanks Emir)
|
||||||
|
- In CMake, "view" is no longer accepted as an alias of the module
|
||||||
|
type "viewmodule" in function `calamares_add_plugin()`.
|
||||||
|
- Plain Ubuntu builds have been added to the CI roster. (thanks Simon)
|
||||||
|
- Commands that run in the target system (in the chroot) no longer
|
||||||
|
use the TMP-related environment variables from the host. #2269
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- The *displaymanager* module configuration for `greetd` has some more
|
||||||
|
options now. (thanks Aleksey)
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.0 (2023-12-12)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Alberto Salvia Novella
|
||||||
|
- Christophe Marin
|
||||||
|
- Evan Maddock
|
||||||
|
- Frede Hundewadt
|
||||||
|
|
||||||
|
Since this is the first non-alpha release of 3.3.0, we would like to thank
|
||||||
|
all the contributors to a year and a half of alpha releases, six in all.
|
||||||
|
Distributions are **strongly** advices to take the release notes of
|
||||||
|
the alpha's into account as well.
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- No changes of note.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *users* and *usersq* no longer support the password requirement 'nonempty'.
|
||||||
|
Use 'minLength: 1' instead. The example configuration allows the user to
|
||||||
|
choose any password at all, but also contains suggestions for other
|
||||||
|
password-requirements schemes. (thanks Alberto)
|
||||||
|
- *users* now can use stronger password hashes, if `crypt_gensalt()` is
|
||||||
|
available in the *crypt* library. (thanks Evan)
|
||||||
|
- *machineid* module supports several variations of writing /etc/machine-id .
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.0-alpha6 (2023-11-16)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Anke Boersma
|
||||||
|
|
||||||
|
This is a hotfix release because -alpha5 didn't compile,
|
||||||
|
and Anke repaired the partition unit-tests when building with Qt6.
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.0-alpha5 (2023-11-13)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Alejo Fernandez
|
||||||
|
- Anke Boersma
|
||||||
|
- Christophe Marin
|
||||||
|
- Emir Sari
|
||||||
|
- Evan James
|
||||||
|
- Gaël PORTAY
|
||||||
|
- Gecko Linux
|
||||||
|
- Jeremy Whiting
|
||||||
|
- Neal Gompa
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Boost::Python is no longer a dependency, Calamares uses a bundled copy
|
||||||
|
of pybind11 instead. This speeds up compilation and reducese the
|
||||||
|
dependency tree a great deal. You can set `WITH_PYBIND11=OFF` in the
|
||||||
|
build to keep Boost::Python and all the binary-compatibility problems
|
||||||
|
it entails.
|
||||||
|
- Coding style now wants clang-format 15 or 16, but no longer needs astyle.
|
||||||
|
There is also a clang-tidy file for additional styling support.
|
||||||
|
- Ongoing translation improvements. (thanks Emir)
|
||||||
|
- Translations for bqi (Luri), es_AR (Castellano), eo (Esperanto),
|
||||||
|
ka (Georgian). In **non-release** builds (e.g. between releases,
|
||||||
|
so for developers building directly from git) all translations are
|
||||||
|
enabled, even the ones with no translations at all.
|
||||||
|
- The logging format in the `session.log` file and on-screen is now
|
||||||
|
more similar, although the file contains a lot more per-line information.
|
||||||
|
- The INSTALL_CONFIG option has been restored. It is still a terrible
|
||||||
|
idea to fork the repository to modify the config files, and you
|
||||||
|
probably should have a calamares-config package with those files
|
||||||
|
instead, there are packaging workflows that can usefully patch-and-
|
||||||
|
install configuration files. The option defaults to OFF.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- All QML modules now have a Qt6-compatible set of QML files as well. (thanks Anke)
|
||||||
|
- *packagechooser* supports AppStream 1.0 API.
|
||||||
|
- *unpackfs* now uses the `-S` option to rsync for sparse file support. (thanks Jeremy)
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.0-alpha4 (2023-10-13)
|
||||||
|
|
||||||
|
Another closing-in-on-3.3.0 release! One of the big changes is that
|
||||||
|
Calamares -- the core and nearly all of the modules in this repository --
|
||||||
|
are compatible with Qt6. That is, it compiles. Functionality has not
|
||||||
|
been tested, but early-testing distributions are encouraged to submit
|
||||||
|
pull requests to improve the code.
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Anke Boersma
|
||||||
|
- Emir Sari
|
||||||
|
- Evan James
|
||||||
|
- Hector Martin
|
||||||
|
- Ivan Borzenkov
|
||||||
|
- Simon Quigley
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Qt6 compatibility. You can choose Qt5 (with KDE Frameworks 5) as before,
|
||||||
|
or choose Qt6 (with KDE Frameworks 6). This means that a Qt6-based Linux
|
||||||
|
distribution can use Calamares without needing an extra version of Qt.
|
||||||
|
Note that some KDE Frameworks are required as well, and those need to be
|
||||||
|
Qt6-based also (and are not released as of September 2023).
|
||||||
|
- QML-based modules are also supported in Qt6, but the QML is likely to
|
||||||
|
be source-incompatible. The *welcomeq* module shipped with Calamares
|
||||||
|
now has two `.qrc` files and uses the `${QT_VERSION_SUFFIX}` variable
|
||||||
|
to pick one of the two depending on the Qt version being used.
|
||||||
|
Other modules are likely to follow the same pattern.
|
||||||
|
- C++ namespaces have been shuffled around and `CalamaresUtils` has been
|
||||||
|
retired. This has an effect on all C++ plugins, since this is neither
|
||||||
|
a binary- nor source-compatible change.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *keyboard* module can now be explicitly configured to use X11 keyboard
|
||||||
|
settings or the FreeDesktop locale1 DBus service. The latter is most
|
||||||
|
useful for Calamares as an "initial setup" system, not an installer,
|
||||||
|
in a Wayland session. (thanks Hector)
|
||||||
|
- *keyboard* module now writes X11 layout configuration with variants
|
||||||
|
for all non-ASCII (e.g. us) layouts. (thanks Ivan)
|
||||||
|
- *keyboard* module now can configure keyboard switch. (thanks Ivan)
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.0-alpha3 (2023-08-28)
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Aleksey Samoilov
|
||||||
|
- Anke Boersma
|
||||||
|
- Arjen Balfoort
|
||||||
|
- Boria138
|
||||||
|
- Brian Morison
|
||||||
|
- Emir Sari
|
||||||
|
- Evan Goode
|
||||||
|
- Evan James
|
||||||
|
- Ficelloo
|
||||||
|
- Hector Martin
|
||||||
|
- Jeremy Attall
|
||||||
|
- Johannes Kamprad
|
||||||
|
- Kasta Hashemi
|
||||||
|
- Kevin Kofler
|
||||||
|
- Mario Haustein
|
||||||
|
- Masato TOYOSHIMA
|
||||||
|
- Panda
|
||||||
|
- Paolo Dongilli
|
||||||
|
- Peter Jung
|
||||||
|
- Philip Müller
|
||||||
|
- Shivanand
|
||||||
|
- Sławomir Lach
|
||||||
|
- Sunderland93
|
||||||
|
- wiz64
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- Incompatible module-configuration changes, see #1438.
|
||||||
|
- Branding entries use ${var} instead of @{var} for substitutions,
|
||||||
|
in line with all the other substitution mechanisms used from C++
|
||||||
|
core. See documentation in `branding.desc`.
|
||||||
|
- Boost::Python requires at least version 1.72.
|
||||||
|
- KDE Frameworks must be version 5.58 or later.
|
||||||
|
- The `INSTALL_CONFIG` option has been removed. If you are installing
|
||||||
|
the example configuration files from the Calamares repository, just
|
||||||
|
stop. That was never a good idea, and you should keep your configs elsewhere.
|
||||||
|
- Progress percentage during install can now be localized. (thanks Emir)
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *dracut* added a configurable kernel name. (thanks Anke)
|
||||||
|
- *initcpiocfg* orders hookds slightly differently. (thanks Peter)
|
||||||
|
- *localeq* moved to using Drawer instead of ComboBox in UI. (thanks Anke)
|
||||||
|
- *keyboardq* moved to using Drawer instead of ComboBox in UI. (thanks Anke)
|
||||||
|
- *netinstall* now has a new *noncheckable* option for groups, which prevent
|
||||||
|
it a group from being checked/uncheckd as a whole. You can still check
|
||||||
|
individual items **in** the group though. (thanks Shivanand)
|
||||||
|
- *partition* can now pick LUKS or LUKS2. (thanks Jeremy)
|
||||||
|
- *zfs* creates a hostid through zgenhostid.
|
||||||
|
- *zfshostid* new module to copy zfs generated /etc/hostid
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.0-alpha2 (2022-08-23)
|
||||||
|
|
||||||
|
Second alpha release, with updated ABI compatibility checking,
|
||||||
|
some 3.3.0 release goals, new features in modules and important bugfixes.
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Anke Boersma
|
||||||
|
- Evan James
|
||||||
|
- Shivanand
|
||||||
|
- Vitor Lopes
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
|
||||||
|
A core **TODO** is moving all library code into the `Calamares` namespace,
|
||||||
|
dropping the `CalamaresUtils` namespace. Modern C++ supports nested namespaces,
|
||||||
|
so in some cases we can use those. This has a drastic effect on ABI compatibility,
|
||||||
|
though, as functions move from one namespace to another. This needs to be
|
||||||
|
completed before a 3.3.0 with ABI stability is released.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
|
||||||
|
Module schemas have been updated to reflect all the incompatible changes.
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.0-alpha1 (2022-06-27)
|
||||||
|
|
||||||
|
Initial 3.3.0 alpha release to check the release scripts &c.
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Adriaan de Groot
|
||||||
|
- Aleksey Samoilov
|
||||||
|
- Anke Boersma
|
||||||
|
- Dan Simmons
|
||||||
|
- Evan James
|
||||||
|
- Peter Jung
|
||||||
|
|
||||||
|
|
||||||
|
# 3.3.0-pre-alpha (unreleased) #
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Anke Boersma
|
||||||
|
- Anubhav Choudhary
|
||||||
|
- Evan James
|
||||||
|
- Vitor Lopes
|
||||||
|
|
||||||
|
This is a "minor" version change, but the size of the changes is very
|
||||||
|
large. Configuration files from previous versions of Calamares will
|
||||||
|
**certainly** need to be re-validated. Take heed of the many changes
|
||||||
|
in the *Modules* heading, below.
|
||||||
|
|
||||||
|
Users (distributions) are **strongly** advised to use the tools
|
||||||
|
for configuration validation (`ci/configvalidator.py`) to check
|
||||||
|
that the distribution configuration files follow the current schema.
|
||||||
|
|
||||||
|
## Project ##
|
||||||
|
- The C++ code in the project is now formatted with clang-format 12 or 13,
|
||||||
|
with the coding-style as found in `.clang-format`; there are minor
|
||||||
|
differences from the tool, compared to the clang-format 9 usually applied
|
||||||
|
to Calamares 3.2.
|
||||||
|
- The CMake code in the project is now formatted with gersemi 0.7.5.
|
||||||
|
|
||||||
|
## Core ##
|
||||||
|
- CMake 3.16, Qt 5.15 are now required; the newer CMake is to support
|
||||||
|
new features (also for KDE Frameworks), Qt is the current LTS version.
|
||||||
|
- Running `calamares -d` no longer enforces a single-application
|
||||||
|
(it is for debugging purposes, after all).
|
||||||
|
- Python 3.6 or later is now required, to allow for F-strings in
|
||||||
|
Python code and allow other tidy-ups in the Python modules.
|
||||||
|
Boost::Python now requires 1.67 or later (for CMake support).
|
||||||
|
- The log file now **always** contains a debug-log, and the `-D` flag
|
||||||
|
primarily controls what is printed to stdout. By default, stdout
|
||||||
|
only gets errors; use `-D6` to match stdout with the file. Use `-D8`
|
||||||
|
to get an extra-verbose log file **and** verbose stdout.
|
||||||
|
|
||||||
|
## Modules ##
|
||||||
|
- *bootloader* now supports more options when building the kernel
|
||||||
|
command-line. (Thanks Evan)
|
||||||
|
- *bootloader* no longer supports `@@`-style suffixes for unique-EFI-id
|
||||||
|
generation. Use `${}` instead.
|
||||||
|
- *displaymanager* no longer supports the discontinued *kdm* display manager.
|
||||||
|
- *fstab* configuration has been completely re-done. Many configuration
|
||||||
|
options have moved to the *mount* module. See #1993
|
||||||
|
- *grubcfg* changed the key *keepDistributor* to *keep_distributor*.
|
||||||
|
Please update configurations.
|
||||||
|
- *mount* now does most of the mounting; options that were in *fstab*
|
||||||
|
have moved here. See #1993
|
||||||
|
- *oemid* now uses consistent variable replacement (e.g. KMacroExpander)
|
||||||
|
and does not support `@@DATE@@` anymore (use `${DATE}`).
|
||||||
|
- *partition* requires KPMCore 21.12 (e.g. KPMCore 4.2 API, or later).
|
||||||
|
- *partition* can now skip installing the bootloader in more scenarios.
|
||||||
|
#1632 (Thanks Anubhav)
|
||||||
|
- *preservefiles* follows `${}` variable syntax instead of `@@`.
|
||||||
|
|
510
CMakeLists.txt
510
CMakeLists.txt
@ -19,56 +19,79 @@
|
|||||||
#
|
#
|
||||||
# SKIP_MODULES : a space or semicolon-separated list of directory names
|
# SKIP_MODULES : a space or semicolon-separated list of directory names
|
||||||
# under src/modules that should not be built.
|
# under src/modules that should not be built.
|
||||||
# USE_<foo> : fills in SKIP_MODULES for modules called <foo>-<something>
|
# USE_<foo> : fills in SKIP_MODULES for modules called <foo>-<something>.
|
||||||
# WITH_<foo> : try to enable <foo> (these usually default to ON). For
|
# WITH_<foo> : try to enable <foo> (these usually default to ON). For
|
||||||
# a list of WITH_<foo> grep CMakeCache.txt after running
|
# a list of WITH_<foo> grep CMakeCache.txt after running
|
||||||
# CMake once. These affect the ABI offered by Calamares.
|
# CMake once. These affect the ABI offered by Calamares.
|
||||||
# - PYTHON (enable Python Job modules)
|
# - PYBIND11 (use bundled pybind11, default ON, needs WITH_PYTHON)
|
||||||
# - QML (enable QML UI View modules)
|
# - PYTHON (enable Python Job modules, default ON if Python is found)
|
||||||
# - PYTHONQT # TODO:3.3: remove
|
# - QML (enable QML UI View modules, default ON)
|
||||||
|
# - QT6 (use Qt6 rather than Qt5, default to OFF)
|
||||||
|
# The WITH_* options affect the ABI of Calamares: you must
|
||||||
|
# build (C++) modules for Calamares with the same WITH_*
|
||||||
|
# settings, or they may not load at all.
|
||||||
# BUILD_<foo> : choose additional things to build
|
# BUILD_<foo> : choose additional things to build
|
||||||
# - TESTING (standard CMake option)
|
# - APPDATA (use AppData in packagechooser, requires QtXml)
|
||||||
|
# - APPSTREAM (use AppStream in packagechooser, requires libappstream-qt)
|
||||||
|
# - BUILD_CRASH_REPORTING (uses KCrash, rather than Calamares internal, for crash reporting)
|
||||||
# - SCHEMA_TESTING (requires Python, see ci/configvalidator.py)
|
# - SCHEMA_TESTING (requires Python, see ci/configvalidator.py)
|
||||||
# DEBUG_<foo> : special developer flags for debugging
|
# - TESTING (standard CMake option)
|
||||||
|
# DEBUG_<foo> : special developer flags for debugging.
|
||||||
|
# PYTHONLIBS_VERSION : if set on the command-line, use a specific Python version
|
||||||
#
|
#
|
||||||
# Example usage:
|
# Example usage:
|
||||||
#
|
#
|
||||||
# cmake . -DSKIP_MODULES="partition luksbootkeycfg"
|
# cmake . -DSKIP_MODULES="partition luksbootkeycfg"
|
||||||
#
|
#
|
||||||
# One special target is "show-version", which can be built
|
# To obtain the version number of calamares, run CMake in script mode, e.g.
|
||||||
# to obtain the version number from here.
|
# cmake -P CMakeLists.txt
|
||||||
|
|
||||||
# TODO:3.3: Require CMake 3.12
|
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
|
||||||
cmake_minimum_required( VERSION 3.3 FATAL_ERROR )
|
|
||||||
project( CALAMARES
|
|
||||||
VERSION 3.2.61
|
|
||||||
LANGUAGES C CXX
|
|
||||||
)
|
|
||||||
|
|
||||||
# Leave this as "Release mode", since 3.2 is in LTS / bugfix-only state,
|
set(CALAMARES_VERSION 3.3.12)
|
||||||
# and should always be releaseable.
|
set(CALAMARES_RELEASE_MODE ON) # Set to ON during a release
|
||||||
set( CALAMARES_VERSION_RC 0 ) # Set to 0 during release cycle, 1 during development
|
|
||||||
if( CALAMARES_VERSION_RC EQUAL 1 AND CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
|
if(CMAKE_SCRIPT_MODE_FILE)
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/CMakeModules/ExtendedVersion.cmake)
|
||||||
|
set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
extend_version( ${CALAMARES_VERSION} ${CALAMARES_RELEASE_MODE} _vshort _vlong )
|
||||||
|
message("${_vlong}")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Massage the version for CMake if there is a version-suffix
|
||||||
|
string(REGEX REPLACE "-.*" "" CALAMARES_VERSION_SHORT "${CALAMARES_VERSION}")
|
||||||
|
# And preserve the original version (suffix and all) because project() overwrites
|
||||||
|
# .. but if we're doing non-release builds, this gets replaced with git versioning.
|
||||||
|
set(CALAMARES_VERSION_LONG "${CALAMARES_VERSION}")
|
||||||
|
|
||||||
|
project(CALAMARES VERSION ${CALAMARES_VERSION_SHORT} LANGUAGES C CXX HOMEPAGE_URL "https://calamares.io/")
|
||||||
|
|
||||||
|
if(NOT CALAMARES_RELEASE_MODE AND CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
|
||||||
message(FATAL_ERROR "Do not build development versions in the source-directory.")
|
message(FATAL_ERROR "Do not build development versions in the source-directory.")
|
||||||
endif()
|
endif()
|
||||||
|
# Calamares in the 3.3 series promises ABI compatbility, so it sets a
|
||||||
|
# .so-version equal to the series number. We use ci/abicheck.sh to
|
||||||
|
# keep track of this. Note that the **alpha** releases also have
|
||||||
|
# such an .so-version, but are not ABI-stable yet.
|
||||||
|
set(CALAMARES_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||||
|
|
||||||
### OPTIONS
|
### OPTIONS
|
||||||
#
|
#
|
||||||
option( INSTALL_CONFIG "Install configuration files" OFF )
|
|
||||||
option(INSTALL_POLKIT "Install Polkit configuration" ON)
|
option(INSTALL_POLKIT "Install Polkit configuration" ON)
|
||||||
option(INSTALL_COMPLETION "Install shell completions" OFF)
|
option(INSTALL_COMPLETION "Install shell completions" OFF)
|
||||||
# Options for the calamares executable
|
option(INSTALL_CONFIG "Install configuration files" OFF)
|
||||||
option( WITH_KF5Crash "Enable crash reporting with KCrash." ON ) # TODO:3.3: WITH->BUILD (this isn't an ABI thing)
|
|
||||||
option( WITH_KF5DBus "Use DBus service for unique-application." OFF ) # TODO:3.3: WITH->BUILD
|
|
||||||
# When adding WITH_* that affects the ABI offered by libcalamares,
|
# When adding WITH_* that affects the ABI offered by libcalamares,
|
||||||
# also update libcalamares/CalamaresConfig.h.in
|
# also update libcalamares/CalamaresConfig.h.in
|
||||||
option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON )
|
option(WITH_PYBIND11 "Use bundled pybind11 instead of Boost::Python" ON)
|
||||||
option( WITH_PYTHONQT "Enable Python view modules API (deprecated, requires PythonQt)." OFF ) # TODO:3.3: remove
|
option(WITH_PYTHON "Enable Python modules API." ON)
|
||||||
option(WITH_QML "Enable QML UI options." ON)
|
option(WITH_QML "Enable QML UI options." ON)
|
||||||
|
option(WITH_QT6 "Use Qt6 instead of Qt5" OFF)
|
||||||
#
|
#
|
||||||
# Additional parts to build
|
# Additional parts to build that do not affect ABI
|
||||||
option(BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON)
|
option(BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON)
|
||||||
|
# Options for the calamares executable
|
||||||
|
option(BUILD_CRASH_REPORTING "Enable crash reporting with KCrash." ON)
|
||||||
|
|
||||||
# Possible debugging flags are:
|
# Possible debugging flags are:
|
||||||
# - DEBUG_TIMEZONES draws latitude and longitude lines on the timezone
|
# - DEBUG_TIMEZONES draws latitude and longitude lines on the timezone
|
||||||
@ -79,6 +102,13 @@ option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON )
|
|||||||
# - DEBUG_PARTITION_UNSAFE (see partition/CMakeLists.txt)
|
# - DEBUG_PARTITION_UNSAFE (see partition/CMakeLists.txt)
|
||||||
# - DEBUG_PARTITION_BAIL_OUT (see partition/CMakeLists.txt)
|
# - DEBUG_PARTITION_BAIL_OUT (see partition/CMakeLists.txt)
|
||||||
|
|
||||||
|
# Special handling for Python versions:
|
||||||
|
# - If you set PYTHONLIBS_VERSION on the command-line, then
|
||||||
|
# that **exact** version will be searched for, and no other.
|
||||||
|
# - If you do not set PYTHONLIBS_VERSION on the command-line,
|
||||||
|
# any suitable version will be found -- but this can fail if
|
||||||
|
# you have multiple Python versions installed, only some of
|
||||||
|
# which include the development headers.
|
||||||
|
|
||||||
### USE_*
|
### USE_*
|
||||||
#
|
#
|
||||||
@ -110,8 +140,7 @@ set( USE_services "" CACHE STRING "Select the services module to use" )
|
|||||||
set(CALAMARES_ORGANIZATION_NAME "Calamares")
|
set(CALAMARES_ORGANIZATION_NAME "Calamares")
|
||||||
set(CALAMARES_ORGANIZATION_DOMAIN "github.com/calamares")
|
set(CALAMARES_ORGANIZATION_DOMAIN "github.com/calamares")
|
||||||
set(CALAMARES_APPLICATION_NAME "Calamares")
|
set(CALAMARES_APPLICATION_NAME "Calamares")
|
||||||
set( CALAMARES_DESCRIPTION_SUMMARY
|
set(CALAMARES_DESCRIPTION_SUMMARY "The distribution-independent installer framework")
|
||||||
"The distribution-independent installer framework" )
|
|
||||||
|
|
||||||
### Transifex (languages) info
|
### Transifex (languages) info
|
||||||
#
|
#
|
||||||
@ -122,7 +151,7 @@ set( CALAMARES_DESCRIPTION_SUMMARY
|
|||||||
#
|
#
|
||||||
# Language en (source language) is added later. It isn't listed in
|
# Language en (source language) is added later. It isn't listed in
|
||||||
# Transifex either. Get the list of languages and their status
|
# Transifex either. Get the list of languages and their status
|
||||||
# from https://transifex.com/calamares/calamares/ , or (preferably)
|
# from https://app.transifex.com/calamares/calamares/ , or (preferably)
|
||||||
# use ci/txstats.py to automatically check.
|
# use ci/txstats.py to automatically check.
|
||||||
#
|
#
|
||||||
# When adding a new language, take care that it is properly loaded
|
# When adding a new language, take care that it is properly loaded
|
||||||
@ -130,51 +159,88 @@ set( CALAMARES_DESCRIPTION_SUMMARY
|
|||||||
# (sr@latin in particular) or location (ca@valencia) need special
|
# (sr@latin in particular) or location (ca@valencia) need special
|
||||||
# handling in libcalamares/locale/Translation.h .
|
# handling in libcalamares/locale/Translation.h .
|
||||||
#
|
#
|
||||||
# NOTE: move eo (Esperanto) to _ok once Qt can actually create a
|
|
||||||
# locale for it. (Qt 5.12.2 can, see Translation Status section).
|
|
||||||
# NOTE: move ie (Interlingue) to _ok once Qt supports it.
|
# NOTE: move ie (Interlingue) to _ok once Qt supports it.
|
||||||
# NOTE: update these lines by running `txstats.py`, or for full automation
|
# NOTE: update these lines by running `txstats.py`, or for full automation
|
||||||
# `txstats.py -e`. See also
|
# `txstats.py -e`. See also
|
||||||
#
|
#
|
||||||
# Total 75 languages
|
# Total 80 languages
|
||||||
set( _tx_complete az az_AZ ca fi_FI fr he hr ja ko lt pt_BR pt_PT
|
set( _tx_complete de en es_AR fi_FI hr hu ja lt tr_TR uk zh_TW )
|
||||||
sv tr_TR uk zh_TW )
|
set( _tx_good az az_AZ be bg ca cs_CZ es fr fur he hi is it_IT ko
|
||||||
set( _tx_good as be ca@valencia cs_CZ da de es fa fur hi it_IT ml
|
pl pt_BR pt_PT ru si sq sv zh_CN )
|
||||||
nl ru si sk sq tg vi zh_CN )
|
set( _tx_ok ar as ast bn ca@valencia da el en_GB eo es_MX et eu fa
|
||||||
set( _tx_ok ar ast bg bn el en_GB es_MX et eu gl hu id is mr nb oc
|
gl id ka ml mr nb nl oc ro sk sl sr sr@latin tg th vi )
|
||||||
pl ro sl sr sr@latin th )
|
set( _tx_incomplete bqi es_PR gu ie ja-Hira kk kn lo lv mk ne_NP
|
||||||
set( _tx_incomplete eo es_PR gu ie ja-Hira kk kn lo lv mk ne_NP
|
ro_RO ta_IN te ur uz zh zh_HK )
|
||||||
ta_IN te ur uz zh zh_HK )
|
# Total 80 languages
|
||||||
|
|
||||||
### Required versions
|
### Required versions
|
||||||
#
|
#
|
||||||
# See DEPENDENCIES section below.
|
# See DEPENDENCIES section below.
|
||||||
set( QT_VERSION 5.9.0 )
|
|
||||||
set( YAMLCPP_VERSION 0.5.1 )
|
|
||||||
set( ECM_VERSION 5.18 )
|
|
||||||
set( PYTHONLIBS_VERSION 3.3 )
|
|
||||||
set( BOOSTPYTHON_VERSION 1.55.0 )
|
|
||||||
|
|
||||||
|
# The default build is with Qt5, but that is increasingly not the
|
||||||
|
# version installed-by-default on Linux systems. Upgrade the default
|
||||||
|
# if Qt5 isn't available but Qt6 is. This also saves messing around
|
||||||
|
# with special CMake flags for every script (e.g. ci/RELEASE.sh and
|
||||||
|
# ci/abicheck.sh).
|
||||||
|
if(NOT WITH_QT6)
|
||||||
|
find_package(Qt5Core QUIET)
|
||||||
|
if(NOT TARGET Qt5::Core)
|
||||||
|
find_package(Qt6Core QUIET)
|
||||||
|
if(TARGET Qt6::Core)
|
||||||
|
message(STATUS "Default Qt version (Qt5) not found, upgrading build to Qt6")
|
||||||
|
set(WITH_QT6 ON)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(WITH_QT6)
|
||||||
|
message(STATUS "Building Calamares with Qt6")
|
||||||
|
set(qtname "Qt6")
|
||||||
|
set(kfname "KF6")
|
||||||
|
set(QT_VERSION 6.5.0)
|
||||||
|
set(ECM_VERSION 5.240)
|
||||||
|
set(KF_VERSION 5.240) # KDE Neon weirdness
|
||||||
|
# API that was deprecated before Qt 5.15 causes a compile error
|
||||||
|
add_compile_definitions(QT_DISABLE_DEPRECATED_BEFORE=0x060400)
|
||||||
|
# Something to add to filenames for this specific Qt version
|
||||||
|
set(QT_VERSION_SUFFIX "-qt6")
|
||||||
|
else()
|
||||||
|
message(STATUS "Building Calamares with Qt5")
|
||||||
|
set(qtname "Qt5")
|
||||||
|
set(kfname "KF5")
|
||||||
|
set(QT_VERSION 5.15.0)
|
||||||
|
set(ECM_VERSION 5.78)
|
||||||
|
set(KF_VERSION 5.78)
|
||||||
|
# API that was deprecated before Qt 5.15 causes a compile error
|
||||||
|
add_compile_definitions(QT_DISABLE_DEPRECATED_BEFORE=0x050f00)
|
||||||
|
# Something to add to filenames for this specific Qt version
|
||||||
|
set(QT_VERSION_SUFFIX "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(BOOSTPYTHON_VERSION 1.72.0)
|
||||||
|
if(DEFINED PYTHONLIBS_VERSION)
|
||||||
|
set(PYTHONLIBS_EXTRA "EXACT")
|
||||||
|
else()
|
||||||
|
set(PYTHONLIBS_VERSION 3.6)
|
||||||
|
set(PYTHONLIBS_EXTRA "")
|
||||||
|
endif()
|
||||||
|
set(YAMLCPP_VERSION 0.5.1)
|
||||||
|
|
||||||
### CMAKE SETUP
|
### CMAKE SETUP
|
||||||
#
|
#
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules")
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules")
|
||||||
|
|
||||||
# Enable IN_LIST
|
# Enable IN_LIST
|
||||||
if( POLICY CMP0057 )
|
|
||||||
cmake_policy(SET CMP0057 NEW)
|
cmake_policy(SET CMP0057 NEW)
|
||||||
endif()
|
|
||||||
# Let ``AUTOMOC`` and ``AUTOUIC`` process ``GENERATED`` files.
|
# Let ``AUTOMOC`` and ``AUTOUIC`` process ``GENERATED`` files.
|
||||||
if( POLICY CMP0071 )
|
|
||||||
cmake_policy(SET CMP0071 NEW)
|
cmake_policy(SET CMP0071 NEW)
|
||||||
endif()
|
|
||||||
# Recognize more macros to trigger automoc
|
# Recognize more macros to trigger automoc
|
||||||
if(NOT CMAKE_VERSION VERSION_LESS "3.10.0")
|
|
||||||
list(APPEND CMAKE_AUTOMOC_MACRO_NAMES
|
list(APPEND CMAKE_AUTOMOC_MACRO_NAMES
|
||||||
"K_PLUGIN_FACTORY_WITH_JSON"
|
"K_PLUGIN_FACTORY_WITH_JSON"
|
||||||
"K_EXPORT_PLASMA_DATAENGINE_WITH_JSON"
|
"K_EXPORT_PLASMA_DATAENGINE_WITH_JSON"
|
||||||
"K_EXPORT_PLASMA_RUNNER"
|
"K_EXPORT_PLASMA_RUNNER"
|
||||||
)
|
)
|
||||||
|
if(POLICY CMP0171)
|
||||||
|
cmake_policy(SET CMP0177 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# CMake Modules
|
# CMake Modules
|
||||||
@ -200,10 +266,19 @@ set( CMAKE_C_STANDARD_REQUIRED ON )
|
|||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||||
set(CMAKE_C_FLAGS_DEBUG "-Og -g")
|
set(CMAKE_C_FLAGS_DEBUG "-Og -g")
|
||||||
set(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")
|
set(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")
|
||||||
set( CMAKE_C_FLAGS_RELEASE "-O4 -DNDEBUG" )
|
set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
|
||||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")
|
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")
|
||||||
|
|
||||||
set( CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined -Wl,--fatal-warnings" )
|
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined -Wl,--fatal-warnings ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
|
|
||||||
|
# If no build type is set, pick a reasonable one
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
if(CALAMARES_RELEASE_MODE)
|
||||||
|
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
|
||||||
|
else()
|
||||||
|
set(CMAKE_BUILD_TYPE "Debug")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
message(STATUS "Found Clang ${CMAKE_CXX_COMPILER_VERSION}, setting up Clang-specific compiler flags.")
|
message(STATUS "Found Clang ${CMAKE_CXX_COMPILER_VERSION}, setting up Clang-specific compiler flags.")
|
||||||
@ -211,7 +286,8 @@ if( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
|||||||
# Clang warnings: doing *everything* is counter-productive, since it warns
|
# Clang warnings: doing *everything* is counter-productive, since it warns
|
||||||
# about things which we can't fix (e.g. C++98 incompatibilities, but
|
# about things which we can't fix (e.g. C++98 incompatibilities, but
|
||||||
# Calamares is C++17).
|
# Calamares is C++17).
|
||||||
foreach( CLANG_WARNINGS
|
foreach(
|
||||||
|
CLANG_WARNINGS
|
||||||
-Weverything
|
-Weverything
|
||||||
-Wno-c++98-compat
|
-Wno-c++98-compat
|
||||||
-Wno-c++98-compat-pedantic
|
-Wno-c++98-compat-pedantic
|
||||||
@ -251,176 +327,195 @@ endif()
|
|||||||
# Use mark_thirdparty_code() to reduce warnings from the compiler
|
# Use mark_thirdparty_code() to reduce warnings from the compiler
|
||||||
# on code that we're not going to fix. Call this with a list of files.
|
# on code that we're not going to fix. Call this with a list of files.
|
||||||
macro(mark_thirdparty_code)
|
macro(mark_thirdparty_code)
|
||||||
set_source_files_properties( ${ARGV}
|
set_source_files_properties(
|
||||||
PROPERTIES
|
${ARGV}
|
||||||
COMPILE_FLAGS "${SUPPRESS_3RDPARTY_WARNINGS}"
|
PROPERTIES COMPILE_FLAGS "${SUPPRESS_3RDPARTY_WARNINGS}" COMPILE_DEFINITIONS "THIRDPARTY"
|
||||||
COMPILE_DEFINITIONS "THIRDPARTY"
|
|
||||||
)
|
)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
if( CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9 OR
|
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.9)
|
||||||
CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.9 )
|
|
||||||
message(STATUS "Found GNU g++ ${CMAKE_CXX_COMPILER_VERSION}, enabling colorized error messages.")
|
message(STATUS "Found GNU g++ ${CMAKE_CXX_COMPILER_VERSION}, enabling colorized error messages.")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=auto")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=auto")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
### DEPENDENCIES
|
### DEPENDENCIES
|
||||||
#
|
#
|
||||||
find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Concurrent Core Gui LinguistTools Network Svg Widgets )
|
find_package(${qtname} ${QT_VERSION} CONFIG REQUIRED Concurrent Core DBus Gui LinguistTools Network Svg Widgets)
|
||||||
if(WITH_QML)
|
if(WITH_QML)
|
||||||
find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Quick QuickWidgets )
|
find_package(${qtname} ${QT_VERSION} CONFIG REQUIRED Quick QuickWidgets)
|
||||||
endif()
|
endif()
|
||||||
# Optional Qt parts
|
# Note that some modules need more Qt modules, optionally.
|
||||||
find_package( Qt5DBus CONFIG )
|
|
||||||
|
|
||||||
find_package( YAMLCPP ${YAMLCPP_VERSION} REQUIRED )
|
find_package(YAMLCPP ${YAMLCPP_VERSION})
|
||||||
|
set_package_properties(
|
||||||
|
YAMLCPP
|
||||||
|
PROPERTIES
|
||||||
|
TYPE REQUIRED
|
||||||
|
DESCRIPTION "YAML parser for C++"
|
||||||
|
PURPOSE "Parsing of configuration files"
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(Polkit${qtname}-1)
|
||||||
if(INSTALL_POLKIT)
|
if(INSTALL_POLKIT)
|
||||||
find_package( PolkitQt5-1 REQUIRED )
|
set_package_properties(
|
||||||
else()
|
Polkit${qtname}-1
|
||||||
# Find it anyway, for dependencies-reporting
|
PROPERTIES
|
||||||
find_package( PolkitQt5-1 )
|
TYPE REQUIRED
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
set_package_properties(
|
set_package_properties(
|
||||||
PolkitQt5-1 PROPERTIES
|
Polkit${qtname}-1
|
||||||
DESCRIPTION "Qt5 support for Polkit"
|
PROPERTIES
|
||||||
|
DESCRIPTION "${qtname} support for Polkit"
|
||||||
URL "https://cgit.kde.org/polkit-qt-1.git"
|
URL "https://cgit.kde.org/polkit-qt-1.git"
|
||||||
PURPOSE "PolkitQt5-1 helps with installing Polkit configuration"
|
PURPOSE "Polkit${qtname}-1 helps with installing Polkit configuration"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Find ECM once, and add it to the module search path; Calamares
|
# Find ECM once, and add it to the module search path; Calamares
|
||||||
# modules that need ECM can do
|
# modules that need ECM can do
|
||||||
# find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE),
|
# if(ECM_FOUND)
|
||||||
# no need to mess with the module path after.
|
# no need to mess with the module path after.
|
||||||
find_package(ECM ${ECM_VERSION} NO_MODULE)
|
find_package(ECM ${ECM_VERSION} NO_MODULE)
|
||||||
if(ECM_FOUND)
|
if(ECM_FOUND)
|
||||||
|
message(STATUS "Found KDE ECM ${ECM_MODULE_PATH}")
|
||||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH})
|
||||||
if(BUILD_TESTING)
|
if(BUILD_TESTING)
|
||||||
# ECM implies that we can build the tests, too
|
# ECM implies that we can build the tests, too
|
||||||
find_package( Qt5 COMPONENTS Test REQUIRED )
|
find_package(${qtname} COMPONENTS Test REQUIRED)
|
||||||
include(ECMAddTests)
|
include(ECMAddTests)
|
||||||
endif()
|
endif()
|
||||||
include(KDEInstallDirs)
|
include(KDEInstallDirs)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package( KF5 QUIET COMPONENTS CoreAddons Crash DBusAddons )
|
find_package(${kfname}CoreAddons ${KF_VERSION} QUIET)
|
||||||
set_package_properties(
|
set_package_properties(
|
||||||
KF5::CoreAddons PROPERTIES
|
${kfname}CoreAddons
|
||||||
|
PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
DESCRIPTION "Classes built on QtCore for About Data"
|
DESCRIPTION "KDE Framework CoreAddons"
|
||||||
URL "https://api.kde.org/frameworks/kcoreaddons/"
|
URL "https://api.kde.org/frameworks/"
|
||||||
PURPOSE "About Calamares"
|
PURPOSE "Essential Framework for AboutData and Macros"
|
||||||
)
|
)
|
||||||
if( NOT KF5Crash_FOUND )
|
|
||||||
if( WITH_KF5Crash )
|
# After this point, there should be no REQUIRED find_packages,
|
||||||
message(WARNING "WITH_KF5Crash is set, but KF5::Crash is not available.")
|
# since we want tidy reporting of optional dependencies.
|
||||||
|
feature_summary(
|
||||||
|
WHAT REQUIRED_PACKAGES_NOT_FOUND
|
||||||
|
FATAL_ON_MISSING_REQUIRED_PACKAGES
|
||||||
|
DESCRIPTION "The following REQUIRED packages were not found:"
|
||||||
|
QUIET_ON_EMPTY
|
||||||
|
)
|
||||||
|
|
||||||
|
#
|
||||||
|
# OPTIONAL DEPENDENCIES
|
||||||
|
#
|
||||||
|
# First, set KF back to optional so that any missing components don't trip us up.
|
||||||
|
find_package(${kfname}Crash ${KF_VERSION} QUIET)
|
||||||
|
set_package_properties(
|
||||||
|
${kfname}Crash
|
||||||
|
PROPERTIES
|
||||||
|
TYPE OPTIONAL
|
||||||
|
DESCRIPTION "KDE Framework Crash"
|
||||||
|
URL "https://api.kde.org/frameworks/"
|
||||||
|
PURPOSE "Framework for sending Crash Dumps"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT TARGET ${kfname}::Crash)
|
||||||
|
if(BUILD_CRASH_REPORTING)
|
||||||
|
message(WARNING "BUILD_CRASH_REPORTING is set, but ${kfname}::Crash is not available.")
|
||||||
endif()
|
endif()
|
||||||
set( WITH_KF5Crash OFF )
|
set(BUILD_CRASH_REPORTING OFF)
|
||||||
endif()
|
|
||||||
if( NOT KF5DBusAddons_FOUND )
|
|
||||||
if( WITH_KF5DBus )
|
|
||||||
message(WARNING "WITH_KF5DBus is set, but KF5::DBusAddons is not available.")
|
|
||||||
endif()
|
|
||||||
set( WITH_KF5DBus OFF )
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# TODO:3.3: Use FindPython3 instead
|
find_package(Python ${PYTHONLIBS_VERSION} ${PYTHONLIBS_EXTRA} COMPONENTS Interpreter Development)
|
||||||
find_package( PythonInterp ${PYTHONLIBS_VERSION} )
|
|
||||||
set_package_properties(
|
set_package_properties(
|
||||||
PythonInterp PROPERTIES
|
Python
|
||||||
|
PROPERTIES
|
||||||
DESCRIPTION "Python3 interpreter."
|
DESCRIPTION "Python3 interpreter."
|
||||||
URL "https://python.org"
|
URL "https://python.org"
|
||||||
PURPOSE "Python3 interpreter for certain tests."
|
PURPOSE "Python3 interpreter for certain tests."
|
||||||
)
|
)
|
||||||
|
|
||||||
set(_schema_explanation "")
|
set(_schema_explanation "")
|
||||||
if ( PYTHONINTERP_FOUND )
|
if(Python_Interpreter_FOUND)
|
||||||
if(BUILD_SCHEMA_TESTING)
|
if(BUILD_SCHEMA_TESTING)
|
||||||
# The configuration validator script has some dependencies,
|
# The configuration validator script has some dependencies,
|
||||||
# and if they are not installed, don't run. If errors out
|
# and if they are not installed, don't run. If errors out
|
||||||
# with exit(1) on missing dependencies.
|
# with exit(1) on missing dependencies.
|
||||||
if(CALAMARES_CONFIGVALIDATOR_CHECKED)
|
if(CALAMARES_CONFIGVALIDATOR_CHECKED)
|
||||||
|
message(STATUS "Using cached config-validation result")
|
||||||
set(_validator_deps ${CALAMARES_CONFIGVALIDATOR_RESULT})
|
set(_validator_deps ${CALAMARES_CONFIGVALIDATOR_RESULT})
|
||||||
else()
|
else()
|
||||||
exec_program( ${PYTHON_EXECUTABLE} ARGS "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" -x RETURN_VALUE _validator_deps )
|
execute_process(
|
||||||
|
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" -x
|
||||||
|
RESULT_VARIABLE _validator_deps
|
||||||
|
)
|
||||||
set(CALAMARES_CONFIGVALIDATOR_CHECKED TRUE CACHE INTERNAL "Dependencies for configvalidator checked")
|
set(CALAMARES_CONFIGVALIDATOR_CHECKED TRUE CACHE INTERNAL "Dependencies for configvalidator checked")
|
||||||
set( CALAMARES_CONFIGVALIDATOR_RESULT ${_validator_deps} CACHE INTERNAL "Result of configvalidator dependency check" )
|
set(CALAMARES_CONFIGVALIDATOR_RESULT ${_validator_deps}
|
||||||
|
CACHE INTERNAL "Result of configvalidator dependency check"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
# It should never succeed, but only returns 1 when the imports fail
|
# It should never succeed, but only returns 1 when the imports fail
|
||||||
if(_validator_deps EQUAL 1)
|
if(_validator_deps EQUAL 1)
|
||||||
|
message(STATUS "Checked for config-validation dependencies: NOT-FOUND")
|
||||||
set(_schema_explanation " Missing dependencies for configvalidator.py.")
|
set(_schema_explanation " Missing dependencies for configvalidator.py.")
|
||||||
set(BUILD_SCHEMA_TESTING OFF)
|
set(BUILD_SCHEMA_TESTING OFF)
|
||||||
|
else()
|
||||||
|
message(STATUS "Checked for config-validation dependencies: found")
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
set(CALAMARES_CONFIGVALIDATOR_CHECKED OFF CACHE INTERNAL "Dependencies for configvalidator checked")
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
# Can't run schema tests without Python3.
|
# Can't run schema tests without Python3.
|
||||||
set(_schema_explanation " Missing Python3.")
|
set(_schema_explanation " Missing Python3.")
|
||||||
set(BUILD_SCHEMA_TESTING OFF)
|
set(BUILD_SCHEMA_TESTING OFF)
|
||||||
|
set(CALAMARES_CONFIGVALIDATOR_CHECKED OFF CACHE INTERNAL "Dependencies for configvalidator checked")
|
||||||
endif()
|
endif()
|
||||||
add_feature_info(yaml-schema BUILD_SCHEMA_TESTING "Validate YAML (config files) with schema.${_schema_explanation}")
|
add_feature_info(yaml-schema BUILD_SCHEMA_TESTING "Validate YAML (config files) with schema.${_schema_explanation}")
|
||||||
|
|
||||||
find_package( PythonLibs ${PYTHONLIBS_VERSION} )
|
if(NOT Python_Development_FOUND)
|
||||||
set_package_properties(
|
message(STATUS "Disabling Python modules")
|
||||||
PythonLibs PROPERTIES
|
|
||||||
DESCRIPTION "C interface libraries for the Python 3 interpreter."
|
|
||||||
URL "https://python.org"
|
|
||||||
PURPOSE "Python 3 is used for Python job modules."
|
|
||||||
)
|
|
||||||
|
|
||||||
if ( PYTHONLIBS_FOUND )
|
|
||||||
# TODO:3.3: Require Boost + CMake; sort out Boost::Python
|
|
||||||
# Since Boost provides CMake config files (starting with Boost 1.70.
|
|
||||||
# or so) the mess that is the Calamares find code picks the wrong
|
|
||||||
# bits. Suppress those CMake config files, as suggested by @jmrcpn
|
|
||||||
set(Boost_NO_BOOST_CMAKE ON)
|
|
||||||
include( BoostPython3 )
|
|
||||||
find_boost_python3( ${BOOSTPYTHON_VERSION} ${PYTHONLIBS_VERSION_STRING} CALAMARES_BOOST_PYTHON3_FOUND )
|
|
||||||
set_package_properties(
|
|
||||||
Boost PROPERTIES
|
|
||||||
PURPOSE "Boost.Python is used for Python job modules."
|
|
||||||
)
|
|
||||||
# TODO:3.3: Remove PythonQt support
|
|
||||||
find_package( PythonQt )
|
|
||||||
set_package_properties( PythonQt PROPERTIES
|
|
||||||
DESCRIPTION "A Python embedding solution for Qt applications."
|
|
||||||
URL "http://pythonqt.sourceforge.net"
|
|
||||||
PURPOSE "PythonQt is used for Python view modules."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if( NOT PYTHONLIBS_FOUND OR NOT CALAMARES_BOOST_PYTHON3_FOUND )
|
|
||||||
message(STATUS "Disabling Boost::Python modules")
|
|
||||||
set(WITH_PYTHON OFF)
|
set(WITH_PYTHON OFF)
|
||||||
|
set(WITH_PYBIND11 OFF)
|
||||||
|
set(WITH_BOOST_PYTHON OFF)
|
||||||
endif()
|
endif()
|
||||||
if( NOT PYTHONLIBS_FOUND OR NOT PYTHONQT_FOUND )
|
|
||||||
message(STATUS "Disabling PythonQt modules")
|
if(WITH_PYTHON AND NOT WITH_PYBIND11)
|
||||||
set( WITH_PYTHONQT OFF )
|
set(WITH_BOOST_PYTHON ON)
|
||||||
|
find_package(boost_python)
|
||||||
|
if(NOT TARGET Boost::python)
|
||||||
|
find_package(Boost ${BOOSTPYTHON_VERSION} COMPONENTS python)
|
||||||
|
set_package_properties(Boost PROPERTIES
|
||||||
|
PURPOSE "Boost.Python is used for Python job modules (because WITH_PYBIND11 is OFF)."
|
||||||
|
TYPE REQUIRED
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(STATUS "Found boost_python with target Boost::python")
|
||||||
|
set(Boost_FOUND ON)
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
add_feature_info(python WITH_PYTHON "Enable Python-modules")
|
||||||
|
add_feature_info(python-pybind11 WITH_PYBIND11 "Python-modules through pybind11")
|
||||||
|
add_feature_info(python-boost WITH_BOOST_PYTHON "Python-modules through Boost::Python")
|
||||||
|
|
||||||
# Now we know the state of the ABI-options, copy them into "Calamares_"
|
# Now we know the state of the ABI-options, copy them into "Calamares_"
|
||||||
# prefixed variables, to match how the variables would-be-named
|
# prefixed variables, to match how the variables would-be-named
|
||||||
# when building out-of-tree.
|
# when building out-of-tree.
|
||||||
set(Calamares_WITH_PYTHON ${WITH_PYTHON})
|
set(Calamares_WITH_PYTHON ${WITH_PYTHON})
|
||||||
set(Calamares_WITH_PYTHONQT ${WITH_PYTHONQT})
|
set(Calamares_WITH_PYBIND11 ${WITH_PYBIND11})
|
||||||
|
set(Calamares_WITH_BOOST_PYTHON ${WITH_BOOST_PYTHON})
|
||||||
set(Calamares_WITH_QML ${WITH_QML})
|
set(Calamares_WITH_QML ${WITH_QML})
|
||||||
|
set(Calamares_WITH_QT6 ${WITH_QT6})
|
||||||
|
|
||||||
### Transifex Translation status
|
### Transifex Translation status
|
||||||
#
|
#
|
||||||
# Construct language lists for use. This massages the language lists
|
# Construct language lists for use. This massages the language lists if
|
||||||
# for use with older Qt (which does not support Esperanto) and checks
|
# needed and checks for some obvious errors. The actual work of
|
||||||
# for some obvious error. The actual work of compiling translations
|
# compiling translations is done in the lang/ directory.
|
||||||
# is done in the lang/ directory.
|
|
||||||
#
|
#
|
||||||
if( Qt5_VERSION VERSION_GREATER 5.12.1 )
|
|
||||||
# At least Qt 5.12.2 seems to support Esperanto in QLocale
|
|
||||||
if( "eo" IN_LIST _tx_incomplete )
|
|
||||||
message(STATUS "Esperanto support since Qt 5.12.2, enabling Esperanto locale")
|
|
||||||
list( REMOVE_ITEM _tx_incomplete "eo" )
|
|
||||||
list( APPEND _tx_ok "eo" )
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(curr_tx ${_tx_complete} ${_tx_good} ${_tx_ok} ${_tx_incomplete})
|
set(curr_tx ${_tx_complete} ${_tx_good} ${_tx_ok} ${_tx_incomplete})
|
||||||
set(tx_errors OFF)
|
set(tx_errors OFF)
|
||||||
@ -443,7 +538,12 @@ if( tx_errors )
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CALAMARES_TRANSLATION_LANGUAGES en ${_tx_complete} ${_tx_good} ${_tx_ok})
|
set(CALAMARES_TRANSLATION_LANGUAGES en ${_tx_complete} ${_tx_good} ${_tx_ok})
|
||||||
|
if(NOT CALAMARES_RELEASE_MODE)
|
||||||
|
# Outside of release mode, enable all the languages
|
||||||
|
list(APPEND CALAMARES_TRANSLATION_LANGUAGES ${_tx_incomplete})
|
||||||
|
endif()
|
||||||
list(SORT CALAMARES_TRANSLATION_LANGUAGES)
|
list(SORT CALAMARES_TRANSLATION_LANGUAGES)
|
||||||
|
list(REMOVE_DUPLICATES CALAMARES_TRANSLATION_LANGUAGES)
|
||||||
|
|
||||||
add_subdirectory(lang) # i18n tools
|
add_subdirectory(lang) # i18n tools
|
||||||
|
|
||||||
@ -498,41 +598,27 @@ endif()
|
|||||||
# "http://tldp.org/HOWTO/SquashFS-HOWTO/creatingandusing.html"
|
# "http://tldp.org/HOWTO/SquashFS-HOWTO/creatingandusing.html"
|
||||||
add_feature_info(ExampleDistro ${mksquashfs_FOUND} "Create example-distro target.")
|
add_feature_info(ExampleDistro ${mksquashfs_FOUND} "Create example-distro target.")
|
||||||
|
|
||||||
|
|
||||||
### CALAMARES PROPER
|
### CALAMARES PROPER
|
||||||
#
|
#
|
||||||
set( CALAMARES_VERSION ${CALAMARES_VERSION_MAJOR}.${CALAMARES_VERSION_MINOR}.${CALAMARES_VERSION_PATCH} )
|
|
||||||
# In rare cases we have hotfix-releases with a tweak
|
|
||||||
if( CALAMARES_VERSION_TWEAK )
|
|
||||||
set( CALAMARES_VERSION "${CALAMARES_VERSION}.${CALAMARES_VERSION_TWEAK}" )
|
|
||||||
endif()
|
|
||||||
set( CALAMARES_VERSION_SHORT "${CALAMARES_VERSION}" )
|
|
||||||
|
|
||||||
# Additional info for non-release builds. The "extended" version information
|
# Additional info for non-release builds. The "extended" version information
|
||||||
# with date and git information (commit, dirty status) is used only
|
# with date and git information (commit, dirty status) is used only
|
||||||
# by CalamaresVersionX.h, which is included by consumers that need a full
|
# by CalamaresVersionX.h, which is included by consumers that need a full
|
||||||
# version number with all that information; normal consumers can include
|
# version number with all that information; normal consumers can include
|
||||||
# CalamaresVersion.h with more stable numbers.
|
# CalamaresVersion.h with more stable numbers.
|
||||||
if( NOT BUILD_RELEASE AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git/" )
|
if(NOT CALAMARES_RELEASE_MODE AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git/")
|
||||||
include(ExtendedVersion)
|
include(ExtendedVersion)
|
||||||
extend_version( "${CALAMARES_VERSION}" OFF CALAMARES_VERSION_SHORT CALAMARES_VERSION )
|
extend_version( "${CALAMARES_VERSION}" OFF CALAMARES_VERSION_SHORT CALAMARES_VERSION_LONG )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Special target for not-RC (e.g. might-be-release) builds.
|
# Special define for RC (e.g. not-a-release) builds.
|
||||||
# This is used by the release script to get the version.
|
# This is consumed via the CalamaresConfig.h header.
|
||||||
if ( CALAMARES_VERSION_RC EQUAL 0 )
|
if(NOT CALAMARES_RELEASE_MODE)
|
||||||
add_custom_target(show-version
|
set(CALAMARES_VERSION_RC 1)
|
||||||
${CMAKE_COMMAND} -E echo CALAMARES_VERSION=${CALAMARES_VERSION_SHORT}
|
|
||||||
USES_TERMINAL
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# enforce using constBegin, constEnd for const-iterators
|
# enforce using constBegin, constEnd for const-iterators
|
||||||
add_definitions(
|
add_definitions(-DQT_STRICT_ITERATORS -DQT_SHARED -DQT_SHAREDPOINTER_TRACK_POINTERS)
|
||||||
-DQT_STRICT_ITERATORS
|
|
||||||
-DQT_SHARED
|
|
||||||
-DQT_SHAREDPOINTER_TRACK_POINTERS
|
|
||||||
)
|
|
||||||
|
|
||||||
# set paths
|
# set paths
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||||
@ -554,13 +640,22 @@ include( GNUInstallDirs )
|
|||||||
# libraries for Calamares.
|
# libraries for Calamares.
|
||||||
set(Calamares_LIBRARIES calamares)
|
set(Calamares_LIBRARIES calamares)
|
||||||
|
|
||||||
|
add_subdirectory(3rdparty/kdsingleapplication)
|
||||||
|
if(WITH_PYBIND11)
|
||||||
|
add_subdirectory(3rdparty/pybind11)
|
||||||
|
endif()
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
add_feature_info(Python ${WITH_PYTHON} "Python job modules")
|
add_feature_info(Python ${WITH_PYTHON} "Python job modules")
|
||||||
add_feature_info(PythonQt ${WITH_PYTHONQT} "Python view modules")
|
add_feature_info(Pybind11 ${WITH_PYBIND11} "Python using bundled pybind11")
|
||||||
add_feature_info(Config ${INSTALL_CONFIG} "Install Calamares configuration")
|
add_feature_info(Qml ${WITH_QML} "QML UI support")
|
||||||
add_feature_info(KCrash ${WITH_KF5Crash} "Crash dumps via KCrash")
|
add_feature_info(Polkit ${INSTALL_POLKIT} "Install Polkit files")
|
||||||
add_feature_info(KDBusAddons ${WITH_KF5DBus} "Unique-application via DBus")
|
add_feature_info(KCrash ${BUILD_CRASH_REPORTING} "Crash dumps via KCrash")
|
||||||
|
|
||||||
|
### Post-source configuration
|
||||||
|
#
|
||||||
|
#
|
||||||
|
find_package(${kfname} ${KF_VERSION} QUIET COMPONENTS CoreAddons)
|
||||||
|
|
||||||
### CMake infrastructure installation
|
### CMake infrastructure installation
|
||||||
#
|
#
|
||||||
@ -573,22 +668,14 @@ configure_package_config_file(
|
|||||||
"CalamaresConfig.cmake.in"
|
"CalamaresConfig.cmake.in"
|
||||||
"${PROJECT_BINARY_DIR}/CalamaresConfig.cmake"
|
"${PROJECT_BINARY_DIR}/CalamaresConfig.cmake"
|
||||||
INSTALL_DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
|
INSTALL_DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
|
||||||
PATH_VARS
|
PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_DATADIR
|
||||||
CMAKE_INSTALL_INCLUDEDIR
|
|
||||||
CMAKE_INSTALL_LIBDIR
|
|
||||||
CMAKE_INSTALL_DATADIR
|
|
||||||
)
|
)
|
||||||
write_basic_package_version_file(
|
write_basic_package_version_file(
|
||||||
${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake
|
${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
COMPATIBILITY SameMajorVersion
|
COMPATIBILITY SameMajorVersion
|
||||||
)
|
)
|
||||||
install(
|
install(EXPORT Calamares DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" FILE "CalamaresTargets.cmake" NAMESPACE Calamares::)
|
||||||
EXPORT Calamares
|
|
||||||
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
|
|
||||||
FILE "CalamaresTargets.cmake"
|
|
||||||
NAMESPACE Calamares::
|
|
||||||
)
|
|
||||||
|
|
||||||
# Install the cmake files
|
# Install the cmake files
|
||||||
install(
|
install(
|
||||||
@ -605,25 +692,14 @@ install(
|
|||||||
"CMakeModules/CalamaresCheckModuleSelection.cmake"
|
"CMakeModules/CalamaresCheckModuleSelection.cmake"
|
||||||
"CMakeModules/CMakeColors.cmake"
|
"CMakeModules/CMakeColors.cmake"
|
||||||
"CMakeModules/FindYAMLCPP.cmake"
|
"CMakeModules/FindYAMLCPP.cmake"
|
||||||
DESTINATION
|
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
|
||||||
"${CMAKE_INSTALL_CMAKEDIR}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
### Miscellaneous installs
|
### Miscellaneous installs
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
if( INSTALL_CONFIG )
|
|
||||||
install(
|
|
||||||
FILES settings.conf
|
|
||||||
DESTINATION share/calamares
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(INSTALL_POLKIT)
|
if(INSTALL_POLKIT)
|
||||||
install(
|
install(FILES com.github.calamares.calamares.policy DESTINATION "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}")
|
||||||
FILES com.github.calamares.calamares.policy
|
|
||||||
DESTINATION "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}"
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(INSTALL_COMPLETION)
|
if(INSTALL_COMPLETION)
|
||||||
@ -634,40 +710,44 @@ if ( INSTALL_COMPLETION )
|
|||||||
install(FILES ${CMAKE_SOURCE_DIR}/data/completion/bash/calamares DESTINATION "${CMAKE_INSTALL_BASHCOMPLETIONDIR}")
|
install(FILES ${CMAKE_SOURCE_DIR}/data/completion/bash/calamares DESTINATION "${CMAKE_INSTALL_BASHCOMPLETIONDIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(
|
install(FILES calamares.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
|
||||||
FILES calamares.desktop
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
install(FILES man/calamares.8 DESTINATION ${CMAKE_INSTALL_MANDIR}/man8/)
|
||||||
FILES man/calamares.8
|
|
||||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man8/
|
|
||||||
)
|
|
||||||
|
|
||||||
# uninstall target
|
if(INSTALL_CONFIG)
|
||||||
|
install(FILES settings.conf DESTINATION share/calamares)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
### Uninstall
|
||||||
|
#
|
||||||
|
#
|
||||||
configure_file(
|
configure_file(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
IMMEDIATE @ONLY
|
IMMEDIATE
|
||||||
|
@ONLY
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target( uninstall
|
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
|
|
||||||
)
|
### Developer convenience
|
||||||
|
#
|
||||||
|
# The module support files -- .desc files, .conf files -- are copied into the build
|
||||||
|
# directory so that it is possible to run `calamares -d` from there. Copy the
|
||||||
|
# top-level settings.conf as well, into the build directory.
|
||||||
|
if(settings.conf IS_NEWER_THAN ${CMAKE_BINARY_DIR}/settings.conf)
|
||||||
|
configure_file(settings.conf ${CMAKE_BINARY_DIR}/settings.conf COPYONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### CMAKE SUMMARY REPORT
|
### CMAKE SUMMARY REPORT
|
||||||
#
|
#
|
||||||
get_directory_property( SKIPPED_MODULES
|
get_directory_property(SKIPPED_MODULES DIRECTORY src/modules DEFINITION LIST_SKIPPED_MODULES)
|
||||||
DIRECTORY src/modules
|
|
||||||
DEFINITION LIST_SKIPPED_MODULES
|
|
||||||
)
|
|
||||||
calamares_explain_skipped_modules( ${SKIPPED_MODULES} )
|
calamares_explain_skipped_modules( ${SKIPPED_MODULES} )
|
||||||
|
|
||||||
feature_summary(
|
feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "The following features are enabled" QUIET_ON_EMPTY)
|
||||||
WHAT DISABLED_FEATURES
|
feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "The following features have been disabled:" QUIET_ON_EMPTY)
|
||||||
DESCRIPTION "The following features have been disabled:"
|
|
||||||
QUIET_ON_EMPTY
|
|
||||||
)
|
|
||||||
feature_summary(
|
feature_summary(
|
||||||
WHAT OPTIONAL_PACKAGES_NOT_FOUND
|
WHAT OPTIONAL_PACKAGES_NOT_FOUND
|
||||||
DESCRIPTION "The following OPTIONAL packages were not found:"
|
DESCRIPTION "The following OPTIONAL packages were not found:"
|
||||||
@ -684,11 +764,11 @@ feature_summary(
|
|||||||
#
|
#
|
||||||
# Note: most distro's will do distro-specific packaging rather than
|
# Note: most distro's will do distro-specific packaging rather than
|
||||||
# using CPack, and this duplicates information in the AppStream, too.
|
# using CPack, and this duplicates information in the AppStream, too.
|
||||||
# TODO:3.3 With newer CMake, move HOMEPAGE_URL to the project()call
|
|
||||||
set(CPACK_PACKAGE_VENDOR calamares)
|
set(CPACK_PACKAGE_VENDOR calamares)
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A Linux system installer")
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A Linux system installer")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION "Calamares is a Linux system installer, intended for Linux distributions to use on their ISOs and other bootable media to install the distribution to the end-user's computer. Calamares can also be used as an OEM configuration tool. It is modular, extensible and highly-configurable for Linux distributions from all five major Linux families.")
|
set(CPACK_PACKAGE_DESCRIPTION
|
||||||
set(CPACK_PACKAGE_HOMEPAGE_URL "https://calamares.io")
|
"Calamares is a Linux system installer, intended for Linux distributions to use on their ISOs and other bootable media to install the distribution to the end-user's computer. Calamares can also be used as an OEM configuration tool. It is modular, extensible and highly-configurable for Linux distributions from all five major Linux families."
|
||||||
|
)
|
||||||
set(CPACK_PACKAGE_ICON "data/images/squid.png")
|
set(CPACK_PACKAGE_ICON "data/images/squid.png")
|
||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
86
CMakeModules/AppStreamHelper.cmake
Normal file
86
CMakeModules/AppStreamHelper.cmake
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
# === This file is part of Calamares - <https://calamares.io> ===
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2023 Adriaan de Groot <groot@kde.org>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
#
|
||||||
|
###
|
||||||
|
#
|
||||||
|
# Finds AppStream-Qt suitable for the Qt version that is in use.
|
||||||
|
# Creates target calamares::appstreamqt to alias whatever is found.
|
||||||
|
# Sets AppStreamQt_FOUND appropriately, regardless of the underlying
|
||||||
|
# variables (e.g. might be AppStreamQt6_FOUND).
|
||||||
|
#
|
||||||
|
|
||||||
|
option(BUILD_APPSTREAM "Support appstream: items in PackageChooser (requires libappstream-qt)" OFF)
|
||||||
|
|
||||||
|
if(TARGET calaappstream)
|
||||||
|
if(TARGET calamares::appstreamqt)
|
||||||
|
message(STATUS "AppStreamQt has already been found")
|
||||||
|
set(AppStreamQt_FOUND TRUE)
|
||||||
|
else()
|
||||||
|
message(STATUS "AppStreamQt has been searched-for and not found")
|
||||||
|
set(AppStreamQt_FOUND FALSE)
|
||||||
|
endif()
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
if(NOT BUILD_APPSTREAM)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
### FIND APPSTREAM
|
||||||
|
#
|
||||||
|
# First, look for a Qt-versioned variety of the package.
|
||||||
|
# If that is not found, look for an unversioned one.
|
||||||
|
set(HAVE_APPSTREAM OFF)
|
||||||
|
find_package(AppStream${qtname})
|
||||||
|
# Not everyone renames the variables consistently
|
||||||
|
if(AppStream${qtname}_FOUND OR AppStreamQt_FOUND)
|
||||||
|
set(_appstream_name AppStream${qtname})
|
||||||
|
set(HAVE_APPSTREAM ON)
|
||||||
|
else()
|
||||||
|
find_package(AppStreamQt)
|
||||||
|
if(AppStreamQt_FOUND)
|
||||||
|
set(_appstream_name AppStreamQt)
|
||||||
|
# TODO: how to check underlying Qt version?
|
||||||
|
set(HAVE_APPSTREAM ON)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_APPSTREAM)
|
||||||
|
# Look for the directory name containing the headers
|
||||||
|
find_file(_appstream_header NAMES ${_appstream_name}/pool.h AppStreamQt/pool.h)
|
||||||
|
if(NOT _appstream_header)
|
||||||
|
set(HAVE_APPSTREAM OFF)
|
||||||
|
else()
|
||||||
|
if(_appstream_header MATCHES /${_appstream_name}/)
|
||||||
|
set(_appstream_header_directory ${_appstream_name})
|
||||||
|
else()
|
||||||
|
set(_appstream_header_directory AppStreamQt)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# Placeholder name
|
||||||
|
set(_appstream_name AppStreamQt)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_appstream_dependency_type OPTIONAL)
|
||||||
|
if(BUILD_APPSTREAM)
|
||||||
|
set(_appstream_dependency_type REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_package_properties(
|
||||||
|
${_appstream_name}
|
||||||
|
PROPERTIES
|
||||||
|
DESCRIPTION "Support for AppStream (cache) data"
|
||||||
|
URL "https://github.com/ximion/appstream"
|
||||||
|
PURPOSE "AppStream provides package data"
|
||||||
|
TYPE ${_appstream_dependency_type}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(calaappstream INTERFACE) # Always, but might not be populated
|
||||||
|
if(HAVE_APPSTREAM)
|
||||||
|
target_compile_definitions(calaappstream INTERFACE HAVE_APPSTREAM_VERSION=${${_appstream_name}_VERSION_MAJOR} HAVE_APPSTREAM_HEADERS=${_appstream_header_directory})
|
||||||
|
target_link_libraries(calaappstream INTERFACE ${_appstream_name})
|
||||||
|
add_library(calamares::appstreamqt ALIAS calaappstream)
|
||||||
|
endif()
|
||||||
|
set(AppStreamQt_FOUND ${HAVE_APPSTREAM})
|
@ -1,97 +0,0 @@
|
|||||||
# === This file is part of Calamares - <https://calamares.io> ===
|
|
||||||
#
|
|
||||||
# SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org>
|
|
||||||
# SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
|
|
||||||
# SPDX-FileCopyrightText: 2019 Kevin Kofler <kevin.kofler@chello.at>
|
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
#
|
|
||||||
###
|
|
||||||
#
|
|
||||||
# Handles the mess that Boost::Python is before CMake 3.16 and
|
|
||||||
# Boost 1.70 or so.
|
|
||||||
#
|
|
||||||
###
|
|
||||||
#
|
|
||||||
# On Ubuntu 14.04, the libboost-python1.54-dev package comes with one library
|
|
||||||
# for each Python version:
|
|
||||||
# libboost_python-py27.so
|
|
||||||
# libboost_python-py33.so
|
|
||||||
# libboost_python-py34.so
|
|
||||||
#
|
|
||||||
# Boost upstream however installs Boost.Python3 libboost_python3.so, which is
|
|
||||||
# what FindBoost.cmake is looking for. It looks for a library named
|
|
||||||
# "libboost_${component}.so".
|
|
||||||
#
|
|
||||||
# On Gentoo instead, the >=dev-libs/boost-1.54 package provides boost library
|
|
||||||
# with a name like:
|
|
||||||
# libboost_python-2.7.so
|
|
||||||
# libboost_python-3.3.so
|
|
||||||
# libboost_python-3.4.so
|
|
||||||
# depending on what python's targets you selected during install
|
|
||||||
#
|
|
||||||
# On Fedora >= 30 instead, the boost-python3-devel provides boost library with a
|
|
||||||
# name like:
|
|
||||||
# libboost_python37.so
|
|
||||||
# depending on what python's targets you selected during install
|
|
||||||
#
|
|
||||||
# find_boost_python3() tries to find the package with different component
|
|
||||||
# names. By default it tries "python3", "python-py$suffix" and
|
|
||||||
# "python-$dotsuffix", where suffix is based on the `python_version` argument.
|
|
||||||
# One can supply a custom component name by setting the
|
|
||||||
# `CALAMARES_BOOST_PYTHON3_COMPONENT` variable at CMake time.
|
|
||||||
set( CALAMARES_BOOST_PYTHON3_COMPONENT python3 CACHE STRING
|
|
||||||
"Name of the Boost.Python component. If Boost.Python is installed as
|
|
||||||
libboost_python-foo.so then this variable should be set to 'python-foo'."
|
|
||||||
)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
|
|
||||||
macro( _find_boost_python3_int boost_version componentname found_var )
|
|
||||||
foreach( _fbp_name ${CALAMARES_BOOST_PYTHON3_COMPONENT} ${componentname} )
|
|
||||||
find_package( Boost ${boost_version} QUIET COMPONENTS ${_fbp_name} )
|
|
||||||
string( TOUPPER ${_fbp_name} _fbp_uc_name )
|
|
||||||
if( Boost_${_fbp_uc_name}_FOUND )
|
|
||||||
if( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" )
|
|
||||||
# No upcasing
|
|
||||||
set( ${found_var} ${_fbp_name} )
|
|
||||||
else()
|
|
||||||
set( ${found_var} ${_fbp_uc_name} )
|
|
||||||
endif()
|
|
||||||
break()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
macro( find_boost_python3 boost_version python_version found_var )
|
|
||||||
set( ${found_var} OFF )
|
|
||||||
set( _fbp_found OFF )
|
|
||||||
|
|
||||||
# turns "3.4.123abc" into "34"
|
|
||||||
string( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\..*" "\\1\\2" _fbp_python_short_version ${python_version} )
|
|
||||||
_find_boost_python3_int( ${boost_version} python-py${_fbp_python_short_version} _fbp_found )
|
|
||||||
|
|
||||||
if (NOT _fbp_found)
|
|
||||||
_find_boost_python3_int( ${boost_version} python${_fbp_python_short_version} _fbp_found )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT _fbp_found)
|
|
||||||
# The following loop changes the searched name for Gentoo based distributions
|
|
||||||
# turns "3.4.123abc" into "3.4"
|
|
||||||
string( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\..*" "\\1.\\2" _fbp_python_short_version ${python_version} )
|
|
||||||
_find_boost_python3_int( ${boost_version} python-${_fbp_python_short_version} _fbp_found )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set( ${found_var} ${_fbp_found} )
|
|
||||||
|
|
||||||
# This is superfluous, but allows proper reporting in the features list
|
|
||||||
if ( _fbp_found )
|
|
||||||
find_package( Boost ${boost_version} COMPONENTS ${_fbp_found} )
|
|
||||||
else()
|
|
||||||
find_package( Boost ${boost_version} COMPONENTS Python )
|
|
||||||
endif()
|
|
||||||
set_package_properties(
|
|
||||||
Boost PROPERTIES
|
|
||||||
DESCRIPTION "A C++ library which enables seamless interoperability between C++ and Python 3."
|
|
||||||
URL "http://www.boost.org"
|
|
||||||
)
|
|
||||||
endmacro()
|
|
@ -101,7 +101,7 @@ function( calamares_add_branding_translations NAME )
|
|||||||
|
|
||||||
file( GLOB BRANDING_TRANSLATION_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${SUBDIRECTORY}/lang/calamares-${NAME}_*.ts" )
|
file( GLOB BRANDING_TRANSLATION_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${SUBDIRECTORY}/lang/calamares-${NAME}_*.ts" )
|
||||||
if ( BRANDING_TRANSLATION_FILES )
|
if ( BRANDING_TRANSLATION_FILES )
|
||||||
qt5_add_translation( QM_FILES ${BRANDING_TRANSLATION_FILES} )
|
qt_add_translation( QM_FILES ${BRANDING_TRANSLATION_FILES} )
|
||||||
add_custom_target( branding-translation-${NAME} ALL DEPENDS ${QM_FILES}
|
add_custom_target( branding-translation-${NAME} ALL DEPENDS ${QM_FILES}
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/lang/
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/lang/
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${QM_FILES} ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/lang/
|
COMMAND ${CMAKE_COMMAND} -E copy ${QM_FILES} ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/lang/
|
||||||
|
@ -62,8 +62,10 @@ function(calamares_add_library)
|
|||||||
add_library(${target} STATIC ${LIBRARY_SOURCES})
|
add_library(${target} STATIC ${LIBRARY_SOURCES})
|
||||||
elseif(LIBRARY_TARGET_TYPE STREQUAL "MODULE")
|
elseif(LIBRARY_TARGET_TYPE STREQUAL "MODULE")
|
||||||
add_library(${target} MODULE ${LIBRARY_SOURCES})
|
add_library(${target} MODULE ${LIBRARY_SOURCES})
|
||||||
else() # default
|
elseif(LIBRARY_TARGET_TYPE STREQUAL "SHARED")
|
||||||
add_library(${target} SHARED ${LIBRARY_SOURCES})
|
add_library(${target} SHARED ${LIBRARY_SOURCES})
|
||||||
|
else() # default
|
||||||
|
message(FATAL_ERROR "Invalid library type '${LIBRARY_TARGET_TYPE}'")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
calamares_automoc(${target})
|
calamares_automoc(${target})
|
||||||
@ -86,9 +88,9 @@ function(calamares_add_library)
|
|||||||
# add link targets
|
# add link targets
|
||||||
target_link_libraries(${target}
|
target_link_libraries(${target}
|
||||||
LINK_PUBLIC ${Calamares_LIBRARIES}
|
LINK_PUBLIC ${Calamares_LIBRARIES}
|
||||||
Qt5::Core
|
${qtname}::Core
|
||||||
Qt5::Gui
|
${qtname}::Gui
|
||||||
Qt5::Widgets
|
${qtname}::Widgets
|
||||||
)
|
)
|
||||||
if(LIBRARY_LINK_LIBRARIES)
|
if(LIBRARY_LINK_LIBRARIES)
|
||||||
target_link_libraries(${target} LINK_PUBLIC ${LIBRARY_LINK_LIBRARIES})
|
target_link_libraries(${target} LINK_PUBLIC ${LIBRARY_LINK_LIBRARIES})
|
||||||
|
@ -121,7 +121,8 @@ function( _calamares_add_module_subdirectory_impl )
|
|||||||
# _mod_testing boolean if the module should be added to the loadmodule tests
|
# _mod_testing boolean if the module should be added to the loadmodule tests
|
||||||
file(STRINGS "${_mod_dir}/module.desc" MODULE_INTERFACE REGEX "^interface")
|
file(STRINGS "${_mod_dir}/module.desc" MODULE_INTERFACE REGEX "^interface")
|
||||||
if ( MODULE_INTERFACE MATCHES "pythonqt" )
|
if ( MODULE_INTERFACE MATCHES "pythonqt" )
|
||||||
set( _mod_enabled ${Calamares_WITH_PYTHONQT} )
|
message( FATAL_ERROR "PythonQt is no longer supported" )
|
||||||
|
set( _mod_enabled OFF )
|
||||||
set( _mod_reason "No PythonQt support" )
|
set( _mod_reason "No PythonQt support" )
|
||||||
set( _mod_testing OFF )
|
set( _mod_testing OFF )
|
||||||
elseif ( MODULE_INTERFACE MATCHES "python" )
|
elseif ( MODULE_INTERFACE MATCHES "python" )
|
||||||
@ -152,12 +153,10 @@ function( _calamares_add_module_subdirectory_impl )
|
|||||||
|
|
||||||
get_filename_component( FLEXT ${MODULE_FILE} EXT )
|
get_filename_component( FLEXT ${MODULE_FILE} EXT )
|
||||||
if( "${FLEXT}" STREQUAL ".conf" )
|
if( "${FLEXT}" STREQUAL ".conf" )
|
||||||
if( INSTALL_CONFIG )
|
message(STATUS "Config ${MODULE_FILE}")
|
||||||
install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${MODULE_FILE}
|
|
||||||
DESTINATION ${MODULE_DATA_DESTINATION} )
|
|
||||||
endif()
|
|
||||||
list( APPEND MODULE_CONFIG_FILES ${MODULE_FILE} )
|
list( APPEND MODULE_CONFIG_FILES ${MODULE_FILE} )
|
||||||
else()
|
else()
|
||||||
|
message(STATUS "Non-Config ${MODULE_FILE}")
|
||||||
install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${MODULE_FILE}
|
install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${MODULE_FILE}
|
||||||
DESTINATION ${MODULE_DESTINATION} )
|
DESTINATION ${MODULE_DESTINATION} )
|
||||||
endif()
|
endif()
|
||||||
@ -169,11 +168,13 @@ function( _calamares_add_module_subdirectory_impl )
|
|||||||
message( " ${Green}MODULE_DESTINATION:${ColorReset} ${MODULE_DESTINATION}" )
|
message( " ${Green}MODULE_DESTINATION:${ColorReset} ${MODULE_DESTINATION}" )
|
||||||
if( MODULE_CONFIG_FILES )
|
if( MODULE_CONFIG_FILES )
|
||||||
if (INSTALL_CONFIG)
|
if (INSTALL_CONFIG)
|
||||||
set( _destination "${MODULE_DATA_DESTINATION}" )
|
message(" ${Green}CONFIGURATION_FILES:${ColorReset} ${MODULE_CONFIG_FILES} => [Build directory and ${MODULE_DATA_DESTINATION}]")
|
||||||
|
foreach(_cf ${MODULE_CONFIG_FILES})
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${_cf} DESTINATION ${MODULE_DATA_DESTINATION})
|
||||||
|
endforeach()
|
||||||
else()
|
else()
|
||||||
set( _destination "[Build directory only]" )
|
message(" ${Green}CONFIGURATION_FILES:${ColorReset} ${MODULE_CONFIG_FILES} => [Build directory only]")
|
||||||
endif()
|
endif()
|
||||||
message( " ${Green}CONFIGURATION_FILES:${ColorReset} ${MODULE_CONFIG_FILES} => ${_destination}" )
|
|
||||||
endif()
|
endif()
|
||||||
message( "" )
|
message( "" )
|
||||||
# We copy over the lang directory, if any
|
# We copy over the lang directory, if any
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#
|
#
|
||||||
# calamares_add_plugin(
|
# calamares_add_plugin(
|
||||||
# module-name
|
# module-name
|
||||||
# TYPE <view|job>
|
# TYPE <viewmodule|job>
|
||||||
# EXPORT_MACRO macro-name
|
# EXPORT_MACRO macro-name
|
||||||
# SOURCES source-file...
|
# SOURCES source-file...
|
||||||
# UI ui-file...
|
# UI ui-file...
|
||||||
@ -35,7 +35,7 @@
|
|||||||
# [WEIGHT w]
|
# [WEIGHT w]
|
||||||
# )
|
# )
|
||||||
#
|
#
|
||||||
# Function parameters:
|
# Function optional parameters:
|
||||||
# - COMPILE_DEFINITIONS
|
# - COMPILE_DEFINITIONS
|
||||||
# Definitions are set on the resulting module with a suitable
|
# Definitions are set on the resulting module with a suitable
|
||||||
# flag (i.e. `-D`) so only state the name (optionally, also the value)
|
# flag (i.e. `-D`) so only state the name (optionally, also the value)
|
||||||
@ -65,6 +65,11 @@
|
|||||||
# SKIPPED_MODULES is set in the parent (i.e. caller's) scope with the
|
# SKIPPED_MODULES is set in the parent (i.e. caller's) scope with the
|
||||||
# reason why. This should rarely be a concern as AddModuleSubdirectory
|
# reason why. This should rarely be a concern as AddModuleSubdirectory
|
||||||
# already handles skip-reasons and collects them for reporting.
|
# already handles skip-reasons and collects them for reporting.
|
||||||
|
#
|
||||||
|
# The target defined this way is called "calamares_<TYPE>_<module-name>",
|
||||||
|
# e.g. "calamares_viewmodule_packagechooserq". The function sets a variable
|
||||||
|
# in its **calling** scope, `<module-name>_TARGET` with the full name
|
||||||
|
# of the target.
|
||||||
|
|
||||||
include( CMakeParseArguments )
|
include( CMakeParseArguments )
|
||||||
|
|
||||||
@ -107,7 +112,6 @@ function( calamares_add_plugin )
|
|||||||
if(INSTALL_CONFIG AND NOT PLUGIN_NO_INSTALL)
|
if(INSTALL_CONFIG AND NOT PLUGIN_NO_INSTALL)
|
||||||
set(_destination "${PLUGIN_DATA_DESTINATION}")
|
set(_destination "${PLUGIN_DATA_DESTINATION}")
|
||||||
elseif( NOT PLUGIN_NO_INSTALL )
|
elseif( NOT PLUGIN_NO_INSTALL )
|
||||||
# Not INSTALL_CONFIG
|
|
||||||
set( _destination "[Build directory only]" )
|
set( _destination "[Build directory only]" )
|
||||||
else()
|
else()
|
||||||
set( _destination "[Skipping installation]" )
|
set( _destination "[Skipping installation]" )
|
||||||
@ -127,7 +131,7 @@ function( calamares_add_plugin )
|
|||||||
set( target "calamares_${PLUGIN_TYPE}_${PLUGIN_NAME}" )
|
set( target "calamares_${PLUGIN_TYPE}_${PLUGIN_NAME}" )
|
||||||
|
|
||||||
# automatic library linkage
|
# automatic library linkage
|
||||||
if(PLUGIN_TYPE STREQUAL "view" OR PLUGIN_TYPE STREQUAL "viewmodule")
|
if(PLUGIN_TYPE STREQUAL "viewmodule")
|
||||||
list(APPEND PLUGIN_LINK_PRIVATE_LIBRARIES Calamares::calamaresui)
|
list(APPEND PLUGIN_LINK_PRIVATE_LIBRARIES Calamares::calamaresui)
|
||||||
elseif(PLUGIN_TYPE STREQUAL "job")
|
elseif(PLUGIN_TYPE STREQUAL "job")
|
||||||
list(APPEND PLUGIN_LINK_PRIVATE_LIBRARIES Calamares::calamares)
|
list(APPEND PLUGIN_LINK_PRIVATE_LIBRARIES Calamares::calamares)
|
||||||
@ -210,20 +214,20 @@ function( calamares_add_plugin )
|
|||||||
|
|
||||||
set( _warned_config OFF )
|
set( _warned_config OFF )
|
||||||
foreach( PLUGIN_CONFIG_FILE ${PLUGIN_CONFIG_FILES} )
|
foreach( PLUGIN_CONFIG_FILE ${PLUGIN_CONFIG_FILES} )
|
||||||
if( ${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN_CONFIG_FILE} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE} OR INSTALL_CONFIG )
|
if( ${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN_CONFIG_FILE} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE} )
|
||||||
configure_file( ${PLUGIN_CONFIG_FILE} ${PLUGIN_CONFIG_FILE} COPYONLY )
|
configure_file( ${PLUGIN_CONFIG_FILE} ${PLUGIN_CONFIG_FILE} COPYONLY )
|
||||||
else()
|
else()
|
||||||
message( " ${BoldYellow}Not updating${ColorReset} ${PLUGIN_CONFIG_FILE}" )
|
message( " ${BoldYellow}Not updating${ColorReset} ${PLUGIN_CONFIG_FILE}" )
|
||||||
set( _warned_config ON )
|
set( _warned_config ON )
|
||||||
endif()
|
endif()
|
||||||
if(INSTALL_CONFIG)
|
if(INSTALL_CONFIG)
|
||||||
install(
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE} DESTINATION ${PLUGIN_DATA_DESTINATION})
|
||||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE}
|
|
||||||
DESTINATION ${PLUGIN_DATA_DESTINATION} )
|
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
if ( _warned_config )
|
if ( _warned_config )
|
||||||
message( "" )
|
message( "" )
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(${NAME}_TARGET ${target} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -21,14 +21,12 @@
|
|||||||
include(CMakeParseArguments)
|
include(CMakeParseArguments)
|
||||||
include(CalamaresAutomoc)
|
include(CalamaresAutomoc)
|
||||||
|
|
||||||
function( calamares_add_test )
|
function(calamares_add_test name)
|
||||||
# parse arguments (name needs to be saved before passing ARGN into the macro)
|
|
||||||
set( NAME ${ARGV0} )
|
|
||||||
set(options GUI)
|
set(options GUI)
|
||||||
set( oneValueArgs NAME RESOURCES )
|
set(oneValueArgs RESOURCES)
|
||||||
set(multiValueArgs SOURCES LIBRARIES DEFINITIONS)
|
set(multiValueArgs SOURCES LIBRARIES DEFINITIONS)
|
||||||
cmake_parse_arguments(TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
cmake_parse_arguments(TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
set( TEST_NAME ${NAME} )
|
set(TEST_NAME ${name})
|
||||||
|
|
||||||
if(ECM_FOUND AND BUILD_TESTING)
|
if(ECM_FOUND AND BUILD_TESTING)
|
||||||
ecm_add_test(
|
ecm_add_test(
|
||||||
@ -38,15 +36,18 @@ function( calamares_add_test )
|
|||||||
LINK_LIBRARIES
|
LINK_LIBRARIES
|
||||||
Calamares::calamares
|
Calamares::calamares
|
||||||
${TEST_LIBRARIES}
|
${TEST_LIBRARIES}
|
||||||
Qt5::Core
|
${qtname}::Core
|
||||||
Qt5::Test
|
${qtname}::Test
|
||||||
)
|
)
|
||||||
calamares_automoc( ${TEST_NAME} )
|
calamares_automoc( ${TEST_NAME} )
|
||||||
# We specifically pass in the source directory of the test-being-
|
# We specifically pass in the source directory of the test-being-
|
||||||
# compiled, so that it can find test-files in that source dir.
|
# compiled, so that it can find test-files in that source dir.
|
||||||
target_compile_definitions( ${TEST_NAME} PRIVATE -DBUILD_AS_TEST="${CMAKE_CURRENT_SOURCE_DIR}" ${TEST_DEFINITIONS} )
|
target_compile_definitions(
|
||||||
|
${TEST_NAME}
|
||||||
|
PRIVATE -DBUILD_AS_TEST="${CMAKE_CURRENT_SOURCE_DIR}" ${TEST_DEFINITIONS}
|
||||||
|
)
|
||||||
if(TEST_GUI)
|
if(TEST_GUI)
|
||||||
target_link_libraries( ${TEST_NAME} Calamares::calamaresui Qt5::Gui )
|
target_link_libraries(${TEST_NAME} Calamares::calamaresui ${qtname}::Gui)
|
||||||
endif()
|
endif()
|
||||||
if(TEST_RESOURCES)
|
if(TEST_RESOURCES)
|
||||||
calamares_autorcc( ${TEST_NAME} ${TEST_RESOURCES} )
|
calamares_autorcc( ${TEST_NAME} ${TEST_RESOURCES} )
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# This file has not yet been documented for use outside of Calamares itself.
|
# This file has not yet been documented for use outside of Calamares itself.
|
||||||
|
|
||||||
include(CMakeParseArguments)
|
include(CMakeParseArguments)
|
||||||
|
include(FeatureSummary)
|
||||||
|
|
||||||
# The Gettext module is still old-fashioned, ALLCAPS variables
|
# The Gettext module is still old-fashioned, ALLCAPS variables
|
||||||
find_package( Gettext )
|
find_package( Gettext )
|
||||||
@ -100,3 +101,58 @@ function( install_calamares_gettext_translations )
|
|||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
set(_calamares_qrc_translations_qrc_source ${CMAKE_CURRENT_LIST_DIR}/i18n.qrc.in) # Needs to be set outside of function
|
||||||
|
function(calamares_qrc_translations basename)
|
||||||
|
set(options "")
|
||||||
|
set(oneValueArgs SUBDIRECTORY OUTPUT_VARIABLE)
|
||||||
|
set(multiValueArgs PREFIXES LANGUAGES)
|
||||||
|
cmake_parse_arguments(_qrt "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT _qrt_OUTPUT_VARIABLE)
|
||||||
|
message(FATAL_ERROR "No output variable")
|
||||||
|
endif()
|
||||||
|
if(NOT _qrt_PREFIXES)
|
||||||
|
set(_qrt_PREFIXES "${basename}")
|
||||||
|
endif()
|
||||||
|
if(NOT _qrt_LANGUAGES)
|
||||||
|
set(_qrt_LANGUAGES ${CALAMARES_TRANSLATION_LANGUAGES})
|
||||||
|
endif()
|
||||||
|
if(NOT _qrt_SUBDIRECTORY)
|
||||||
|
set(_qrt_SUBDIRECTORY "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(translations_qrc_infile ${CMAKE_CURRENT_BINARY_DIR}/${basename}.qrc)
|
||||||
|
set(translations_qrc_outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${basename}.cxx)
|
||||||
|
|
||||||
|
# Must use this variable name because of the @ substitution
|
||||||
|
set(calamares_i18n_qrc_content "")
|
||||||
|
set(calamares_i18n_ts_filelist "")
|
||||||
|
foreach(lang ${_qrt_LANGUAGES})
|
||||||
|
foreach(tlsource ${_qrt_PREFIXES})
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_qrt_SUBDIRECTORY}/${tlsource}_${lang}.ts")
|
||||||
|
string(APPEND calamares_i18n_qrc_content "<file>${tlsource}_${lang}.qm</file>\n")
|
||||||
|
list(APPEND calamares_i18n_ts_filelist "${CMAKE_CURRENT_SOURCE_DIR}/${_qrt_SUBDIRECTORY}/${tlsource}_${lang}.ts")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
configure_file(${_calamares_qrc_translations_qrc_source} ${translations_qrc_infile} @ONLY)
|
||||||
|
qt_add_translation(QM_FILES ${calamares_i18n_ts_filelist})
|
||||||
|
|
||||||
|
# Run the resource compiler (rcc_options should already be set)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${translations_qrc_outfile}
|
||||||
|
COMMAND ${qtname}::rcc
|
||||||
|
ARGS
|
||||||
|
${rcc_options}
|
||||||
|
--format-version 1
|
||||||
|
-name ${basename}
|
||||||
|
-o ${translations_qrc_outfile}
|
||||||
|
${translations_qrc_infile}
|
||||||
|
MAIN_DEPENDENCY ${translations_qrc_infile}
|
||||||
|
DEPENDS ${QM_FILES}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(${_qrt_OUTPUT_VARIABLE} ${translations_qrc_outfile} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
@ -57,11 +57,6 @@ function( extend_version version short_only short_var long_var )
|
|||||||
set( ${short_var} "${version}" PARENT_SCOPE )
|
set( ${short_var} "${version}" PARENT_SCOPE )
|
||||||
set( _v "${version}" )
|
set( _v "${version}" )
|
||||||
if ( NOT short_only )
|
if ( NOT short_only )
|
||||||
# Additional info for non-release builds which want "long" version info
|
|
||||||
# with date and git information (commit, dirty status). That is used only
|
|
||||||
# by CalamaresVersionX.h, which is included by consumers that need a full
|
|
||||||
# version number with all that information; normal consumers can include
|
|
||||||
# CalamaresVersion.h with more stable numbers.
|
|
||||||
string( TIMESTAMP CALAMARES_VERSION_DATE "%Y%m%d" )
|
string( TIMESTAMP CALAMARES_VERSION_DATE "%Y%m%d" )
|
||||||
if( CALAMARES_VERSION_DATE GREATER 0 )
|
if( CALAMARES_VERSION_DATE GREATER 0 )
|
||||||
set( _v ${_v}.${CALAMARES_VERSION_DATE} )
|
set( _v ${_v}.${CALAMARES_VERSION_DATE} )
|
||||||
|
@ -1,185 +0,0 @@
|
|||||||
# === This file is part of Calamares - <https://calamares.io> ===
|
|
||||||
#
|
|
||||||
# SPDX-FileCopyrightText: 2016 Teo Mrnjavac <teo@kde.org>
|
|
||||||
# SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
|
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
#
|
|
||||||
###
|
|
||||||
#
|
|
||||||
# Find PythonQt
|
|
||||||
#
|
|
||||||
# Sets PYTHONQT_FOUND, PYTHONQT_INCLUDE_DIR, PYTHONQT_LIBRARY, PYTHONQT_LIBRARIES
|
|
||||||
#
|
|
||||||
# Also sets PYTHONQT_INCLUDE_DIRS to add whatever directories
|
|
||||||
# that are needed for extensions.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Python is required
|
|
||||||
find_package(PythonLibs)
|
|
||||||
if(NOT PYTHONLIBS_FOUND)
|
|
||||||
message(FATAL_ERROR "error: Python is required to build PythonQt")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Cut X.Y[.Z] down to just X.Y
|
|
||||||
string(REGEX REPLACE
|
|
||||||
"^([0-9][0-9]*)\.([0-9][0-9]*)"
|
|
||||||
"\\1.\\2@"
|
|
||||||
_PYTHONLIBS_MAJMIN
|
|
||||||
${PYTHONLIBS_VERSION_STRING}
|
|
||||||
)
|
|
||||||
string(REGEX REPLACE
|
|
||||||
"@.*"
|
|
||||||
""
|
|
||||||
PYTHONLIBS_MAJMIN
|
|
||||||
${_PYTHONLIBS_MAJMIN}
|
|
||||||
)
|
|
||||||
|
|
||||||
if(NOT EXISTS "${PYTHONQT_INSTALL_DIR}")
|
|
||||||
find_path(PYTHONQT_INSTALL_DIR
|
|
||||||
NAMES
|
|
||||||
include/PythonQt/PythonQt.h
|
|
||||||
include/PythonQt5/PythonQt.h
|
|
||||||
DOC "Directory where PythonQt was installed.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# XXX Since PythonQt 3.0 is not yet cmakeified, depending
|
|
||||||
# on how PythonQt is built, headers will not always be
|
|
||||||
# installed in "include/PythonQt". That is why "src"
|
|
||||||
# is added as an option. See [1] for more details.
|
|
||||||
# [1] https://github.com/commontk/CTK/pull/538#issuecomment-86106367
|
|
||||||
find_path(PYTHONQT_INCLUDE_DIR PythonQt.h
|
|
||||||
PATHS
|
|
||||||
"${PYTHONQT_INSTALL_DIR}/include/PythonQt"
|
|
||||||
"${PYTHONQT_INSTALL_DIR}/include/PythonQt5"
|
|
||||||
"${PYTHONQT_INSTALL_DIR}/src"
|
|
||||||
DOC "Path to the PythonQt include directory")
|
|
||||||
find_path(PYTHONQT_ALL_INCLUDE_DIR PythonQt_QtAll.h
|
|
||||||
PATHS
|
|
||||||
"${PYTHONQT_INCLUDE_DIR}"
|
|
||||||
"${PYTHONQT_INSTALL_DIR}"
|
|
||||||
PATH_SUFFIXES
|
|
||||||
"extensions/PythonQt_QtAll"
|
|
||||||
"src"
|
|
||||||
DOC "Path to the PythonQt 'all' header")
|
|
||||||
|
|
||||||
if ( NOT PythonQt_FIND_QUIETLY )
|
|
||||||
message( STATUS "Searching for PythonQt (PythonLibs ${PYTHONLIBS_MAJMIN}) .." )
|
|
||||||
if ( PYTHONQT_INCLUDE_DIR )
|
|
||||||
message( STATUS " .. found include ${PYTHONQT_INCLUDE_DIR}" )
|
|
||||||
message( STATUS " .. found all include ${PYTHONQT_ALL_INCLUDE_DIR}" )
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Minimum v3.1 is needed
|
|
||||||
find_library(PYTHONQT_LIBRARY_RELEASE
|
|
||||||
NAMES
|
|
||||||
PythonQt-Qt5-Python${PYTHONLIBS_MAJMIN}
|
|
||||||
PythonQt-Qt5-Python3
|
|
||||||
PythonQt
|
|
||||||
PATHS "${PYTHONQT_INSTALL_DIR}/lib"
|
|
||||||
DOC "The PythonQt library."
|
|
||||||
)
|
|
||||||
find_library(PYTHONQT_LIBRARY_DEBUG
|
|
||||||
NAMES
|
|
||||||
PythonQt-Qt5-Python${PYTHONLIBS_MAJMIN}JMIN${CTK_CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt-Qt5-Python${PYTHONLIBS_MAJMIN}${CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt-Qt5-Python${PYTHONLIBS_MAJMIN}
|
|
||||||
PythonQt-Qt5-Python3${CTK_CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt-Qt5-Python3${CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt-Qt5-Python3
|
|
||||||
PythonQt${CTK_CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt${CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt
|
|
||||||
PATHS "${PYTHONQT_INSTALL_DIR}/lib"
|
|
||||||
DOC "The PythonQt library (debug build)."
|
|
||||||
)
|
|
||||||
find_library(PYTHONQT_QTALL_LIBRARY_RELEASE
|
|
||||||
NAMES
|
|
||||||
PythonQt_QtAll-Qt5-Python${PYTHONLIBS_MAJMIN}
|
|
||||||
PythonQt_QtAll-Qt5-Python3
|
|
||||||
PythonQt_QtAll
|
|
||||||
PATHS "${PYTHONQT_INSTALL_DIR}/lib"
|
|
||||||
DOC "Full Qt bindings for the PythonQt library."
|
|
||||||
)
|
|
||||||
find_library(PYTHONQT_QTALL_LIBRARY_DEBUG
|
|
||||||
NAMES
|
|
||||||
PythonQt_QtAll-Qt5-Python${PYTHONLIBS_MAJMIN}${CTK_CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt_QtAll-Qt5-Python${PYTHONLIBS_MAJMIN}${CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt_QtAll-Qt5-Python${PYTHONLIBS_MAJMIN}
|
|
||||||
PythonQt_QtAll-Qt5-Python3${CTK_CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt_QtAll-Qt5-Python3${CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt_QtAll-Qt5-Python3
|
|
||||||
PythonQt_QtAll${CTK_CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt_QtAll${CMAKE_DEBUG_POSTFIX}
|
|
||||||
PythonQt_QtAll
|
|
||||||
PATHS "${PYTHONQT_INSTALL_DIR}/lib"
|
|
||||||
DOC "Full Qt bindings for the PythonQt library (debug build)."
|
|
||||||
)
|
|
||||||
|
|
||||||
set(PYTHONQT_LIBRARY)
|
|
||||||
if(PYTHONQT_LIBRARY_RELEASE)
|
|
||||||
list(APPEND PYTHONQT_LIBRARY optimized ${PYTHONQT_LIBRARY_RELEASE})
|
|
||||||
endif()
|
|
||||||
if(PYTHONQT_LIBRARY_DEBUG)
|
|
||||||
list(APPEND PYTHONQT_LIBRARY debug ${PYTHONQT_LIBRARY_DEBUG})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(PYTHONQT_QTALL_LIBRARY)
|
|
||||||
if(PYTHONQT_QTALL_LIBRARY_RELEASE)
|
|
||||||
list(APPEND PYTHONQT_QTALL_LIBRARY optimized ${PYTHONQT_QTALL_LIBRARY_RELEASE})
|
|
||||||
endif()
|
|
||||||
if(PYTHONQT_QTALL_LIBRARY_DEBUG)
|
|
||||||
list(APPEND PYTHONQT_QTALL_LIBRARY debug ${PYTHONQT_QTALL_LIBRARY_DEBUG})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if ( NOT PythonQt_FIND_QUIETLY )
|
|
||||||
if ( PYTHONQT_LIBRARY )
|
|
||||||
message( STATUS " .. found library ${PYTHONQT_LIBRARY}" )
|
|
||||||
endif()
|
|
||||||
if ( PYTHONQT_QTALL_LIBRARY )
|
|
||||||
message( STATUS " .. found qtall ${PYTHONQT_QTALL_LIBRARY}" )
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
mark_as_advanced(PYTHONQT_INSTALL_DIR)
|
|
||||||
mark_as_advanced(PYTHONQT_INCLUDE_DIR)
|
|
||||||
mark_as_advanced(PYTHONQT_LIBRARY_RELEASE)
|
|
||||||
mark_as_advanced(PYTHONQT_LIBRARY_DEBUG)
|
|
||||||
mark_as_advanced(PYTHONQT_QTALL_LIBRARY_RELEASE)
|
|
||||||
mark_as_advanced(PYTHONQT_QTALL_LIBRARY_DEBUG)
|
|
||||||
|
|
||||||
# On linux, also find libutil
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
find_library(PYTHONQT_LIBUTIL util)
|
|
||||||
mark_as_advanced(PYTHONQT_LIBUTIL)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# All upper case _FOUND variable is maintained for backwards compatibility.
|
|
||||||
set(PYTHONQT_FOUND 0)
|
|
||||||
set(PythonQt_FOUND 0)
|
|
||||||
|
|
||||||
if(PYTHONQT_INCLUDE_DIR AND PYTHONQT_LIBRARY AND PYTHONQT_QTALL_LIBRARY)
|
|
||||||
# Currently CMake'ified PythonQt only supports building against a python Release build.
|
|
||||||
# This applies independently of CTK build type (Release, Debug, ...)
|
|
||||||
add_definitions(-DPYTHONQT_USE_RELEASE_PYTHON_FALLBACK)
|
|
||||||
set(PYTHONQT_FOUND 1)
|
|
||||||
set(PythonQt_FOUND ${PYTHONQT_FOUND})
|
|
||||||
set(PYTHONQT_LIBRARIES ${PYTHONQT_LIBRARY} ${PYTHONQT_LIBUTIL} ${PYTHONQT_QTALL_LIBRARY})
|
|
||||||
set(PYTHONQT_INCLUDE_DIRS ${PYTHONQT_INCLUDE_DIR})
|
|
||||||
if(PYTHONQT_ALL_INCLUDE_DIR)
|
|
||||||
list(APPEND PYTHONQT_INCLUDE_DIRS ${PYTHONQT_ALL_INCLUDE_DIR})
|
|
||||||
endif()
|
|
||||||
elseif(NOT PythonQt_FIND_QUIETLY)
|
|
||||||
set(_missing "")
|
|
||||||
if (NOT PYTHONQT_INCLUDE_DIR)
|
|
||||||
list(APPEND _missing "includes")
|
|
||||||
endif()
|
|
||||||
if (NOT PYTHONQT_LIBRARY)
|
|
||||||
list(APPEND _missing "library")
|
|
||||||
endif()
|
|
||||||
if (NOT PYTHONQT_QTALL_LIBRARY)
|
|
||||||
list(APPEND _missing "qtall")
|
|
||||||
endif()
|
|
||||||
message(STATUS "PythonQt not found, missing components ${_missing}")
|
|
||||||
endif()
|
|
@ -7,33 +7,58 @@
|
|||||||
#
|
#
|
||||||
# Finds KPMcore and consistently sets API flags based on the version.
|
# Finds KPMcore and consistently sets API flags based on the version.
|
||||||
#
|
#
|
||||||
if ( NOT KPMcore_searched_for )
|
# If KPMcore is not found, still create calamares::kpmcore interface
|
||||||
set( KPMcore_searched_for TRUE )
|
# library, which will add definition WITHOUT_KPMcore.
|
||||||
|
#
|
||||||
|
if(NOT TARGET calapmcore)
|
||||||
|
find_package(${kfname}Config CONFIG)
|
||||||
|
find_package(${kfname}I18n CONFIG)
|
||||||
|
find_package(${kfname}WidgetsAddons CONFIG)
|
||||||
|
|
||||||
find_package( KPMcore 3.3 )
|
if(WITH_QT6)
|
||||||
|
find_package(KPMcore 24.01.75)
|
||||||
|
else()
|
||||||
|
find_package(KPMcore 20.04.0)
|
||||||
|
endif()
|
||||||
set_package_properties(
|
set_package_properties(
|
||||||
KPMcore PROPERTIES
|
KPMcore
|
||||||
|
PROPERTIES
|
||||||
URL "https://invent.kde.org/kde/kpmcore"
|
URL "https://invent.kde.org/kde/kpmcore"
|
||||||
DESCRIPTION "KDE Partitioning library"
|
DESCRIPTION "KDE Partitioning library"
|
||||||
TYPE RECOMMENDED
|
TYPE RECOMMENDED
|
||||||
PURPOSE "For disk partitioning support"
|
PURPOSE "For disk partitioning support"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Create an internal Calamares interface to KPMcore
|
||||||
|
# and give it a nice alias name. If kpmcore is not found,
|
||||||
|
# then make a "no KPMcore" library.
|
||||||
|
add_library(calapmcore INTERFACE)
|
||||||
|
|
||||||
if(KPMcore_FOUND)
|
if(KPMcore_FOUND)
|
||||||
set( KPMcore_API_DEFINITIONS "" )
|
find_package(${qtname} REQUIRED DBus) # Needed for KPMCore
|
||||||
if( KPMcore_VERSION VERSION_GREATER "3.3.70" AND KPMcore_VERSION VERSION_LESS "4.0" )
|
find_package(${kfname}I18n REQUIRED) # Needed for KPMCore
|
||||||
message( FATAL_ERROR "KPMCore beta versions ${KPMcore_VERSION} not supported" )
|
find_package(${kfname}WidgetsAddons REQUIRED) # Needed for KPMCore
|
||||||
endif()
|
|
||||||
if ( KPMcore_VERSION VERSION_GREATER "3.3.0")
|
target_link_libraries(calapmcore INTERFACE kpmcore ${qtname}::DBus ${kfname}::I18n ${kfname}::WidgetsAddons)
|
||||||
list( APPEND KPMcore_API_DEFINITIONS WITH_KPMCORE331API) # kpmcore > 3.3.0 with deprecations
|
target_include_directories(calapmcore INTERFACE ${KPMCORE_INCLUDE_DIR})
|
||||||
endif()
|
# If there were KPMcore API variations, figure them out here
|
||||||
if ( KPMcore_VERSION VERSION_GREATER_EQUAL "4.0")
|
# target_compile_definitions(calapmcore INTERFACE WITH_KPMcore)
|
||||||
list( APPEND KPMcore_API_DEFINITIONS WITH_KPMCORE4API) # kpmcore 4 with new API
|
|
||||||
endif()
|
# Flag that this library has KPMcore support. A variable
|
||||||
if( KPMcore_VERSION VERSION_GREATER_EQUAL "4.2" )
|
# set here has the wrong scope. ENV{} would be visible
|
||||||
list( APPEND KPMcore_API_DEFINITIONS WITH_KPMCORE42API) # kpmcore 4.2 with new API
|
# everywhere but seems the wrong thing to do. Setting
|
||||||
|
# properties on calapmcore requires a newer CMake than
|
||||||
|
# Debian 11 has, so runs into support issues.
|
||||||
|
add_library(calamares::kpmcore ALIAS calapmcore)
|
||||||
|
else()
|
||||||
|
target_compile_definitions(calapmcore INTERFACE WITHOUT_KPMcore)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
set( KPMcore_API_DEFINITIONS WITHOUT_KPMcore )
|
if(TARGET calamares::kpmcore)
|
||||||
|
message(STATUS "KPMcore has already been found")
|
||||||
|
set(KPMcore_FOUND TRUE)
|
||||||
|
else()
|
||||||
|
message(STATUS "KPMcore has been searched-for and not found")
|
||||||
|
set(KPMcore_FOUND FALSE)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
182
CONTRIBUTING.md
182
CONTRIBUTING.md
@ -28,18 +28,18 @@ rules of decent behavior in both communities are pretty much the same).
|
|||||||
|
|
||||||
GitHub Issues are **one** place for discussing Calamares if there are concrete
|
GitHub Issues are **one** place for discussing Calamares if there are concrete
|
||||||
problems or a new feature to discuss.
|
problems or a new feature to discuss.
|
||||||
|
Issues are not a help channel.
|
||||||
|
Visit Matrix for help with configuration or compilation.
|
||||||
|
|
||||||
Regular Calamares development chit-chat happens in a [Matrix](https://matrix.org/)
|
Regular Calamares development chit-chat happens in a [Matrix](https://matrix.org/)
|
||||||
room, `#calamares:kde.org`. The conversation is bridged with IRC
|
room, `#calamares:kde.org`. Responsiveness is best during the day
|
||||||
on [Libera.Chat](https://libera.chat/).
|
in Europe, but feel free to idle.
|
||||||
Responsiveness is best during the day
|
|
||||||
in Europe, but feel free to idle. If you use IRC, **DO NOT** ask-and-leave. Keep
|
|
||||||
that chat window open because it can easily take a few hours for
|
|
||||||
someone to notice a message.
|
|
||||||
Matrix is persistent, and we'll see your message eventually.
|
Matrix is persistent, and we'll see your message eventually.
|
||||||
|
|
||||||
|
**Note:** You need an account to access Matrix. It doesn't have to be a KDE account,
|
||||||
|
it can be on any Matrix homeserver.
|
||||||
|
|
||||||
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org)
|
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org)
|
||||||
* [![Chat on IRC](https://img.shields.io/badge/IRC-Libera.Chat%20%23calamares-green)](https://kiwiirc.com/client/irc.libera.chat/#calamares)
|
|
||||||
|
|
||||||
|
|
||||||
## General Guidelines
|
## General Guidelines
|
||||||
@ -57,7 +57,7 @@ stay that way.
|
|||||||
|
|
||||||
If you are writing documentation, use *en_US* spelling.
|
If you are writing documentation, use *en_US* spelling.
|
||||||
|
|
||||||
If you are doing cool stuff, let us know (on IRC or through issues).
|
If you are doing cool stuff, let us know (on Matrix or through issues).
|
||||||
|
|
||||||
**Do** fork Calamares to try new things, **don't** keep your fork to
|
**Do** fork Calamares to try new things, **don't** keep your fork to
|
||||||
yourself, **do** upstream things as much as you can. When you make cool
|
yourself, **do** upstream things as much as you can. When you make cool
|
||||||
@ -67,6 +67,49 @@ distributions than your own. So keep other folk in mind. There is
|
|||||||
also the [extensions](https://github.com/calamares/calamares-extensions)
|
also the [extensions](https://github.com/calamares/calamares-extensions)
|
||||||
repository for somewhat-more-specialized modules and examples.
|
repository for somewhat-more-specialized modules and examples.
|
||||||
|
|
||||||
|
### Commit Messages
|
||||||
|
|
||||||
|
Please try to use `[module] description` as the first line of a commit
|
||||||
|
message. Follow regular git commit-message recommendations: write what
|
||||||
|
and why -- especially the **why** for a change. When modifying a module
|
||||||
|
under `src/modules/`, write the name of the module, e.g. this made-up example:
|
||||||
|
|
||||||
|
```
|
||||||
|
[packages] Enable dnf5 as package-manager
|
||||||
|
|
||||||
|
DNF version 5 prefers the name 'dnf5' to avoid confusion with
|
||||||
|
older DNF, even when a compatibility name 'dnf' is available.
|
||||||
|
```
|
||||||
|
|
||||||
|
It's OK to list multiple modules; don't bother listing a module
|
||||||
|
and its QML variant separately.
|
||||||
|
|
||||||
|
Use `[libcalamares]`, `[libcalamaresui]` and `[calamares]` for changes
|
||||||
|
in those directories as appropriate.
|
||||||
|
|
||||||
|
There are various exceptions, and metadata files follow other conventions.
|
||||||
|
When in doubt, use `git log` to see what kind of **previous** commit messages
|
||||||
|
have been used for a given file.
|
||||||
|
|
||||||
|
### Attribution
|
||||||
|
|
||||||
|
Remember that your git commit contains your git username. This becomes part
|
||||||
|
of the public information in the Calamares repository. There is no way
|
||||||
|
to change this later.
|
||||||
|
|
||||||
|
When you contribute a PR, feel free to add a few lines in the `CHANGES`
|
||||||
|
file, which describes each release. Just add them to the section
|
||||||
|
for the next release, and it can be sorted out when the PR is merged.
|
||||||
|
Remember to add your preferred name in the list of contributors for
|
||||||
|
the release -- names are sorted alphabetically and case-insensitive.
|
||||||
|
|
||||||
|
If you don't add anything to `CHANGES`, don't worry, something will
|
||||||
|
probably be added later in a `Changes: credits` commit.
|
||||||
|
|
||||||
|
> Please do **not** update the `AUTHORS` file. This is done automatically,
|
||||||
|
> but irregularly, based on the git usernames in commits (and some social
|
||||||
|
> knowledge about Calamares contributors).
|
||||||
|
|
||||||
|
|
||||||
## Building Calamares
|
## Building Calamares
|
||||||
|
|
||||||
@ -74,26 +117,92 @@ Up to date
|
|||||||
[building-Calamares](https://github.com/calamares/calamares/wiki/Develop-Guide)
|
[building-Calamares](https://github.com/calamares/calamares/wiki/Develop-Guide)
|
||||||
instructions are on the wiki.
|
instructions are on the wiki.
|
||||||
|
|
||||||
### Dependencies
|
### Simple Build in Docker
|
||||||
|
|
||||||
|
You may have success with the Docker images that the CI system uses.
|
||||||
|
Pick one (or more) of these images which are also used in CI:
|
||||||
|
|
||||||
|
- `docker pull docker://opensuse/tumbleweed`
|
||||||
|
- `docker pull kdeneon/plasma:user`
|
||||||
|
- `docker pull fedora:40`
|
||||||
|
|
||||||
|
See the `nightly-*.yml` files in directory `.github/workflows/` for
|
||||||
|
the full list of Docker images that are used in CI.
|
||||||
|
|
||||||
|
Then start a container with the right image, from the root of Calamares
|
||||||
|
source checkout. Start with this command and substitute `opensuse/tumbleweed`
|
||||||
|
or `kdeneon/plasma:user` for the `$IMAGE` part.
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -ti \
|
||||||
|
--tmpfs /build:rw,exec \
|
||||||
|
--user 0:0 \
|
||||||
|
-e DISPLAY=:0 \
|
||||||
|
-v /tmp/.X11-unix:/tmp/.X11-unix \
|
||||||
|
-v .:/src \
|
||||||
|
$IMAGE \
|
||||||
|
bash
|
||||||
|
```
|
||||||
|
|
||||||
|
This starts a container with the chosen image with a temporary build
|
||||||
|
directory in `/build` and the Calamaressources mounted as `/src`.
|
||||||
|
|
||||||
|
Run the script to install dependencies: you could use `deploycala.py`
|
||||||
|
or one of the shell scripts in `ci/` to install the right
|
||||||
|
dependencies for the image (in this example, for openSUSE and Qt6).
|
||||||
|
- `cd /src`
|
||||||
|
- `./ci/deps-opensuse-qt6.sh`
|
||||||
|
|
||||||
|
Then run CMake (add any CMake options you like at the end) and ninja.
|
||||||
|
- `cmake -S /src -B /build -G Ninja`
|
||||||
|
- `ninja -C /build`
|
||||||
|
|
||||||
|
There is a script `ci/build.sh` that does the CMake an ninja steps.
|
||||||
|
- If you set `CMAKE_ARGS` in the environment those extra CMake options are used.
|
||||||
|
- If you add an argument to the script command which names a workflow
|
||||||
|
(e.g. "nightly-opensuse-qt6") then `CMAKE_ARGS` are extracted from that
|
||||||
|
workflow and used for the build.
|
||||||
|
|
||||||
|
### Running in Docker
|
||||||
|
|
||||||
|
To run Calamares inside the container, or e.g. `loadmodule` to test
|
||||||
|
individual modules, you may need to configure X authentication; a
|
||||||
|
simple and insecure way of doing that is to run `xhost +` in the host
|
||||||
|
environment of the Docker containers.
|
||||||
|
|
||||||
|
To re-use a container (e.g. after exiting it and putting Calamares
|
||||||
|
development away for the night), (re)start the container and connect
|
||||||
|
a shell to it, to continue where you left off. Here, (re)starting
|
||||||
|
a container called *opensuse-qt6*:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker container start opensuse-qt6
|
||||||
|
docker container exec -ti opensuse-qt6 bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependencies for Calamares 3.3
|
||||||
|
|
||||||
|
> The dependencies for Calamares 3.3 reflect "resonably current"
|
||||||
|
> software as of September 2023. For Calamares 3.2 dependencies,
|
||||||
|
> which are 2017-era, see the `CONTRIBUTING` file in that branch.
|
||||||
|
|
||||||
Main:
|
Main:
|
||||||
* Compiler with C++17 support: GCC >= 7 or Clang >= 5
|
* Compiler with C++17 support
|
||||||
* CMake >= 3.3
|
* CMake >= 3.16
|
||||||
* Qt >= 5.9
|
|
||||||
* yaml-cpp >= 0.5.1
|
* yaml-cpp >= 0.5.1
|
||||||
* Python >= 3.3 (required for some modules)
|
* Qt >= 5.15 or Qt >= 6.5
|
||||||
* Boost.Python >= 1.55.0 (required for some modules)
|
* KDE Frameworks KCoreAddons >= 5.78
|
||||||
* KDE extra-cmake-modules >= 5.18 (recommended; required for some modules;
|
* KDE extra-cmake-modules >= 5.78 (recommended; required for some modules;
|
||||||
required for some tests)
|
required for some tests)
|
||||||
* KDE Frameworks KCoreAddons (>= 5.58 recommended)
|
* Python >= 3.6 (required for some modules)
|
||||||
* PythonQt (optional, deprecated)
|
* Boost.Python >= 1.72.0 (required for some modules if WITH_PYBIND11 is OFF)
|
||||||
|
|
||||||
Individual modules may have their own requirements;
|
Individual modules may have their own requirements;
|
||||||
these are listed in CMake output.
|
these are listed in CMake output.
|
||||||
Particular requirements (not complete):
|
Particular requirements (not complete):
|
||||||
|
|
||||||
* *fsresizer* KPMCore >= 3.3 (>= 4.2 recommended)
|
* *fsresizer* KPMCore >= 20.04
|
||||||
* *partition* KPMCore >= 3.3 (>= 4.2 recommended)
|
* *partition* KPMCore >= 20.04
|
||||||
* *users* LibPWQuality (optional)
|
* *users* LibPWQuality (optional)
|
||||||
|
|
||||||
|
|
||||||
@ -109,6 +218,41 @@ Calamares translations are done on Transifex.
|
|||||||
The [translator's guide](https://github.com/calamares/calamares/wiki/Translate-Guide)
|
The [translator's guide](https://github.com/calamares/calamares/wiki/Translate-Guide)
|
||||||
on the wiki explains how to get involved there.
|
on the wiki explains how to get involved there.
|
||||||
|
|
||||||
|
### Using Transifex
|
||||||
|
|
||||||
|
> This section is copied from the wiki. Please read the wiki for more details.
|
||||||
|
|
||||||
|
Calamares uses [Transifex](https://www.transifex.com/) as its translation
|
||||||
|
inrfastructure.
|
||||||
|
The [project overview](https://www.transifex.com/calamares/calamares/) for Calamares
|
||||||
|
shows which languages exist and how translated they are.
|
||||||
|
Translations are (semi-)regularly updated from the *calamares* (development)
|
||||||
|
branch of Calamares and sent to Transifex; updated translations are
|
||||||
|
imported into the same *calamares* branch.
|
||||||
|
|
||||||
|
This means that stable releases don't get translation updates --
|
||||||
|
I have not thought of a good way to do that with one Calamares
|
||||||
|
project in Transifex.
|
||||||
|
|
||||||
|
Internally, the program uses **both** Qt translations and GNU
|
||||||
|
gettext. This is invisible for the translator, but it does mean
|
||||||
|
that the same string can show up in two different Calamares string collections.
|
||||||
|
|
||||||
|
### Using Pull Requests
|
||||||
|
|
||||||
|
> Please avoid using PRs to update translations if you can.
|
||||||
|
> They **can** be merged back to Transifex, but it's somewhat
|
||||||
|
> annoying to do so. You can merge your updated translations files
|
||||||
|
> (the `.ts` files) to Transifex as described in this section.
|
||||||
|
|
||||||
|
- Log in to Transifex
|
||||||
|
- Select the language for upload (e.g. Arabic)
|
||||||
|
- Click the resource to update (e.g. *Calamares* which is the one for the
|
||||||
|
bulk of the strings from the program itself, stored as
|
||||||
|
`lang/calamares_ar.ts` in the repository)
|
||||||
|
- Click *Upload file* and pick the right `.ts` file
|
||||||
|
- Click the *Translate* button to double-check the uploaded translations.
|
||||||
|
|
||||||
|
|
||||||
## Testing Calamares
|
## Testing Calamares
|
||||||
|
|
||||||
|
@ -46,20 +46,31 @@ macro(accumulate_deps outvar target namespace)
|
|||||||
endforeach()
|
endforeach()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
# Qt5 infrastructure for translations is required
|
set(Calamares_WITH_QT6 @WITH_QT6@)
|
||||||
set(qt5_required Core Widgets LinguistTools)
|
if(Calamares_WITH_QT6)
|
||||||
accumulate_deps(qt5_required Calamares::calamares Qt5::)
|
set(qtname "Qt6")
|
||||||
accumulate_deps(qt5_required Calamares::calamaresui Qt5::)
|
set(kfname "kf6")
|
||||||
find_package(Qt5 CONFIG REQUIRED ${qt5_required})
|
message(STATUS "Calamares was built with Qt6 and KDE Frameworks 6")
|
||||||
|
else()
|
||||||
|
set(qtname "Qt5")
|
||||||
|
set(kfname "kf5")
|
||||||
|
message(STATUS "Calamares was built with Qt5 and KDE Frameworks 5 (legacy)")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(kf5_required "")
|
# Qt infrastructure for translations is required
|
||||||
accumulate_deps(kf5_required Calamares::calamares KF5::)
|
set(qt_required Core Widgets LinguistTools)
|
||||||
accumulate_deps(kf5_required Calamares::calamaresui KF5::)
|
accumulate_deps(qt_required Calamares::calamares ${qtname}::)
|
||||||
if(kf5_required)
|
accumulate_deps(qt_required Calamares::calamaresui ${qtname}::)
|
||||||
|
find_package(${qtname} CONFIG REQUIRED ${qt_required})
|
||||||
|
|
||||||
|
set(kf_required "")
|
||||||
|
accumulate_deps(kf_required Calamares::calamares ${kfname}::)
|
||||||
|
accumulate_deps(kf_required Calamares::calamaresui ${kfname}::)
|
||||||
|
if(kf_required)
|
||||||
find_package(ECM ${ECM_VERSION} NO_MODULE)
|
find_package(ECM ${ECM_VERSION} NO_MODULE)
|
||||||
if( ECM_FOUND )
|
if( ECM_FOUND )
|
||||||
list(INSERT CMAKE_MODULE_PATH 0 ${ECM_MODULE_PATH})
|
list(INSERT CMAKE_MODULE_PATH 0 ${ECM_MODULE_PATH})
|
||||||
find_package(KF5 REQUIRED COMPONENTS ${kf5_required})
|
find_package(${kfname} REQUIRED COMPONENTS ${kf_required})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -87,5 +98,7 @@ include(CalamaresAddPlugin)
|
|||||||
# This list should match the one in libcalamares/CalamaresConfig.h,
|
# This list should match the one in libcalamares/CalamaresConfig.h,
|
||||||
# which is the C++-language side of the same configuration.
|
# which is the C++-language side of the same configuration.
|
||||||
set(Calamares_WITH_PYTHON @WITH_PYTHON@)
|
set(Calamares_WITH_PYTHON @WITH_PYTHON@)
|
||||||
set(Calamares_WITH_PYTHONQT @WITH_PYTHONQT@)
|
set(Calamares_WITH_PYBIND11 @WITH_PYBIND11@)
|
||||||
|
set(Calamares_WITH_BOOST_PYTHON @WITH_BOOST_PYTHON@)
|
||||||
set(Calamares_WITH_QML @WITH_QML@)
|
set(Calamares_WITH_QML @WITH_QML@)
|
||||||
|
set(Calamares_WITH_QT6 @WITH_QT6@)
|
||||||
|
@ -1,488 +0,0 @@
|
|||||||
|
|
||||||
The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.
|
|
||||||
|
|
||||||
You may use, distribute and copy the KD Tools Library under the terms of
|
|
||||||
GNU Library General Public License version 2, which is displayed below.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
[This is the first released version of the library GPL. It is
|
|
||||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
Licenses are intended to guarantee your freedom to share and change
|
|
||||||
free software--to make sure the software is free for all its users.
|
|
||||||
|
|
||||||
This license, the Library General Public License, applies to some
|
|
||||||
specially designated Free Software Foundation software, and to any
|
|
||||||
other libraries whose authors decide to use it. You can use it for
|
|
||||||
your libraries, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if
|
|
||||||
you distribute copies of the library, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of the library, whether gratis
|
|
||||||
or for a fee, you must give the recipients all the rights that we gave
|
|
||||||
you. You must make sure that they, too, receive or can get the source
|
|
||||||
code. If you link a program with the library, you must provide
|
|
||||||
complete object files to the recipients so that they can relink them
|
|
||||||
with the library, after making changes to the library and recompiling
|
|
||||||
it. And you must show them these terms so they know their rights.
|
|
||||||
|
|
||||||
Our method of protecting your rights has two steps: (1) copyright
|
|
||||||
the library, and (2) offer you this license which gives you legal
|
|
||||||
permission to copy, distribute and/or modify the library.
|
|
||||||
|
|
||||||
Also, for each distributor's protection, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
library. If the library is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original
|
|
||||||
version, so that any problems introduced by others will not reflect on
|
|
||||||
the original authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that companies distributing free
|
|
||||||
software will individually obtain patent licenses, thus in effect
|
|
||||||
transforming the program into proprietary software. To prevent this,
|
|
||||||
we have made it clear that any patent must be licensed for everyone's
|
|
||||||
free use or not licensed at all.
|
|
||||||
|
|
||||||
Most GNU software, including some libraries, is covered by the ordinary
|
|
||||||
GNU General Public License, which was designed for utility programs. This
|
|
||||||
license, the GNU Library General Public License, applies to certain
|
|
||||||
designated libraries. This license is quite different from the ordinary
|
|
||||||
one; be sure to read it in full, and don't assume that anything in it is
|
|
||||||
the same as in the ordinary license.
|
|
||||||
|
|
||||||
The reason we have a separate public license for some libraries is that
|
|
||||||
they blur the distinction we usually make between modifying or adding to a
|
|
||||||
program and simply using it. Linking a program with a library, without
|
|
||||||
changing the library, is in some sense simply using the library, and is
|
|
||||||
analogous to running a utility program or application program. However, in
|
|
||||||
a textual and legal sense, the linked executable is a combined work, a
|
|
||||||
derivative of the original library, and the ordinary General Public License
|
|
||||||
treats it as such.
|
|
||||||
|
|
||||||
Because of this blurred distinction, using the ordinary General
|
|
||||||
Public License for libraries did not effectively promote software
|
|
||||||
sharing, because most developers did not use the libraries. We
|
|
||||||
concluded that weaker conditions might promote sharing better.
|
|
||||||
|
|
||||||
However, unrestricted linking of non-free programs would deprive the
|
|
||||||
users of those programs of all benefit from the free status of the
|
|
||||||
libraries themselves. This Library General Public License is intended to
|
|
||||||
permit developers of non-free programs to use free libraries, while
|
|
||||||
preserving your freedom as a user of such programs to change the free
|
|
||||||
libraries that are incorporated in them. (We have not seen how to achieve
|
|
||||||
this as regards changes in header files, but we have achieved it as regards
|
|
||||||
changes in the actual functions of the Library.) The hope is that this
|
|
||||||
will lead to faster development of free libraries.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow. Pay close attention to the difference between a
|
|
||||||
"work based on the library" and a "work that uses the library". The
|
|
||||||
former contains code derived from the library, while the latter only
|
|
||||||
works together with the library.
|
|
||||||
|
|
||||||
Note that it is possible for a library to be covered by the ordinary
|
|
||||||
General Public License rather than by this special one.
|
|
||||||
|
|
||||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License Agreement applies to any software library which
|
|
||||||
contains a notice placed by the copyright holder or other authorized
|
|
||||||
party saying it may be distributed under the terms of this Library
|
|
||||||
General Public License (also called "this License"). Each licensee is
|
|
||||||
addressed as "you".
|
|
||||||
|
|
||||||
A "library" means a collection of software functions and/or data
|
|
||||||
prepared so as to be conveniently linked with application programs
|
|
||||||
(which use some of those functions and data) to form executables.
|
|
||||||
|
|
||||||
The "Library", below, refers to any such software library or work
|
|
||||||
which has been distributed under these terms. A "work based on the
|
|
||||||
Library" means either the Library or any derivative work under
|
|
||||||
copyright law: that is to say, a work containing the Library or a
|
|
||||||
portion of it, either verbatim or with modifications and/or translated
|
|
||||||
straightforwardly into another language. (Hereinafter, translation is
|
|
||||||
included without limitation in the term "modification".)
|
|
||||||
|
|
||||||
"Source code" for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For a library, complete source code means
|
|
||||||
all the source code for all modules it contains, plus any associated
|
|
||||||
interface definition files, plus the scripts used to control compilation
|
|
||||||
and installation of the library.
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running a program using the Library is not restricted, and output from
|
|
||||||
such a program is covered only if its contents constitute a work based
|
|
||||||
on the Library (independent of the use of the Library in a tool for
|
|
||||||
writing it). Whether that is true depends on what the Library does
|
|
||||||
and what the program that uses the Library does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Library's
|
|
||||||
complete source code as you receive it, in any medium, provided that
|
|
||||||
you conspicuously and appropriately publish on each copy an
|
|
||||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
|
||||||
all the notices that refer to this License and to the absence of any
|
|
||||||
warranty; and distribute a copy of this License along with the
|
|
||||||
Library.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy,
|
|
||||||
and you may at your option offer warranty protection in exchange for a
|
|
||||||
fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Library or any portion
|
|
||||||
of it, thus forming a work based on the Library, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The modified work must itself be a software library.
|
|
||||||
|
|
||||||
b) You must cause the files modified to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
c) You must cause the whole of the work to be licensed at no
|
|
||||||
charge to all third parties under the terms of this License.
|
|
||||||
|
|
||||||
d) If a facility in the modified Library refers to a function or a
|
|
||||||
table of data to be supplied by an application program that uses
|
|
||||||
the facility, other than as an argument passed when the facility
|
|
||||||
is invoked, then you must make a good faith effort to ensure that,
|
|
||||||
in the event an application does not supply such function or
|
|
||||||
table, the facility still operates, and performs whatever part of
|
|
||||||
its purpose remains meaningful.
|
|
||||||
|
|
||||||
(For example, a function in a library to compute square roots has
|
|
||||||
a purpose that is entirely well-defined independent of the
|
|
||||||
application. Therefore, Subsection 2d requires that any
|
|
||||||
application-supplied function or table used by this function must
|
|
||||||
be optional: if the application does not supply it, the square
|
|
||||||
root function must still compute square roots.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Library,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Library, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote
|
|
||||||
it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Library.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Library
|
|
||||||
with the Library (or with a work based on the Library) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
|
||||||
License instead of this License to a given copy of the Library. To do
|
|
||||||
this, you must alter all the notices that refer to this License, so
|
|
||||||
that they refer to the ordinary GNU General Public License, version 2,
|
|
||||||
instead of to this License. (If a newer version than version 2 of the
|
|
||||||
ordinary GNU General Public License has appeared, then you can specify
|
|
||||||
that version instead if you wish.) Do not make any other change in
|
|
||||||
these notices.
|
|
||||||
|
|
||||||
Once this change is made in a given copy, it is irreversible for
|
|
||||||
that copy, so the ordinary GNU General Public License applies to all
|
|
||||||
subsequent copies and derivative works made from that copy.
|
|
||||||
|
|
||||||
This option is useful when you wish to copy part of the code of
|
|
||||||
the Library into a program that is not a library.
|
|
||||||
|
|
||||||
4. You may copy and distribute the Library (or a portion or
|
|
||||||
derivative of it, under Section 2) in object code or executable form
|
|
||||||
under the terms of Sections 1 and 2 above provided that you accompany
|
|
||||||
it with the complete corresponding machine-readable source code, which
|
|
||||||
must be distributed under the terms of Sections 1 and 2 above on a
|
|
||||||
medium customarily used for software interchange.
|
|
||||||
|
|
||||||
If distribution of object code is made by offering access to copy
|
|
||||||
from a designated place, then offering equivalent access to copy the
|
|
||||||
source code from the same place satisfies the requirement to
|
|
||||||
distribute the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
5. A program that contains no derivative of any portion of the
|
|
||||||
Library, but is designed to work with the Library by being compiled or
|
|
||||||
linked with it, is called a "work that uses the Library". Such a
|
|
||||||
work, in isolation, is not a derivative work of the Library, and
|
|
||||||
therefore falls outside the scope of this License.
|
|
||||||
|
|
||||||
However, linking a "work that uses the Library" with the Library
|
|
||||||
creates an executable that is a derivative of the Library (because it
|
|
||||||
contains portions of the Library), rather than a "work that uses the
|
|
||||||
library". The executable is therefore covered by this License.
|
|
||||||
Section 6 states terms for distribution of such executables.
|
|
||||||
|
|
||||||
When a "work that uses the Library" uses material from a header file
|
|
||||||
that is part of the Library, the object code for the work may be a
|
|
||||||
derivative work of the Library even though the source code is not.
|
|
||||||
Whether this is true is especially significant if the work can be
|
|
||||||
linked without the Library, or if the work is itself a library. The
|
|
||||||
threshold for this to be true is not precisely defined by law.
|
|
||||||
|
|
||||||
If such an object file uses only numerical parameters, data
|
|
||||||
structure layouts and accessors, and small macros and small inline
|
|
||||||
functions (ten lines or less in length), then the use of the object
|
|
||||||
file is unrestricted, regardless of whether it is legally a derivative
|
|
||||||
work. (Executables containing this object code plus portions of the
|
|
||||||
Library will still fall under Section 6.)
|
|
||||||
|
|
||||||
Otherwise, if the work is a derivative of the Library, you may
|
|
||||||
distribute the object code for the work under the terms of Section 6.
|
|
||||||
Any executables containing that work also fall under Section 6,
|
|
||||||
whether or not they are linked directly with the Library itself.
|
|
||||||
|
|
||||||
6. As an exception to the Sections above, you may also compile or
|
|
||||||
link a "work that uses the Library" with the Library to produce a
|
|
||||||
work containing portions of the Library, and distribute that work
|
|
||||||
under terms of your choice, provided that the terms permit
|
|
||||||
modification of the work for the customer's own use and reverse
|
|
||||||
engineering for debugging such modifications.
|
|
||||||
|
|
||||||
You must give prominent notice with each copy of the work that the
|
|
||||||
Library is used in it and that the Library and its use are covered by
|
|
||||||
this License. You must supply a copy of this License. If the work
|
|
||||||
during execution displays copyright notices, you must include the
|
|
||||||
copyright notice for the Library among them, as well as a reference
|
|
||||||
directing the user to the copy of this License. Also, you must do one
|
|
||||||
of these things:
|
|
||||||
|
|
||||||
a) Accompany the work with the complete corresponding
|
|
||||||
machine-readable source code for the Library including whatever
|
|
||||||
changes were used in the work (which must be distributed under
|
|
||||||
Sections 1 and 2 above); and, if the work is an executable linked
|
|
||||||
with the Library, with the complete machine-readable "work that
|
|
||||||
uses the Library", as object code and/or source code, so that the
|
|
||||||
user can modify the Library and then relink to produce a modified
|
|
||||||
executable containing the modified Library. (It is understood
|
|
||||||
that the user who changes the contents of definitions files in the
|
|
||||||
Library will not necessarily be able to recompile the application
|
|
||||||
to use the modified definitions.)
|
|
||||||
|
|
||||||
b) Accompany the work with a written offer, valid for at
|
|
||||||
least three years, to give the same user the materials
|
|
||||||
specified in Subsection 6a, above, for a charge no more
|
|
||||||
than the cost of performing this distribution.
|
|
||||||
|
|
||||||
c) If distribution of the work is made by offering access to copy
|
|
||||||
from a designated place, offer equivalent access to copy the above
|
|
||||||
specified materials from the same place.
|
|
||||||
|
|
||||||
d) Verify that the user has already received a copy of these
|
|
||||||
materials or that you have already sent this user a copy.
|
|
||||||
|
|
||||||
For an executable, the required form of the "work that uses the
|
|
||||||
Library" must include any data and utility programs needed for
|
|
||||||
reproducing the executable from it. However, as a special exception,
|
|
||||||
the source code distributed need not include anything that is normally
|
|
||||||
distributed (in either source or binary form) with the major
|
|
||||||
components (compiler, kernel, and so on) of the operating system on
|
|
||||||
which the executable runs, unless that component itself accompanies
|
|
||||||
the executable.
|
|
||||||
|
|
||||||
It may happen that this requirement contradicts the license
|
|
||||||
restrictions of other proprietary libraries that do not normally
|
|
||||||
accompany the operating system. Such a contradiction means you cannot
|
|
||||||
use both them and the Library together in an executable that you
|
|
||||||
distribute.
|
|
||||||
|
|
||||||
7. You may place library facilities that are a work based on the
|
|
||||||
Library side-by-side in a single library together with other library
|
|
||||||
facilities not covered by this License, and distribute such a combined
|
|
||||||
library, provided that the separate distribution of the work based on
|
|
||||||
the Library and of the other library facilities is otherwise
|
|
||||||
permitted, and provided that you do these two things:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work
|
|
||||||
based on the Library, uncombined with any other library
|
|
||||||
facilities. This must be distributed under the terms of the
|
|
||||||
Sections above.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library of the fact
|
|
||||||
that part of it is a work based on the Library, and explaining
|
|
||||||
where to find the accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
8. You may not copy, modify, sublicense, link with, or distribute
|
|
||||||
the Library except as expressly provided under this License. Any
|
|
||||||
attempt otherwise to copy, modify, sublicense, link with, or
|
|
||||||
distribute the Library is void, and will automatically terminate your
|
|
||||||
rights under this License. However, parties who have received copies,
|
|
||||||
or rights, from you under this License will not have their licenses
|
|
||||||
terminated so long as such parties remain in full compliance.
|
|
||||||
|
|
||||||
9. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Library or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Library (or any work based on the
|
|
||||||
Library), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Library or works based on it.
|
|
||||||
|
|
||||||
10. Each time you redistribute the Library (or any work based on the
|
|
||||||
Library), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute, link with or modify the Library
|
|
||||||
subject to these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
11. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Library at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Library by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Library.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under any
|
|
||||||
particular circumstance, the balance of the section is intended to apply,
|
|
||||||
and the section as a whole is intended to apply in other circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
12. If the distribution and/or use of the Library is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Library under this License may add
|
|
||||||
an explicit geographical distribution limitation excluding those countries,
|
|
||||||
so that distribution is permitted only in or among countries not thus
|
|
||||||
excluded. In such case, this License incorporates the limitation as if
|
|
||||||
written in the body of this License.
|
|
||||||
|
|
||||||
13. The Free Software Foundation may publish revised and/or new
|
|
||||||
versions of the Library General Public License from time to time.
|
|
||||||
Such new versions will be similar in spirit to the present version,
|
|
||||||
but may differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Library
|
|
||||||
specifies a version number of this License which applies to it and
|
|
||||||
"any later version", you have the option of following the terms and
|
|
||||||
conditions either of that version or of any later version published by
|
|
||||||
the Free Software Foundation. If the Library does not specify a
|
|
||||||
license version number, you may choose any version ever published by
|
|
||||||
the Free Software Foundation.
|
|
||||||
|
|
||||||
14. If you wish to incorporate parts of the Library into other free
|
|
||||||
programs whose distribution conditions are incompatible with these,
|
|
||||||
write to the author to ask for permission. For software which is
|
|
||||||
copyrighted by the Free Software Foundation, write to the Free
|
|
||||||
Software Foundation; we sometimes make exceptions for this. Our
|
|
||||||
decision will be guided by the two goals of preserving the free status
|
|
||||||
of all derivatives of our free software and of promoting the sharing
|
|
||||||
and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
|
||||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
|
||||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
|
||||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
|
||||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
|
||||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
|
||||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
|
||||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
|
||||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
|
||||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
|
||||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
|
||||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
|
||||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
|
||||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
|
||||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|
||||||
DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Libraries
|
|
||||||
|
|
||||||
If you develop a new library, and you want it to be of the greatest
|
|
||||||
possible use to the public, we recommend making it free software that
|
|
||||||
everyone can redistribute and change. You can do so by permitting
|
|
||||||
redistribution under these terms (or, alternatively, under the terms of the
|
|
||||||
ordinary General Public License).
|
|
||||||
|
|
||||||
To apply these terms, attach the following notices to the library. It is
|
|
||||||
safest to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least the
|
|
||||||
"copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the library's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
|
||||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1990
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
That's all there is to it!
|
|
32
README.md
32
README.md
@ -7,26 +7,26 @@
|
|||||||
|
|
||||||
[![Current issue](https://img.shields.io/badge/issue-in_progress-FE9B48)](https://github.com/calamares/calamares/labels/hacking%3A%20in-progress)
|
[![Current issue](https://img.shields.io/badge/issue-in_progress-FE9B48)](https://github.com/calamares/calamares/labels/hacking%3A%20in-progress)
|
||||||
[![GitHub release](https://img.shields.io/github/release/calamares/calamares.svg)](https://github.com/calamares/calamares/releases)
|
[![GitHub release](https://img.shields.io/github/release/calamares/calamares.svg)](https://github.com/calamares/calamares/releases)
|
||||||
[![GitHub Build Status](https://img.shields.io/github/workflow/status/calamares/calamares/ci?label=GH%20build)](https://github.com/calamares/calamares/actions?query=workflow%3Aci)
|
[![GitHub Build Status](https://img.shields.io/github/actions/workflow/status/calamares/calamares/push.yml)](https://github.com/calamares/calamares/actions?query=workflow%3Aci)
|
||||||
[![GitHub license](https://img.shields.io/github/license/calamares/calamares.svg)](https://github.com/calamares/calamares/blob/calamares/LICENSES/GPL-3.0-or-later.txt)
|
[![GitHub license](https://img.shields.io/badge/license-Multiple-green)](https://github.com/calamares/calamares/tree/calamares/LICENSES)
|
||||||
|
|
||||||
|
|
||||||
| [Report a Bug](https://github.com/calamares/calamares/issues/new) | [Translate](https://www.transifex.com/projects/p/calamares/) | [Contribute](CONTRIBUTING.md) | [Matrix: #calamares:kde.org](https://webchat.kde.org/#/room/%23calamares:kde.org) | [IRC: Libera.Chat #calamares](https://kiwiirc.com/client/irc.libera.chat/#calamares) | [Wiki](https://github.com/calamares/calamares/wiki) |
|
| [Report a Bug](https://github.com/calamares/calamares/issues/new) | [Translate](https://app.transifex.com/calamares/calamares/) | [Contribute](CONTRIBUTING.md) | [Chat on Matrix: #calamares:kde.org](https://webchat.kde.org/#/room/%23calamares:kde.org) | [Wiki](https://github.com/calamares/calamares/wiki) |
|
||||||
|:--:|:--:|:--:|:--:|:--:|:--:|
|
|:--:|:--:|:--:|:--:|:--:|
|
||||||
|
|
||||||
|
|
||||||
> Calamares is a distribution-independent system installer, with an advanced partitioning
|
> Calamares is a distribution-independent system installer, with an advanced partitioning
|
||||||
> feature for both manual and automated partitioning operations. Calamares is designed to
|
> feature for both manual and automated partitioning operations. Calamares is designed to
|
||||||
> be customizable by distribution maintainers without need for cumbersome patching,
|
> be customizable by distribution maintainers without the need for cumbersome patching,
|
||||||
> thanks to third party branding and external modules support.
|
> thanks to third-party branding and external modules support.
|
||||||
|
|
||||||
## Target Audience
|
## Target Audience
|
||||||
|
|
||||||
Calamares is a Linux installer; users who install Linux on a computer will hopefully
|
Calamares is a Linux installer; users who install Linux on a computer will hopefully
|
||||||
use it just **once**, to install their Linux distribution. Calamares is not
|
use it just **once**, to install their Linux distribution. Calamares is not
|
||||||
a "ready to use" application: distributions apply a huge amount of customisation
|
a "ready to use" application: distributions apply a huge amount of customization
|
||||||
and configuration to Calamares, and the target audience for this repository
|
and configuration to Calamares, and the target audience for this repository
|
||||||
is those distributions, and the people who make those Linux distro's.
|
is those distributions, and the people who make those Linux distros.
|
||||||
|
|
||||||
Calamares has some [generic user documentation](https://calamares.io/docs/users-guide/)
|
Calamares has some [generic user documentation](https://calamares.io/docs/users-guide/)
|
||||||
for end-users, but most of what we have is for distro developers.
|
for end-users, but most of what we have is for distro developers.
|
||||||
@ -45,25 +45,23 @@ The dependencies are explained in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|||||||
## Contributing to Calamares
|
## Contributing to Calamares
|
||||||
|
|
||||||
Calamares welcomes PRs. New issues are welcome, too.
|
Calamares welcomes PRs. New issues are welcome, too.
|
||||||
There are both the Calamares **core** repository (this one),
|
There are both the Calamares **core** repository (this one)
|
||||||
and an **extensions** repository ([Calamares extensions](https://github.com/calamares/calamares-extensions)).
|
and an **extensions** repository ([Calamares extensions](https://github.com/calamares/calamares-extensions)).
|
||||||
|
|
||||||
Contributions to code, modules, documentation, the wiki and the website are all welcome.
|
Contributions to code, modules, documentation, the wiki, and the website are all welcome.
|
||||||
There is more information in the [CONTRIBUTING.md](CONTRIBUTING.md) file.
|
There is more information in the [CONTRIBUTING.md](CONTRIBUTING.md) file.
|
||||||
|
|
||||||
## Join the Conversation
|
## Join the Conversation
|
||||||
|
|
||||||
GitHub Issues are **one** place for discussing Calamares if there are concrete
|
GitHub Issues are **one** place for discussing Calamares if there are concrete
|
||||||
problems or a new feature to discuss.
|
problems or a new feature to discuss.
|
||||||
|
Issues are not a help channel.
|
||||||
|
Visit Matrix for help with configuration or compilation.
|
||||||
|
|
||||||
Regular Calamares development chit-chat happens in a [Matrix](https://matrix.org/)
|
Regular Calamares development chit-chat happens in a [Matrix](https://matrix.org/)
|
||||||
room, `#calamares:kde.org`. The conversation is bridged with IRC
|
room, `#calamares:kde.org`. Responsiveness is best during the day
|
||||||
on [Libera.Chat](https://libera.chat/).
|
in Europe, but feel free to idle.
|
||||||
Responsiveness is best during the day
|
|
||||||
in Europe, but feel free to idle. If you use IRC, **DO NOT** ask-and-leave. Keep
|
|
||||||
that chat window open because it can easily take a few hours for
|
|
||||||
someone to notice a message.
|
|
||||||
Matrix is persistent, and we'll see your message eventually.
|
Matrix is persistent, and we'll see your message eventually.
|
||||||
|
|
||||||
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org) (needs a Matrix account)
|
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org) (needs a Matrix account)
|
||||||
* [![Chat on IRC](https://img.shields.io/badge/IRC-Libera.Chat%20%23calamares-green)](https://kiwiirc.com/client/irc.libera.chat/#calamares) (IRC supports guest accounts)
|
|
||||||
|
@ -76,7 +76,7 @@ Follow the instructions printed by the release script.
|
|||||||
* Upload tarball and signature.
|
* Upload tarball and signature.
|
||||||
* Publish release article on `calamares.io`.
|
* Publish release article on `calamares.io`.
|
||||||
* Close associated milestone on GitHub if it's entirely done.
|
* Close associated milestone on GitHub if it's entirely done.
|
||||||
* Update topic on #calamares IRC channel.
|
* Update topic on `#calamares:kde.org` Matrix channel.
|
||||||
|
|
||||||
## (4) Post-Release
|
## (4) Post-Release
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
# * BUILD_CLANG set to `false` to avoid second build with clang
|
# * BUILD_CLANG set to `false` to avoid second build with clang
|
||||||
# * BUILD_ONLY set to `true` to break after building
|
# * BUILD_ONLY set to `true` to break after building
|
||||||
# * TEST_TARBALL set to 'false' to skip build-and-test phase after tarring
|
# * TEST_TARBALL set to 'false' to skip build-and-test phase after tarring
|
||||||
|
# * QT_VERSION set to nothing (uses default), 5 or 6
|
||||||
#
|
#
|
||||||
### END USAGE
|
### END USAGE
|
||||||
|
|
||||||
@ -70,11 +71,18 @@ while getopts "hBbPT" opt ; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
if $STRING_FREEZE ; then
|
if $STRING_FREEZE ; then
|
||||||
sh ci/txcheck.sh || { echo "! String freeze failed." ; exit 1 ; }
|
sh ci/txcheck.sh || { echo "! String freeze failed." ; exit 1 ; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Via environment, not command-line
|
||||||
|
case "$QT_VERSION" in
|
||||||
|
5) extra_cmake_args="-DWITH_QT6=OFF" ;;
|
||||||
|
6) extra_cmake_args="-DWITH_QT6=ON" ;;
|
||||||
|
"") extra_cmake_args="" ;;
|
||||||
|
*) echo "Invalid QT_VERSION environment '${QT_VERSION}'" ; exit 1 ; ;;
|
||||||
|
esac
|
||||||
|
|
||||||
### Setup
|
### Setup
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -86,13 +94,23 @@ KEY_ID="328D742D8807A435"
|
|||||||
rm -f CMakeLists.txt.gpg
|
rm -f CMakeLists.txt.gpg
|
||||||
gpg -s -u $KEY_ID CMakeLists.txt
|
gpg -s -u $KEY_ID CMakeLists.txt
|
||||||
|
|
||||||
|
### Get version number for this release
|
||||||
|
#
|
||||||
|
# Do this early, in a clean build-dir, since it doesn't cost much.
|
||||||
|
# Redirect stderr from CMake script mode, because the message()
|
||||||
|
# in CMakeLists.txt that prints the version, goes to stderr.
|
||||||
|
rm -rf "$BUILDDIR"
|
||||||
|
mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; }
|
||||||
|
V=$( cd "$BUILDDIR" && cmake -P ../CMakeLists.txt 2>&1 )
|
||||||
|
test -n "$V" || { echo "Could not obtain version in $BUILDDIR ." ; exit 1 ; }
|
||||||
|
|
||||||
### Build with default compiler
|
### Build with default compiler
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
if test "x$BUILD_DEFAULT" = "xtrue" ; then
|
if test "x$BUILD_DEFAULT" = "xtrue" ; then
|
||||||
rm -rf "$BUILDDIR"
|
rm -rf "$BUILDDIR"
|
||||||
mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; }
|
mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; }
|
||||||
( cd "$BUILDDIR" && cmake .. && make -j4 ) || { echo "Could not perform test-build in $BUILDDIR." ; exit 1 ; }
|
( cd "$BUILDDIR" && cmake .. $extra_cmake_args && make -j4 ) || { echo "Could not perform test-build in $BUILDDIR." ; exit 1 ; }
|
||||||
( cd "$BUILDDIR" && make test ) || { echo "Tests failed in $BUILDDIR ." ; exit 1 ; }
|
( cd "$BUILDDIR" && make test ) || { echo "Tests failed in $BUILDDIR ." ; exit 1 ; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -104,7 +122,7 @@ if test "x$BUILD_CLANG" = "xtrue" ; then
|
|||||||
# Do build again with clang
|
# Do build again with clang
|
||||||
rm -rf "$BUILDDIR"
|
rm -rf "$BUILDDIR"
|
||||||
mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; }
|
mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; }
|
||||||
( cd "$BUILDDIR" && CC=clang CXX=clang++ cmake .. && make -j4 ) || { echo "Could not perform test-build in $BUILDDIR." ; exit 1 ; }
|
( cd "$BUILDDIR" && CC=clang CXX=clang++ cmake .. $extra_cmake_args && make -j4 ) || { echo "Could not perform test-build in $BUILDDIR." ; exit 1 ; }
|
||||||
( cd "$BUILDDIR" && make test ) || { echo "Tests failed in $BUILDDIR (clang)." ; exit 1 ; }
|
( cd "$BUILDDIR" && make test ) || { echo "Tests failed in $BUILDDIR (clang)." ; exit 1 ; }
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -121,15 +139,9 @@ else
|
|||||||
# Presumably -B was given; just do the cmake part
|
# Presumably -B was given; just do the cmake part
|
||||||
rm -rf "$BUILDDIR"
|
rm -rf "$BUILDDIR"
|
||||||
mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; }
|
mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; }
|
||||||
( cd "$BUILDDIR" && cmake .. ) || { echo "Could not run cmake in $BUILDDIR ." ; exit 1 ; }
|
( cd "$BUILDDIR" && cmake .. $extra_cmake_args ) || { echo "Could not run cmake in $BUILDDIR ." ; exit 1 ; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
### Get version number for this release
|
|
||||||
#
|
|
||||||
#
|
|
||||||
V=$( cd "$BUILDDIR" && make show-version | grep ^CALAMARES_VERSION | sed s/^[A-Z_]*=// )
|
|
||||||
test -n "$V" || { echo "Could not obtain version in $BUILDDIR ." ; exit 1 ; }
|
|
||||||
|
|
||||||
### Create signed tag
|
### Create signed tag
|
||||||
#
|
#
|
||||||
# This is the signing key ID associated with the GitHub account adriaandegroot,
|
# This is the signing key ID associated with the GitHub account adriaandegroot,
|
||||||
|
92
ci/abicheck.sh
Executable file
92
ci/abicheck.sh
Executable file
@ -0,0 +1,92 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
#
|
||||||
|
# Compares the ABI of the current working tree with the ABI
|
||||||
|
# from a base-version. Uses libabigail for the actual comparison.
|
||||||
|
#
|
||||||
|
# To use the tool, just run the script. It will build Calamares at
|
||||||
|
# least once, maybe twice (if it needs the base-version ABI information
|
||||||
|
# and hasn't cached it).
|
||||||
|
|
||||||
|
# The build settings can be influenced via environment variables:
|
||||||
|
# * QT_VERSION set to nothing (uses default), 5 or 6
|
||||||
|
|
||||||
|
case "$QT_VERSION" in
|
||||||
|
5) extra_cmake_args="-DWITH_QT6=OFF" ;;
|
||||||
|
6) extra_cmake_args="-DWITH_QT6=ON" ;;
|
||||||
|
"") extra_cmake_args="" ;;
|
||||||
|
*) echo "Invalid QT_VERSION environment '${QT_VERSION}'" ; exit 1 ; ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# The base version can be a tag or git-hash; it will be checked-out
|
||||||
|
# in a worktree.
|
||||||
|
#
|
||||||
|
# Note that the hash here corresponds to v3.3.3 . That was a release
|
||||||
|
# with hidden visibility enabled and a first step towards more-stable ABI.
|
||||||
|
BASE_VERSION=8741c7ec1a94ee5f27e98ef3663d1a8f4738d2c2
|
||||||
|
|
||||||
|
### Build a tree and cache the ABI info into ci/
|
||||||
|
#
|
||||||
|
#
|
||||||
|
do_build() {
|
||||||
|
LABEL=$1
|
||||||
|
SOURCE_DIR=$2
|
||||||
|
|
||||||
|
BUILD_DIR=build-abi-$LABEL
|
||||||
|
rm -rf $BUILD_DIR
|
||||||
|
rm -f $BUILD_DIR.log
|
||||||
|
|
||||||
|
echo "# Running CMake for $LABEL"
|
||||||
|
cmake -S $SOURCE_DIR -B $BUILD_DIR -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-Og -g -gdwarf" -DCMAKE_C_FLAGS="-Og -g -gdwarf" $extra_cmake_args > /dev/null 2>&1
|
||||||
|
test -f $BUILD_DIR/Makefile || { echo "! failed to CMake $LABEL" ; exit 1 ; }
|
||||||
|
|
||||||
|
echo "# Running make for $LABEL"
|
||||||
|
# Two targets make knows about at top-level
|
||||||
|
if make -C $BUILD_DIR -j12 calamares calamaresui > $BUILD_DIR.log 2>&1
|
||||||
|
then
|
||||||
|
ls -1 $BUILD_DIR/libcalamares*.so.*
|
||||||
|
# Copy the un-versioned files; .so is a symlink to the just-built one
|
||||||
|
for lib in $BUILD_DIR/libcalamares*.so
|
||||||
|
do
|
||||||
|
cp $lib ci/`basename $lib`.$LABEL
|
||||||
|
done
|
||||||
|
rm -rf $BUILD_DIR $BUILD_DIR.log
|
||||||
|
echo "# .. build successful for $LABEL"
|
||||||
|
else
|
||||||
|
echo "! failed to build $LABEL"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
### Build current tree and get ABI info
|
||||||
|
#
|
||||||
|
#
|
||||||
|
do_build current .
|
||||||
|
|
||||||
|
### Build ABI base version
|
||||||
|
#
|
||||||
|
# We cache this to save on some build time, if we are chasing a
|
||||||
|
# single branch from an unchanging base version.
|
||||||
|
#
|
||||||
|
if test -f ci/libcalamares.so.$BASE_VERSION
|
||||||
|
then
|
||||||
|
# The ABI version is cached, so we're good
|
||||||
|
:
|
||||||
|
else
|
||||||
|
git worktree remove --force tree-abi-$BASE_VERSION > /dev/null 2>&1
|
||||||
|
git worktree add tree-abi-$BASE_VERSION $BASE_VERSION > /dev/null 2>&1 || { echo "! could not create worktree for $BASE_VERSION" ; exit 1 ; }
|
||||||
|
do_build $BASE_VERSION tree-abi-$BASE_VERSION
|
||||||
|
git worktree remove --force tree-abi-$BASE_VERSION > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Compare & Report
|
||||||
|
#
|
||||||
|
# abidiff compares the Application Binary Interfaces (ABI) of two
|
||||||
|
# shared libraries in ELF format. It emits a meaningful report describing
|
||||||
|
# the differences between the two ABIs.
|
||||||
|
#
|
||||||
|
# -l prints only the leaf changes, leaving out explanations of why.
|
||||||
|
#
|
||||||
|
abidiff -l ci/libcalamares.so.$BASE_VERSION ci/libcalamares.so.current
|
@ -9,7 +9,7 @@ indent=spaces=4
|
|||||||
|
|
||||||
# Brackets
|
# Brackets
|
||||||
style=break
|
style=break
|
||||||
add-brackets
|
add-braces
|
||||||
|
|
||||||
# Spaces
|
# Spaces
|
||||||
pad-paren-in
|
pad-paren-in
|
||||||
|
59
ci/build.sh
Executable file
59
ci/build.sh
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
#
|
||||||
|
# Generic build. The build is driven by environment variables:
|
||||||
|
# - SRCDIR (e.g. /src)
|
||||||
|
# - BUILDDIR (e.g. /build)
|
||||||
|
# - CMAKE_ARGS (e.g. "-DWITH_QT6=ON -DCMAKE_BUILD_TYPE=Debug")
|
||||||
|
#
|
||||||
|
# If SRCDIR is not set, it is assumed to be the directory above
|
||||||
|
# wherever this script is being run from (this script is in ci/).
|
||||||
|
#
|
||||||
|
# If BUILDDIR is not set, and /build exists (e.g. in the recommended
|
||||||
|
# Docker setup) then /build is used.
|
||||||
|
#
|
||||||
|
# If CMAKE_ARGS is not set, but the script is given an argument
|
||||||
|
# that exists as a workflow (e.g. "nightly-opensuse-qt6" or
|
||||||
|
# "nightly-debian.yml") and yq is installed, then the CMAKE_ARGS
|
||||||
|
# are extracted from that workflow file.
|
||||||
|
#
|
||||||
|
# Summary, pick one:
|
||||||
|
# - set environment variables, run "build.sh"
|
||||||
|
# - set no variables, run "build.sh <workflow-name>"
|
||||||
|
|
||||||
|
if test -z "$SRCDIR" ; then
|
||||||
|
_d=$(dirname "$0" )
|
||||||
|
_d=$(dirname "$_d" )
|
||||||
|
test -f "$_d/CMakeLists.txt" && SRCDIR="$_d"
|
||||||
|
fi
|
||||||
|
if test -z "$BUILDDIR" ; then
|
||||||
|
test -d "/build" && BUILDDIR=/build
|
||||||
|
fi
|
||||||
|
if test -z "$CMAKE_ARGS" -a -n "$1" ; then
|
||||||
|
_d="$SRCDIR/.github/workflows/$1"
|
||||||
|
test -f "$_d" || _d="$SRCDIR/.github/workflows/$1.yml"
|
||||||
|
test -f "$_d" || { echo "! No workflow $1" ; exit 1 ; }
|
||||||
|
|
||||||
|
if test -x "$(which yq)" ; then
|
||||||
|
CMAKE_ARGS=$(yq ".env.CMAKE_ARGS" "$_d")
|
||||||
|
else
|
||||||
|
CMAKE_ARGS=$(python3 -c 'import yaml ; f=open("'$_d'","r"); print(yaml.safe_load(f)["env"]["CMAKE_ARGS"]);')
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sanity check
|
||||||
|
test -n "$BUILDDIR" || { echo "! \$BUILDDIR not set" ; exit 1 ; }
|
||||||
|
test -n "$SRCDIR" || { echo "! \$SRCDIR not set" ; exit 1 ; }
|
||||||
|
mkdir -p "$BUILDDIR"
|
||||||
|
test -f "$SRCDIR/CMakeLists.txt" || { echo "! Missing $SRCDIR/CMakeLists.txt" ; exit 1 ; }
|
||||||
|
|
||||||
|
BUILD_MESSAGE="No commit info"
|
||||||
|
test -n "$GIT_HASH" && BUILD_MESSAGE=$( git log -1 --abbrev-commit --pretty=oneline --no-decorate "$GIT_HASH" )
|
||||||
|
|
||||||
|
echo "::" ; echo ":: $BUILD_MESSAGE" ; echo "::"
|
||||||
|
|
||||||
|
cmake -S "$SRCDIR" -B "$BUILDDIR" -G Ninja $CMAKE_ARGS || exit 1
|
||||||
|
ninja -C "$BUILDDIR" || exit 1
|
||||||
|
ninja -C "$BUILDDIR" install || exit 1
|
||||||
|
|
||||||
|
echo "::" ; echo ":: $BUILD_MESSAGE" ; echo "::"
|
@ -4,12 +4,14 @@
|
|||||||
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
#
|
#
|
||||||
# Calls astyle with settings matching Calamares coding style
|
# Apply Calamares-style formatting to sources. Requires clang-format-15.
|
||||||
# Requires astyle >= 2.04 and clang-format-8 or later
|
|
||||||
#
|
#
|
||||||
# You can pass in directory names, in which case the files
|
# You can pass in directory names, in which case the files
|
||||||
# in that directory (NOT below it) are processed.
|
# in that directory (NOT below it) are processed.
|
||||||
#
|
#
|
||||||
|
# If the environment variable CLANG_FORMAT is set to a (full path) and
|
||||||
|
# that path is executable, it will be used if possible.
|
||||||
|
#
|
||||||
LANG=C
|
LANG=C
|
||||||
LC_ALL=C
|
LC_ALL=C
|
||||||
LC_NUMERIC=C
|
LC_NUMERIC=C
|
||||||
@ -21,10 +23,17 @@ test -d "$BASEDIR" || { echo "! Could not determine base for $0" ; exit 1 ; }
|
|||||||
test -d "$TOPDIR" || { echo "! Cound not determine top-level source dir" ; exit 1 ; }
|
test -d "$TOPDIR" || { echo "! Cound not determine top-level source dir" ; exit 1 ; }
|
||||||
test -f "$TOPDIR/.clang-format" || { echo "! No .clang-format support files in $TOPDIR" ; exit 1 ; }
|
test -f "$TOPDIR/.clang-format" || { echo "! No .clang-format support files in $TOPDIR" ; exit 1 ; }
|
||||||
|
|
||||||
AS=$( which astyle )
|
# Start with CLANG_FORMAT, if it is specified
|
||||||
|
CF_VERSIONS=""
|
||||||
# Allow specifying CF_VERSIONS outside already
|
if test -n "$CLANG_FORMAT" && test -x "$CLANG_FORMAT" ; then
|
||||||
CF_VERSIONS="$CF_VERSIONS clang-format13 clang-format-13 clang-format-13.0.1 clang-format12 clang-format-12 clang-format"
|
CF_VERSIONS="$CLANG_FORMAT"
|
||||||
|
fi
|
||||||
|
# And a bunch of other potential known versions of clang-format, newest first
|
||||||
|
CF_VERSIONS="$CF_VERSIONS clang-format-17"
|
||||||
|
CF_VERSIONS="$CF_VERSIONS clang-format-16 clang-format-16.0.6 "
|
||||||
|
CF_VERSIONS="$CF_VERSIONS clang-format15 clang-format-15 "
|
||||||
|
# Generic name of clang-format
|
||||||
|
CF_VERSIONS="$CF_VERSIONS clang-format"
|
||||||
for _cf in $CF_VERSIONS
|
for _cf in $CF_VERSIONS
|
||||||
do
|
do
|
||||||
# Not an error if this particular clang-format isn't found
|
# Not an error if this particular clang-format isn't found
|
||||||
@ -32,27 +41,30 @@ do
|
|||||||
test -n "$CF" && break
|
test -n "$CF" && break
|
||||||
done
|
done
|
||||||
|
|
||||||
test -n "$AS" || { echo "! No astyle found in PATH"; exit 1 ; }
|
|
||||||
test -n "$CF" || { echo "! No clang-format ($CF_VERSIONS) found in PATH"; exit 1 ; }
|
test -n "$CF" || { echo "! No clang-format ($CF_VERSIONS) found in PATH"; exit 1 ; }
|
||||||
test -x "$AS" || { echo "! $AS is not executable."; exit 1 ; }
|
|
||||||
test -x "$CF" || { echo "! $CF is not executable."; exit 1 ; }
|
test -x "$CF" || { echo "! $CF is not executable."; exit 1 ; }
|
||||||
|
|
||||||
### CLANG-FORMAT-WRANGLING
|
### CLANG-FORMAT-WRANGLING
|
||||||
#
|
#
|
||||||
# Version 7 and earlier doesn't understand all the options we would like
|
# Version 7 and earlier doesn't understand all the options we would like.
|
||||||
# Version 12 handles lambdas nicely, so use that.
|
# Version 12 handled lambdas nicely and was the norm for Calamares 3.2.
|
||||||
# Version 13 is also ok.
|
# Version 13 was also ok.
|
||||||
# Version 14 behaves differently with short-functions-in-class,
|
# Version 14 behaves differently with short-functions-in-class,
|
||||||
# spreading functions out that 13 keeps on one line. To avoid
|
# spreading functions out that 13 keeps on one line. To avoid
|
||||||
# ping-pong commits, forbid 14.
|
# ping-pong commits, forbid 14.
|
||||||
|
# Version 15 is available on recent-ish Ubuntus and FreeBSD, pick it.
|
||||||
|
# It also supports inserting braces, which is the one thing we kept
|
||||||
|
# astyle around for.
|
||||||
|
# Version 16 is available on openSUSE and is ok as well.
|
||||||
|
# Version 17 is available on FreeBSD and KaOS and is ok as well.
|
||||||
|
|
||||||
format_version=`"$CF" --version | tr -dc '[^.0-9]' | cut -d . -f 1`
|
format_version=`"$CF" --version | tr -dc '[^.0-9]' | cut -d . -f 1`
|
||||||
case "$format_version" in
|
case "$format_version" in
|
||||||
12|13 )
|
15|16|17 )
|
||||||
:
|
:
|
||||||
;;
|
;;
|
||||||
* )
|
* )
|
||||||
echo "! Clang-format version '$format_version' unsupported, versions 12 or 13 are ok."
|
echo "! Clang-format version '$format_version' unsupported, versions 15-17 are ok."
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -72,7 +84,6 @@ done
|
|||||||
style_some()
|
style_some()
|
||||||
{
|
{
|
||||||
if test -n "$*" ; then
|
if test -n "$*" ; then
|
||||||
$AS --options=$BASEDIR/astylerc --quiet "$@"
|
|
||||||
$CF -i -style=file "$@"
|
$CF -i -style=file "$@"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,6 @@ ERR_IMPORT, ERR_USAGE, ERR_FILE_NOT_FOUND, ERR_SYNTAX, ERR_INVALID = range(1,6)
|
|||||||
#
|
#
|
||||||
try:
|
try:
|
||||||
from jsonschema import validate, SchemaError, ValidationError
|
from jsonschema import validate, SchemaError, ValidationError
|
||||||
from jsonschema import draft7_format_checker
|
|
||||||
from yaml import safe_load, YAMLError
|
from yaml import safe_load, YAMLError
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
46
ci/deps-debian11.sh
Executable file
46
ci/deps-debian11.sh
Executable file
@ -0,0 +1,46 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
#
|
||||||
|
# Install dependencies for the nightly-debian (11) build
|
||||||
|
#
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install git-core jq curl ninja
|
||||||
|
apt-get -y install \
|
||||||
|
build-essential \
|
||||||
|
cmake \
|
||||||
|
extra-cmake-modules \
|
||||||
|
gettext \
|
||||||
|
libatasmart-dev \
|
||||||
|
libappstreamqt-dev \
|
||||||
|
libboost-python-dev \
|
||||||
|
libicu-dev \
|
||||||
|
libparted-dev \
|
||||||
|
libpolkit-qt5-1-dev \
|
||||||
|
libqt5svg5-dev \
|
||||||
|
libqt5webkit5-dev \
|
||||||
|
libyaml-cpp-dev \
|
||||||
|
ninja-build \
|
||||||
|
os-prober \
|
||||||
|
pkg-config \
|
||||||
|
python3-dev \
|
||||||
|
qtbase5-dev \
|
||||||
|
qtdeclarative5-dev \
|
||||||
|
qttools5-dev \
|
||||||
|
qttools5-dev-tools
|
||||||
|
# Same name as on KDE neon, different version
|
||||||
|
apt-get -y install libkpmcore-dev
|
||||||
|
# Additional dependencies (KF5, +)
|
||||||
|
apt-get -y install \
|
||||||
|
libkf5config-dev \
|
||||||
|
libkf5coreaddons-dev \
|
||||||
|
libkf5i18n-dev \
|
||||||
|
libkf5iconthemes-dev \
|
||||||
|
libkf5parts-dev \
|
||||||
|
libkf5service-dev \
|
||||||
|
libkf5solid-dev \
|
||||||
|
libkf5crash-dev \
|
||||||
|
libkf5package-dev \
|
||||||
|
libkf5plasma-dev \
|
||||||
|
libpwquality-dev \
|
||||||
|
libqt5webenginewidgets5 \
|
||||||
|
qtwebengine5-dev
|
||||||
|
true
|
13
ci/deps-endeavouros.sh
Executable file
13
ci/deps-endeavouros.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
#
|
||||||
|
# Install dependencies for building on EndeavourOS
|
||||||
|
#
|
||||||
|
# There is no docker image for EndeavoudOS, and the live ISO
|
||||||
|
# for Cassini Nova is KF5 / Qt5 based, but we can build there.
|
||||||
|
# It even has most of the build-deps already installed.
|
||||||
|
pacman -Syu --noconfirm jq
|
||||||
|
pacman -S --noconfirm git cmake ninja jq || exit 1
|
||||||
|
pacman -S --noconfirm gcc yaml-cpp icu || exit 1
|
||||||
|
pacman -S --noconfirm extra-cmake-modules || exit 1
|
||||||
|
pacman -S --noconfirm python-jsonschema || exit 1
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user