Compare commits
	
		
			1399 Commits
		
	
	
		
			v3.2.48
			...
			headers-in
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7d50897335 | |||
|   | 8a199aaaf9 | ||
|   | 02aa49d442 | ||
|   | f847f90842 | ||
|   | fa2b96e9cc | ||
|   | 7971bff2da | ||
|   | 6cbed0f458 | ||
|   | e326758900 | ||
|   | ee09fd6613 | ||
|   | a48a16646b | ||
|   | 1401f4ff21 | ||
|   | 6ef7d23168 | ||
|   | 3be99a9ac7 | ||
|   | 040f424931 | ||
|   | 93ce2daff0 | ||
|   | 0ac170c3de | ||
|   | 115f00f5cd | ||
|   | e73f5fb9fe | ||
|   | cd0a381a35 | ||
|   | 709296940c | ||
|   | 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 | ||
|   | e13dbc621a | ||
|   | 559d19018c | ||
|   | 7a9a50d702 | ||
|   | 98d534d5dd | ||
|   | 26236fe63a | ||
|   | a3d06e6d77 | ||
|   | b37afd4269 | ||
|   | 01e7cf44c2 | ||
|   | 5809b32c98 | ||
|   | 8748a52c68 | ||
|   | 65f93168f2 | ||
|   | 0e2fa42b60 | ||
|   | 5f06b321b2 | ||
|   | 146f549552 | ||
|   | 8305b6cb1a | ||
|   | 51a1d06c51 | ||
|   | 63211c86de | ||
|   | de85a02f74 | ||
|   | 8868ae956a | ||
|   | 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 | ||
|   | 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 | ||
|   | 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 | ||
|   | f1e4bcd8e5 | ||
|   | 20b4cefedb | ||
|   | 33aeabd617 | ||
|   | 1963dd3412 | ||
|   | c4496ef86b | ||
|   | 1e2a51f952 | ||
|   | 06d6f217b5 | ||
|   | 63c3f68619 | ||
|   | ca2e36b3f3 | ||
|   | 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 | ||
|   | 9def0cb66f | ||
|   | ddf65a2437 | ||
|   | 4ced8279c6 | ||
|   | 625693ac50 | ||
|   | 1821eb1b39 | ||
|   | d1664f3502 | ||
|   | 6235e04ded | ||
|   | 9191748d82 | ||
|   | 26166e8f51 | ||
|   | f9f4c6f36e | ||
|   | f16da0fde7 | ||
|   | abdfeaa96c | ||
|   | 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 | ||
|   | 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 | ||
|   | 6dbf9de06e | ||
|   | 795256cba5 | ||
|   | b11ee3abc5 | ||
|   | 82b19a6314 | ||
|   | 18626901d3 | ||
|   | 40d8e1e0f6 | ||
|   | b8b7b10bfd | ||
|   | ed5149c17f | ||
|   | f4fb495488 | ||
|   | b7dcf55d4c | ||
|   | 7f7e4aa1ae | ||
|   | 79db04dc2e | ||
|   | 2478570deb | ||
|   | d80661211c | ||
|   | 4420120b55 | ||
|   | 1f237cd373 | ||
|   | 214522f42a | ||
|   | 0257c9d31e | ||
|   | e4729b8dc3 | ||
|   | 5f55f14f9d | ||
|   | 0809dc65ec | ||
|   | 2696bd5b44 | ||
|   | 9cfbb4106b | ||
|   | 8461571fbd | ||
|   | 700f2a6af3 | ||
|   | 2f3fb4a387 | ||
|   | 57d978b82d | ||
|   | 7ccd7aa4e5 | ||
|   | 42f9f07a07 | ||
|   | 9f91b50553 | ||
|   | f8dd3ea133 | ||
|   | 0fd0e9a1af | ||
|   | 26751f2acd | ||
|   | 849b831ca4 | ||
|   | 4d10629acf | ||
|   | 341fecd3ff | ||
|   | 056a5c29cb | ||
|   | a20ab6f0c6 | ||
|   | 70b83f5ca6 | ||
|   | 9ca763127d | ||
|   | 9fdae8c76f | ||
|   | 8b44eef002 | ||
|   | e6960ceec1 | ||
|   | 0141e681df | ||
|   | f5c58c8065 | ||
|   | 3645f99259 | ||
|   | 105159a285 | ||
|   | f958a3c2f7 | ||
|   | d4a776e759 | ||
|   | 1ae79fe58c | ||
|   | 687d44859f | ||
|   | 2c07463ac6 | ||
|   | 7356961f52 | ||
|   | e6d72cb23b | ||
|   | dc699db5f5 | ||
|   | c9be4c744f | ||
|   | 916b87e62e | ||
|   | 425901fb98 | ||
|   | 3b55b65a34 | ||
|   | b763087e11 | ||
|   | e27c57f8a6 | ||
|   | 821a62ffbb | ||
|   | 72240d0d59 | ||
|   | 13153df484 | ||
|   | fb910d7c41 | ||
|   | 55f1df9563 | ||
|   | b2f1a28504 | ||
|   | aca48bc027 | ||
|   | 753ba765eb | ||
|   | 34d8d90688 | ||
|   | 729c31dd7a | ||
|   | 1b2d12b9a1 | ||
|   | ce74d2fdfc | ||
|   | d34f593562 | ||
|   | 00898b18d6 | ||
|   | 84186babab | ||
|   | 18363ca183 | ||
|   | 006c3f99e6 | ||
|   | 04121892cf | ||
|   | 3e72635204 | ||
|   | 7dc450edb4 | ||
|   | 6e8d820737 | ||
|   | 135fce77c1 | ||
|   | b5c5eecdbd | ||
|   | af813ac95b | ||
|   | bb395db9f4 | ||
|   | ff7ceb2e2b | ||
|   | cada0f2547 | ||
|   | f4e5e08aa8 | ||
|   | 5526cdc03c | ||
|   | 63ee982d36 | ||
|   | 4e5078c950 | ||
|   | 61c67f8c22 | ||
|   | badb1d4706 | ||
|   | dfffbc62bc | ||
|   | fd53c090f4 | ||
|   | 6de880c95d | ||
|   | de03a92a8f | ||
|   | 2a7cbd2520 | ||
|   | 4edad4d8c4 | ||
|   | 7e4fc3e4c7 | ||
|   | f9f18e5d3b | ||
|   | 4a852facb3 | ||
|   | 09255a1d9c | ||
|   | f8345a09a2 | ||
|   | 72f25f24ef | ||
|   | 8466d1eb3e | ||
|   | cc7fe7fff7 | ||
|   | 0a4e6804c6 | ||
|   | 900700b9bc | ||
|   | 12b62980cb | ||
|   | e7f6ead038 | ||
|   | 51e3ac0ded | ||
|   | 2a42084af4 | ||
|   | 66682b3e84 | ||
|   | 17814410e9 | ||
|   | cebafcf869 | ||
|   | 7d5a4eafa2 | ||
|   | fc8e5fb5c7 | ||
|   | f352740aba | ||
|   | 874a0c1f38 | ||
|   | 8fea6f71ab | ||
|   | 56071c4016 | ||
|   | 9e664d7165 | ||
|   | cf5f0e1caa | ||
|   | 62f3055e5a | ||
|   | 542aa5c083 | ||
|   | 9e2728bcb7 | ||
|   | 6bf710bed3 | ||
|   | 67ad12c2d0 | ||
|   | 4a4d872bb0 | ||
|   | 9d6bb2ee2a | ||
|   | a63c474d93 | ||
|   | f67df577db | ||
|   | 25a6a5ee53 | ||
|   | cd4b8d4179 | ||
|   | 31c8123677 | ||
|   | d318778f53 | ||
|   | 152f99fb07 | ||
|   | 42841a217c | ||
|   | 7937cd625d | ||
|   | 0d3e5e1c26 | ||
|   | 52e2c8c262 | ||
|   | a9df841770 | ||
|   | 7096ee760e | ||
|   | 880c367d64 | ||
|   | 704e250664 | ||
|   | 928b46f18e | ||
|   | f42924a9ca | ||
|   | 9196f696ea | ||
|   | 824d706a20 | ||
|   | f4e9b3689d | ||
|   | bbeba5c9ab | ||
|   | 0678957def | ||
|   | bc98b9892c | ||
|   | d0db56e964 | ||
|   | ef9bf2650c | ||
|   | 7473462125 | ||
|   | 40c5ef1c35 | ||
|   | fe04ae3ac1 | ||
|   | 1bf5206bd7 | ||
|   | 85c67113b7 | ||
|   | 14129fedb6 | ||
|   | 3bc3b352d8 | ||
|   | 21aa608ce2 | ||
|   | 091eb9683b | ||
|   | 4be25e2f70 | ||
|   | 2de7736291 | ||
|   | e005b1af32 | ||
|   | a8857e51f4 | ||
|   | ed9155bfd8 | ||
|   | 4713f0be42 | ||
|   | 8407d39109 | ||
|   | 1f7b2a3d2d | ||
|   | a7cf1b18ce | ||
|   | f26ff07046 | ||
|   | fee8ac67ef | ||
|   | 03ddabae16 | ||
|   | 7e560fb40d | ||
|   | 42e7fed10a | ||
|   | 8aa8597ab0 | ||
|   | 792c4914b0 | ||
|   | 5307976179 | ||
|   | 0bb93f4a97 | ||
|   | 1c3817ad65 | ||
|   | a7d3630e42 | ||
|   | 992d2d3be0 | ||
|   | ee1232b10a | ||
|   | 1ef2fff03e | ||
|   | ade0fc7e19 | ||
|   | b80fde365b | ||
|   | 01cec2e361 | ||
|   | f302bd8854 | ||
|   | 6ef243ba37 | ||
|   | 5bff26e1e0 | ||
|   | eefe65ad0e | ||
|   | c48209a9dd | ||
|   | d7459e2bfe | ||
|   | 53926b8bbe | ||
|   | 5e80dddc82 | ||
|   | 585d06494e | ||
|   | 62de4eb8bf | ||
|   | ab0a33ceae | ||
|   | e15e57600e | ||
|   | d02afa20b8 | ||
|   | d70d1ebfcd | ||
|   | eb5be9cd34 | ||
|   | cab4be1bd0 | ||
|   | 78067110c9 | ||
|   | 287e89e760 | ||
|   | 1aee8401db | ||
|   | bbb0efc15e | ||
|   | 70911b9275 | ||
|   | 34ea3112a5 | ||
|   | 4613386863 | ||
|   | 4466e360e1 | ||
|   | 1752dd573b | ||
|   | 19af46faea | ||
|   | 466c01b524 | ||
|   | 9374daca64 | ||
|   | 33fabccc14 | ||
|   | fae515c3a2 | ||
|   | 2114a6f880 | ||
|   | 29733819f5 | ||
|   | 5d1b024237 | ||
|   | a3bd0d8091 | ||
|   | 03f755d168 | ||
|   | 1c49648fc5 | ||
|   | a86f3ba96d | ||
|   | c86ff3a5bb | ||
|   | ab8d59bd41 | ||
|   | dcbb83ebe5 | ||
|   | 807dee54fd | ||
|   | 73d09977fc | ||
|   | 47016765b3 | ||
|   | 217e4ab4f7 | ||
|   | b129cb0786 | ||
|   | e102e2630e | ||
|   | 7650795f48 | ||
|   | e5036da084 | ||
|   | 07f4ec529b | ||
|   | 0b2af86ec9 | ||
|   | 8b917ace4d | ||
|   | ab1c78ca23 | ||
|   | 3679bb45f0 | ||
|   | 1101b0dc82 | ||
|   | 15b4660d3e | ||
|   | e457d099d8 | ||
|   | 7686b89cd6 | ||
|   | e757639669 | ||
|   | 7b22546b14 | ||
|   | 7db14cb5cf | ||
|   | 33b4fd3a20 | ||
|   | c8185affb9 | ||
|   | 91e1087eb9 | ||
|   | 24026af32a | ||
|   | 2241445b09 | ||
|   | fb893542a2 | ||
|   | 9a66b51117 | ||
|   | caa15c03a6 | ||
|   | 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 | ||
|   | 69e00d181a | ||
|   | b0837b1a98 | ||
|   | a67adf7702 | ||
|   | f6b65b3b93 | ||
|   | bbea67ecb4 | ||
|   | cc3ab110ee | ||
|   | d76dd2f8e0 | ||
|   | 334b7fc219 | ||
|   | f923dedc3f | ||
|   | 576f244d2d | ||
|   | d03a8acc9d | ||
|   | 2c0d9396e2 | ||
|   | bb278c7ba9 | ||
|   | 3bf0a93b86 | ||
|   | 82b5ca8bfc | ||
|   | baf8ef2c33 | ||
|   | 913b7c8809 | ||
|   | 7ccc5d08c8 | ||
|   | 7f232f0994 | ||
|   | 30139107de | ||
|   | 9c58f49c49 | ||
|   | 3b02115f8e | ||
|   | dad12a0e02 | ||
|   | c28ba5ffb2 | ||
|   | 9ca6d3c715 | ||
|   | b95eb55994 | ||
|   | 1a8fc1feec | ||
|   | 92b1341730 | ||
|   | 3524d4a0d0 | ||
|   | 3b0aa69ad3 | ||
|   | 9299bedd7e | ||
|   | a12c6de2ef | ||
|   | 2f78a37426 | ||
|   | c5c546d290 | ||
|   | 854c711ac6 | ||
|   | 6a6aa8867b | ||
|   | b653b13002 | ||
|   | 99bf5497ca | ||
|   | 73462d9214 | ||
|   | 8a8ac4fe2b | ||
|   | 4494a4b35a | ||
|   | 04f38ea661 | ||
|   | 55dcd831bc | ||
|   | 94d5746268 | ||
|   | b52b54849a | ||
|   | 345830794a | ||
|   | c70deed13a | ||
|   | 3381e3040c | ||
|   | 8deead2781 | ||
|   | 04a3ac5557 | ||
|   | 5c2c60612b | ||
|   | 14ef6577ae | ||
|   | 1f289bc93d | ||
|   | 511631c6ae | ||
|   | 93be40349b | ||
|   | a45f324ed8 | ||
|   | 9e4b2d14cb | ||
|   | ec3282e15d | ||
|   | 9b769f0ae4 | ||
|   | e51a47d072 | ||
|   | f64938cb3f | ||
|   | 9b0ef5fce5 | ||
|   | 8ce92d450c | ||
|   | 982f9c8458 | ||
|   | f888cb87d1 | ||
|   | 97031ea3e6 | ||
|   | a303efb174 | ||
|   | 029bb3efdd | ||
|   | 4545470f2d | ||
|   | 99b19b9539 | ||
|   | aedb55ea36 | ||
|   | 49c56add7d | ||
|   | 930d8e20ff | ||
|   | 8ec02b3d16 | ||
|   | bb62bebf1a | ||
|   | ce8aaf8955 | ||
|   | db3160145e | ||
|   | 7c5a663237 | ||
|   | 6f28120401 | ||
|   | 1ee82e390b | ||
|   | 88d392f612 | ||
|   | 9b651b4f00 | ||
|   | f4a10a313c | ||
|   | 7d89643146 | ||
|   | 276aa191d5 | ||
|   | fa28999561 | ||
|   | 121b11525f | ||
|   | b2aa5d8dea | ||
|   | b44091b4e3 | ||
|   | 05468016a1 | ||
|   | f0d4788e6d | ||
|   | 28bf8478c4 | ||
|   | d998c9e24b | ||
|   | 26a613fff1 | ||
|   | 1a3f41ff33 | ||
|   | d5e0fca490 | ||
|   | 87c8c3e6ee | ||
|   | d8e49cd9e7 | ||
|   | 20c44ff99a | ||
|   | 1a6fb1c3d2 | ||
|   | d89955f4b3 | ||
|   | 743d3ecd01 | ||
|   | f60def5ecc | ||
|   | c35da331a2 | ||
|   | 4b905d5b52 | ||
|   | b5faf1be9b | ||
|   | ea061ae239 | ||
|   | 9e522eddf8 | ||
|   | 923379def6 | ||
|   | 53d3fcb2fd | ||
|   | a6afb6be7c | ||
|   | 0f84efed39 | ||
|   | 6596cd1208 | ||
|   | 207576c885 | ||
|   | 667e88f2df | ||
|   | 569db7c018 | ||
|   | dca5d9b52b | ||
|   | 827d06df85 | ||
|   | 107afcff27 | ||
|   | 1793c627cd | ||
|   | 7aafeec2cb | ||
|   | 2f782f18c4 | ||
|   | 53c4bbe4e0 | ||
|   | 4fe55533d7 | ||
|   | 9b3bc3d25f | ||
|   | 60630efa6a | ||
|   | 7e51731167 | ||
|   | c5fec83f64 | ||
|   | f2a6736883 | ||
|   | 5b40f17b9c | ||
|   | d4812bbb36 | ||
|   | e3515347ed | ||
|   | 03b261dfc5 | ||
|   | 05991c9ee9 | ||
|   | 9779676fd8 | ||
|   | 77190a0d42 | ||
|   | c3224e60d6 | ||
|   | aecdb5fe6d | ||
|   | c1f1934c27 | ||
|   | 23f501c071 | ||
|   | 92f4ab30ea | ||
|   | 682ae24b7d | ||
|   | 7129a2239c | ||
|   | 9dd2f275f1 | ||
|   | f04f0a7e1d | ||
|   | 99d11f754f | ||
|   | 62888f7984 | ||
|   | 240c89c585 | ||
|   | b1742876fd | ||
|   | f34008b518 | ||
|   | 03291fb726 | ||
|   | 0be88f1453 | ||
|   | a59c45d869 | ||
|   | 7f14aa6bf1 | ||
|   | c7cc599a19 | ||
|   | 3b55c2805a | ||
|   | cf097850de | ||
|   | b167d8da03 | ||
|   | e507a23795 | ||
|   | 5160fdc26a | ||
|   | 8f769006d6 | ||
|   | 9f6f82405b | ||
|   | 932ab17c9a | ||
|   | ebdcb15703 | ||
|   | 660b198da0 | ||
|   | fa7394723c | ||
|   | 3ea25a901e | ||
|   | d5c6a70442 | ||
|   | 0fff01e36e | ||
|   | 95240da872 | ||
|   | 93e7b12a5d | ||
|   | 4b3b44bdfb | ||
|   | d98027ad2f | ||
|   | 2bf43ffbf2 | ||
|   | 0c7f06137a | ||
|   | a352bd946e | ||
|   | d1e4740e70 | ||
|   | baad8f7d2c | ||
|   | 5d23a8f693 | ||
|   | 9127b76e5f | ||
|   | aede7056f2 | ||
|   | cf913b87ff | ||
|   | c4eee7bb11 | ||
|   | 7f90b99388 | ||
|   | f4720ae02c | ||
|   | 45fff23499 | ||
|   | 82dcc1b57b | ||
|   | d8be9a9443 | ||
|   | fbcd1ffbbe | ||
|   | d8c875f351 | ||
|   | 6f738813a6 | ||
|   | 4a30aae9bb | ||
|   | 691951974d | ||
|   | e9899d0345 | ||
|   | ffeab32403 | ||
|   | 80300e412c | ||
|   | 51f67f6c3e | ||
|   | cf2899b1e6 | ||
|   | c0f4b80cbe | ||
|   | 19afa46978 | ||
|   | 6a2e80a0b7 | ||
|   | 5b994f85c9 | ||
|   | f7d4f049a7 | ||
|   | 37e189992e | ||
|   | c1a01ca7a6 | ||
|   | e597998021 | ||
|   | f65feedcce | ||
|   | 6be1208488 | ||
|   | 63ed2e5fb8 | ||
|   | 22c9d888b4 | ||
|   | 1db217931b | ||
|   | a657d7388c | ||
|   | f4c2db7f21 | ||
|   | 95122fdcf5 | ||
|   | 2aa8c2f0e0 | ||
|   | 88afcee37a | ||
|   | 929496552e | ||
|   | c9156d41b1 | ||
|   | 7a462f4522 | ||
|   | ed5c4c9c87 | ||
|   | b4b7deac2d | ||
|   | d1866edfe5 | ||
|   | 79683dd83d | ||
|   | c587145bdd | ||
|   | 4d5ae96db6 | ||
|   | 6034feb69d | ||
|   | afa5e75d76 | ||
|   | 5e4866c439 | ||
|   | 0070dd2c01 | ||
|   | 4c5ee3b53a | ||
|   | 5d6375dab7 | ||
|   | 546780d7a8 | ||
|   | ac083f787d | ||
|   | bca4b73677 | ||
|   | da2612d2d9 | ||
|   | 08cd79f0c2 | ||
|   | 4811c59e33 | ||
|   | 11f3f938d8 | ||
|   | 85a3d1dc84 | ||
|   | 6101dd9079 | ||
|   | 79a91b486a | ||
|   | 2aaaabe152 | ||
|   | a93126a6d0 | ||
|   | 112d0b2e90 | ||
|   | 98bbc222cb | ||
|   | fad23c9ac6 | ||
|   | e6813949af | ||
|   | 4be932ff9d | ||
|   | 8eb7eb8b1f | ||
|   | b4ac6b73c8 | ||
|   | 2eda55d3af | ||
|   | a8f6596d38 | ||
|   | b227419f01 | ||
|   | da03e12b7b | ||
|   | f349a9c864 | ||
|   | 624bb13736 | ||
|   | 94bca61491 | ||
|   | ee2fea74df | ||
|   | 1f9ae6cae6 | ||
|   | e14fa5de75 | ||
|   | 626ab98949 | ||
|   | 3be6946d93 | ||
|   | 475c0d21a1 | ||
|   | c2ae5fad96 | ||
|   | 4fe5f1c06f | ||
|   | 5b483ab26f | ||
|   | 3e1bc6cb22 | ||
|   | bb1d3022e0 | ||
|   | a50ffa74e1 | ||
|   | 03f2e45605 | ||
|   | 4e61f24960 | ||
|   | 1c853941dc | ||
|   | 24a881ad75 | ||
|   | 7cfa654a68 | ||
|   | 7864ab5cfa | ||
|   | 905f1241e3 | ||
|   | f0aba5db96 | ||
|   | 480fe56ae3 | ||
|   | 728315d3cc | ||
|   | da72e815dc | ||
|   | 0145f6fe7d | ||
|   | cfeba736d5 | ||
|   | be18e51bc9 | ||
|   | 7fc2859f23 | ||
|   | 587a18a6fa | ||
|   | 043619cd4b | ||
|   | f04394d014 | ||
|   | 07354a26a9 | ||
|   | fdf0f208f0 | ||
|   | 6680584724 | ||
|   | c5573a1997 | ||
|   | b8ce21d572 | ||
|   | 1356012fb4 | ||
|   | 8bb2c5fc6b | ||
|   | dc7a1e43b7 | ||
|   | 53c90516b2 | ||
|   | d3ed5663d0 | ||
|   | 778c2855f4 | ||
|   | 445ed870cc | ||
|   | 3be52f8b37 | ||
|   | a1b7ba0dc5 | ||
|   | 8b5e49d980 | ||
|   | 90f6ea1fc8 | ||
|   | 238672ef78 | ||
|   | b1ecbb4151 | ||
|   | 795b2c88e8 | ||
|   | becb1d5710 | ||
|   | 5b225cf960 | ||
|   | 6261f8a5cb | ||
|   | 132ebd2c2d | ||
|   | db86c24638 | ||
|   | 03da766b39 | ||
|   | adaed52818 | ||
|   | 7ac42b5f40 | ||
|   | 3cdb019de7 | ||
|   | b4afedc79e | ||
|   | 3870851074 | ||
|   | 046a228d62 | ||
|   | 2c20a00cc3 | ||
|   | 45d6eb36fb | ||
|   | 7ea21663ca | ||
|   | 5ca029df25 | ||
|   | bc2713ccbb | ||
|   | bb948c47dc | ||
|   | fa29ae2c5e | ||
|   | 043bdc36d6 | ||
|   | f0eb7ffbda | ||
|   | e8ca298712 | ||
|   | 13700b18c8 | ||
|   | 1197d8c750 | ||
|   | 09f47b5762 | ||
|   | 4611545f93 | ||
|   | 6e715205d7 | ||
|   | 09a03fbbc0 | ||
|   | bb3f4442f5 | ||
|   | 5b05110351 | ||
|   | eda85c176a | ||
|   | 32da51b44c | ||
|   | 0b6239a996 | ||
|   | 79ae3cd00f | ||
|   | c2e63f4a6b | ||
|   | 8b804c4ae0 | ||
|   | 3030a710cc | ||
|   | b07c9bb4af | ||
|   | 3234de5753 | ||
|   | 2f9edb3e08 | ||
|   | ca7f288488 | ||
|   | 49890acd04 | ||
|   | dc11dd2203 | ||
|   | 6e59177f54 | ||
|   | d2ac201b98 | ||
|   | c8ea3bccf7 | ||
|   | 8e4c9b8bd6 | ||
|   | 13196ed2e2 | ||
|   | eb2cf60466 | ||
|   | 149f3ff3fe | ||
|   | d89553a777 | ||
|   | 890c17cd71 | ||
|   | 6ef7acc108 | ||
|   | baf8297cc4 | ||
|   | 47f2dd3c18 | ||
|   | 6e08da6c8d | ||
|   | b8c02587ae | ||
|   | aa332477fd | ||
|   | d9f7726f7d | ||
|   | 2f2a418cc4 | ||
|   | 2dd77ee828 | ||
|   | bfa7b9a792 | ||
|   | 32c5e18db0 | ||
|   | 003e7949e3 | ||
|   | e8936392e3 | ||
|   | c834a5066d | ||
|   | 6bf0da7230 | ||
|   | 1d96c5af46 | ||
|   | 6e8779cbce | ||
|   | e4a3b66024 | ||
|   | 1667d75a70 | ||
|   | ce23efae99 | ||
|   | bd4bed1438 | ||
|   | 23f6b25cfc | ||
|   | 8e959105c6 | ||
|   | dde55471ba | ||
|   | 97eea9bde2 | ||
|   | b5f8e30093 | ||
|   | 9d9cd44617 | ||
|   | c1f7a2c855 | ||
|   | e0f40cb4a4 | ||
|   | 04e927e67f | ||
|   | 605ad788d0 | ||
|   | bcde8b87b1 | ||
|   | cb3b2422a9 | ||
|   | 60cc8696e3 | ||
|   | ca4dbabf70 | ||
|   | c1e1e6c3a4 | ||
|   | cf6c930df5 | ||
|   | e1df2a2450 | ||
|   | bd3f89fb57 | ||
|   | f9dc932f62 | ||
|   | 4b08aebe7f | ||
|   | 1fe27effe5 | ||
|   | 453e760709 | ||
|   | 0ad9242ab7 | ||
|   | 5da736466c | ||
|   | df256b608a | ||
|   | 1f5bdef96e | ||
|   | 261c3587a5 | ||
|   | a6ba3dfce0 | ||
|   | 1bd5628256 | ||
|   | 714605ebaa | ||
|   | 5975ff9e42 | ||
|   | a27b72e893 | ||
|   | 396746acc1 | ||
|   | adc3af0345 | ||
|   | 5a82c8123b | ||
|   | 8ab1a4fb30 | ||
|   | 72701aae21 | ||
|   | 419be4df25 | 
| @@ -22,14 +22,16 @@ Cpp11BracedListStyle: "false" | ||||
| FixNamespaceComments: "true" | ||||
| IncludeBlocks: Preserve | ||||
| IndentWidth: "4" | ||||
| InsertBraces: "true" | ||||
| MaxEmptyLinesToKeep: "2" | ||||
| NamespaceIndentation: None | ||||
| PointerAlignment: Left | ||||
| ReflowComments: "false" | ||||
| SortIncludes: "true" | ||||
| SpaceAfterCStyleCast: "false" | ||||
| SpaceInEmptyBlock: "false" | ||||
| SpacesBeforeTrailingComments: "2" | ||||
| SpacesInAngles: "true" | ||||
| SpacesInParentheses: "true" | ||||
| SpacesInSquareBrackets: "true" | ||||
| Standard: Cpp11 | ||||
| Standard: c++17 | ||||
|   | ||||
| @@ -1,35 +0,0 @@ | ||||
| #   SPDX-FileCopyrightText: no | ||||
| #   SPDX-License-Identifier: CC0-1.0 | ||||
| --- | ||||
| BasedOnStyle: WebKit | ||||
|  | ||||
| AlignAfterOpenBracket: Align | ||||
| AlignEscapedNewlines: DontAlign | ||||
| AllowAllParametersOfDeclarationOnNextLine: "false" | ||||
| AllowShortFunctionsOnASingleLine: Inline | ||||
| AllowShortIfStatementsOnASingleLine: "false" | ||||
| AllowShortLambdasOnASingleLine: All | ||||
| AllowShortLoopsOnASingleLine: "false" | ||||
| AlwaysBreakAfterReturnType: TopLevelDefinitions | ||||
| AlwaysBreakTemplateDeclarations: Yes | ||||
| BinPackArguments: "false" | ||||
| BinPackParameters: "false" | ||||
| BreakBeforeBraces: Allman | ||||
| BreakBeforeTernaryOperators: "true" | ||||
| BreakConstructorInitializers: BeforeComma | ||||
| ColumnLimit: 120 | ||||
| Cpp11BracedListStyle: "false" | ||||
| FixNamespaceComments: "true" | ||||
| IncludeBlocks: Preserve | ||||
| IndentWidth: "4" | ||||
| MaxEmptyLinesToKeep: "2" | ||||
| NamespaceIndentation: None | ||||
| PointerAlignment: Left | ||||
| ReflowComments: "false" | ||||
| SortIncludes: "true" | ||||
| SpaceAfterCStyleCast: "false" | ||||
| SpacesBeforeTrailingComments: "2" | ||||
| SpacesInAngles: "true" | ||||
| SpacesInParentheses: "true" | ||||
| SpacesInSquareBrackets: "true" | ||||
| Standard: Cpp11 | ||||
							
								
								
									
										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 | ||||
|  | ||||
							
								
								
									
										5
									
								
								.git-blame-ignore-revs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.git-blame-ignore-revs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| #   SPDX-FileCopyrightText: no | ||||
| #   SPDX-License-Identifier: CC0-1.0 | ||||
| # | ||||
| 18fef8dfe5d926ec0bc979562553adf4db8db2e9 | ||||
| 874a0c1f38b0da4e5bc83083b13a63b1c7eed935 | ||||
							
								
								
									
										14
									
								
								.github/workflows/issues.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.github/workflows/issues.yml
									
									
									
									
										vendored
									
									
								
							| @@ -8,20 +8,6 @@ jobs: | ||||
|   notify: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: "notify: new" | ||||
|         if: github.event.issue.state == 'open' | ||||
|         uses: calamares/actions/matrix-notify@v3 | ||||
|         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@v3 | ||||
|         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" | ||||
|         if: github.event.issue.state != 'open' | ||||
|         run: | | ||||
|   | ||||
							
								
								
									
										36
									
								
								.github/workflows/nightly-debian.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								.github/workflows/nightly-debian.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| name: nightly-debian-10 | ||||
| name: nightly-debian-11 | ||||
|  | ||||
| on: | ||||
|   schedule: | ||||
| @@ -9,36 +9,26 @@ 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://debian:10 | ||||
|       image: docker://debian:11 | ||||
|       options: --tmpfs /build:rw --user 0:0 | ||||
|     steps: | ||||
|       - name: "prepare env" | ||||
|         uses: calamares/actions/prepare-debian@v3 | ||||
|       - name: "prepare git" | ||||
|         shell: bash | ||||
|         run: | | ||||
|             apt-get update | ||||
|             apt-get -y install git-core jq curl | ||||
|       - name: "prepare source" | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: calamares/actions/generic-checkout@v5 | ||||
|       - name: "install dependencies" | ||||
|         shell: bash | ||||
|         run: ./ci/deps-debian11.sh | ||||
|       - name: "build" | ||||
|         id: build | ||||
|         uses: calamares/actions/generic-build@v3 | ||||
|       - name: "notify: ok" | ||||
|         if: ${{ success() && github.repository == 'calamares/calamares' }} | ||||
|         uses: calamares/actions/matrix-notify@v3 | ||||
|         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@v3 | ||||
|         with: | ||||
|           token: ${{ secrets.MATRIX_TOKEN }} | ||||
|           room: ${{ secrets.MATRIX_ROOM }} | ||||
|           message: "FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}" | ||||
|         shell: bash | ||||
|         run: ./ci/build.sh | ||||
|   | ||||
							
								
								
									
										33
									
								
								.github/workflows/nightly-fedora-qt6.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								.github/workflows/nightly-fedora-qt6.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| 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 | ||||
|  | ||||
| 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 | ||||
							
								
								
									
										29
									
								
								.github/workflows/nightly-neon-unstable.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								.github/workflows/nightly-neon-unstable.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| name: nightly-neon-unstable | ||||
|  | ||||
| on: | ||||
|   schedule: | ||||
|     - cron: "59 23 * * *" | ||||
|   workflow_dispatch: | ||||
|  | ||||
| env: | ||||
|   BUILDDIR: /build | ||||
|   SRCDIR: ${{ github.workspace }} | ||||
|   CMAKE_ARGS: | | ||||
|     -DKDE_INSTALL_USE_QT_SYS_PATHS=ON | ||||
|     -DCMAKE_BUILD_TYPE=Debug | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     container: | ||||
|       image: docker://kdeneon/plasma:unstable | ||||
|       options: --tmpfs /build:rw --user 0:0 | ||||
|     steps: | ||||
|       - name: "prepare source" | ||||
|         uses: calamares/actions/generic-checkout@v5 | ||||
|       - name: "install dependencies" | ||||
|         shell: bash | ||||
|         run: ./ci/deps-neon.sh | ||||
|       - name: "build" | ||||
|         shell: bash | ||||
|         run: ./ci/build.sh | ||||
							
								
								
									
										33
									
								
								.github/workflows/nightly-neon.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								.github/workflows/nightly-neon.yml
									
									
									
									
										vendored
									
									
								
							| @@ -9,9 +9,7 @@ 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: | ||||
| @@ -21,36 +19,23 @@ jobs: | ||||
|       image: docker://kdeneon/plasma:user | ||||
|       options: --tmpfs /build:rw --user 0:0 | ||||
|     steps: | ||||
|       - name: "prepare env" | ||||
|         uses: calamares/actions/prepare-neon@v3 | ||||
|       - name: "prepare source" | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: calamares/actions/generic-checkout@v5 | ||||
|       - name: "install dependencies" | ||||
|         shell: bash | ||||
|         run: ./ci/deps-neon.sh | ||||
|       - name: "build" | ||||
|         id: build | ||||
|         uses: calamares/actions/generic-build@v3 | ||||
|         shell: bash | ||||
|         run: ./ci/build.sh | ||||
|       - name: "Calamares: archive" | ||||
|         working-directory: ${{ env.BUILDDIR }} | ||||
|         run: | | ||||
|           make install DESTDIR=${{ env.BUILDDIR }}/stage | ||||
|           DESTDIR=${{ env.BUILDDIR }}/stage ninja install | ||||
|           tar czf calamares.tar.gz stage | ||||
|       - name: "Calamares: upload" | ||||
|         uses: actions/upload-artifact@v2 | ||||
|         uses: actions/upload-artifact@v3 | ||||
|         with: | ||||
|           name: calamares-tarball | ||||
|           path: ${{ env.BUILDDIR }}/calamares.tar.gz | ||||
|           if-no-files-found: error | ||||
|           retention-days: 3 | ||||
|       - name: "notify: ok" | ||||
|         if: ${{ success() && github.repository == 'calamares/calamares' }} | ||||
|         uses: calamares/actions/matrix-notify@v3 | ||||
|         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@v3 | ||||
|         with: | ||||
|           token: ${{ secrets.MATRIX_TOKEN }} | ||||
|           room: ${{ secrets.MATRIX_ROOM }} | ||||
|           message: "FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}" | ||||
|           retention-days: 7 | ||||
|   | ||||
							
								
								
									
										33
									
								
								.github/workflows/nightly-opensuse-qt6.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								.github/workflows/nightly-opensuse-qt6.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| name: nightly-opensuse-qt6 | ||||
|  | ||||
| on: | ||||
|   schedule: | ||||
|     - cron: "32 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 | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     container: | ||||
|       image: docker://opensuse/tumbleweed | ||||
|       options: --tmpfs /build:rw --user 0:0 | ||||
|     steps: | ||||
|       - name: "prepare git" | ||||
|         shell: bash | ||||
|         run: zypper --non-interactive in git-core jq curl | ||||
|       - name: "prepare source" | ||||
|         uses: calamares/actions/generic-checkout@v5 | ||||
|       - name: "install dependencies" | ||||
|         shell: bash | ||||
|         run: ./ci/deps-opensuse-qt6.sh | ||||
|       - name: "build" | ||||
|         shell: bash | ||||
|         run: ./ci/build.sh | ||||
							
								
								
									
										35
									
								
								.github/workflows/nightly-opensuse.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								.github/workflows/nightly-opensuse.yml
									
									
									
									
										vendored
									
									
								
							| @@ -9,37 +9,26 @@ 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 | ||||
|     -DBUILD_SCHEMA_TESTING=ON | ||||
|     -DBUILD_TESTING=ON | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     container: | ||||
|       image: docker://opensuse/leap | ||||
|       image: docker://opensuse/tumbleweed | ||||
|       options: --tmpfs /build:rw --user 0:0 | ||||
|     steps: | ||||
|       - name: "prepare env" | ||||
|         uses: calamares/actions/prepare-opensuse@v3 | ||||
|       - name: "prepare git" | ||||
|         shell: bash | ||||
|         run: zypper --non-interactive in git-core jq curl | ||||
|       - name: "prepare source" | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: calamares/actions/generic-checkout@v5 | ||||
|       - name: "install dependencies" | ||||
|         shell: bash | ||||
|         run: ./ci/deps-opensuse.sh | ||||
|       - name: "build" | ||||
|         id: build | ||||
|         uses: calamares/actions/generic-build@v3 | ||||
|       - name: "notify: ok" | ||||
|         if: ${{ success() && github.repository == 'calamares/calamares' }} | ||||
|         uses: calamares/actions/matrix-notify@v3 | ||||
|         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@v3 | ||||
|         with: | ||||
|           token: ${{ secrets.MATRIX_TOKEN }} | ||||
|           room: ${{ secrets.MATRIX_ROOM }} | ||||
|           message: "FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}" | ||||
|         shell: bash | ||||
|         run: ./ci/build.sh | ||||
|   | ||||
							
								
								
									
										33
									
								
								.github/workflows/push.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								.github/workflows/push.yml
									
									
									
									
										vendored
									
									
								
							| @@ -17,8 +17,9 @@ env: | ||||
|   CMAKE_ARGS: | | ||||
|     -DWEBVIEW_FORCE_WEBKIT=1 | ||||
|     -DKDE_INSTALL_USE_QT_SYS_PATHS=ON | ||||
|     -DWITH_PYTHONQT=OFF" | ||||
|     -DWITH_PYTHONQT=OFF | ||||
|     -DCMAKE_BUILD_TYPE=Debug | ||||
|   GIT_HASH: ${{ github.event.head_commit.id }} | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
| @@ -27,29 +28,11 @@ jobs: | ||||
|       image: docker://kdeneon/plasma:user | ||||
|       options: --tmpfs /build:rw --user 0:0 | ||||
|     steps: | ||||
|       - name: "prepare env" | ||||
|         uses: calamares/actions/prepare-neon@v3 | ||||
|       - name: "prepare source" | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: calamares/actions/generic-checkout@v5 | ||||
|       - name: "install dependencies" | ||||
|         shell: bash | ||||
|         run: ./ci/deps-neon.sh | ||||
|       - name: "build" | ||||
|         id: build | ||||
|         uses: calamares/actions/generic-build@v3 | ||||
|       - name: "notify: ok" | ||||
|         if: ${{ success() && github.repository == 'calamares/calamares' }} | ||||
|         uses: calamares/actions/matrix-notify@v3 | ||||
|         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@v3 | ||||
|         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 }} | ||||
|         shell: bash | ||||
|         run: ./ci/build.sh | ||||
|   | ||||
							
								
								
									
										18
									
								
								.reuse/dep5
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								.reuse/dep5
									
									
									
									
									
								
							| @@ -15,6 +15,10 @@ Files: man/calamares.8 | ||||
| License: GPL-3.0-or-later | ||||
| 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 | ||||
| # | ||||
| # 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 | ||||
| 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 | ||||
| # | ||||
| # .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 | ||||
| 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 | ||||
|   | ||||
| @@ -2,21 +2,21 @@ | ||||
| #   SPDX-License-Identifier: CC0-1.0 | ||||
|  | ||||
| [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 | ||||
| source_file = lang/calamares_en.ts | ||||
| source_lang = en | ||||
| type        = QT | ||||
|  | ||||
| [calamares.fdo] | ||||
| [o:calamares:p:calamares:r:fdo] | ||||
| file_filter = lang/desktop_<lang>.desktop | ||||
| source_file = calamares.desktop | ||||
| source_lang = en | ||||
| type        = DESKTOP | ||||
|  | ||||
| [calamares.python] | ||||
| [o:calamares:p:calamares:r:python] | ||||
| file_filter = lang/python/<lang>/LC_MESSAGES/python.po | ||||
| source_file = lang/python.pot | ||||
| 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; | ||||
| }; | ||||
							
								
								
									
										30
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -20,30 +20,58 @@ and moral support from (alphabetically by first name or nickname): | ||||
|  - Allen Welkie | ||||
|  - AlmAck | ||||
|  - Andrius Štikonas | ||||
|  - Anke Boersma | ||||
|  - Anubhav Choudhary | ||||
|  - Arjen Balfoort | ||||
|  - Arnaud Ferraris | ||||
|  - Artem Grinev | ||||
|  - artoo@cromnix.org | ||||
|  - benne-dee | ||||
|  - Bernhard Landauer | ||||
|  - Bezzy1999 | ||||
|  - Bill Auger | ||||
|  - Bob van der Linden | ||||
|  - Caio Jordão Carvalho | ||||
|  - Camilo Higuita | ||||
|  - Collabora LTD | ||||
|  - Corey Lang | ||||
|  - crispg72 | ||||
|  - Dan Simmons | ||||
|  - demmm | ||||
|  - Emmanuel Arias | ||||
|  - Enrique Medina Gremaldos | ||||
|  - Erik Dubois | ||||
|  - Dominic Hayes | ||||
|  - El-Wumbus | ||||
|  - Evan James | ||||
|  - Frede H | ||||
|  - Gabriel Craciunescu | ||||
|  - Harald Sitter | ||||
|  - Huang Jia Wen | ||||
|  - Jerrod Frost | ||||
|  - Jia Chao | ||||
|  - Joe Kamprad | ||||
|  - Jonas Strassel | ||||
|  - Kai Dohmen | ||||
|  - Kevin Kofler | ||||
|  - Kyle Robertze | ||||
|  - Lisa Vitolo | ||||
|  - Neal Gompa | ||||
|  - Matti Hyttinen | ||||
|  - n3rdopolis | ||||
|  - Neal Gompa | ||||
|  - Nico 'dr460nf1r3' | ||||
|  - Omer I.S. | ||||
|  - Philip Müller | ||||
|  - Ramon Buldó | ||||
|  - Raul Rodrigo Segura | ||||
|  - Rohan Garg | ||||
|  - Santosh Mahto | ||||
|  - Scott Harvey | ||||
|  - Simon Quigley | ||||
|  - Taejun Park | ||||
|  - Victor Fuentes | ||||
|  - vtriolet | ||||
|  - Walter Lapchynski | ||||
|  - Waneon Kim | ||||
|  | ||||
|  > This list was updated to revision 6e8d820737dea0f3e08f12b10768facef19be684 on May 28th 2022. | ||||
|   | ||||
							
								
								
									
										354
									
								
								CHANGES-3.2
									
									
									
									
									
								
							
							
						
						
									
										354
									
								
								CHANGES-3.2
									
									
									
									
									
								
							| @@ -7,6 +7,360 @@ contributors are listed. Note that Calamares does not have a historical | ||||
| changelog -- this log starts with version 3.2.0. The release notes on the | ||||
| website will have to do for older versions. | ||||
|  | ||||
|  | ||||
| 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 (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): | ||||
|  - Adriaan de Groot | ||||
|  - Anke Boersma | ||||
|  | ||||
| ## Core ## | ||||
|  - 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 ## | ||||
|  - *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) # | ||||
|  | ||||
| This is the first community-maintainence release of Calamares 3.2. | ||||
| Somewhat ironically, all the commits in the branch come from | ||||
| Adriaan de Groot -- the community is working in the 3.3 (*calamares*) | ||||
| branch. | ||||
|  | ||||
| ## Core ## | ||||
|  - No core changes | ||||
|  | ||||
| ## Modules ## | ||||
|  - *fstab* now warns when the mount options are empty (which is non- | ||||
|    sensical, and indicates that the configuration is bad). | ||||
|  - *locale* does a better job of preserving Catalan (Valencia) | ||||
|    across modules; previously it dropped the *Valencia* | ||||
|    after the locale module unless you specifically re-selected | ||||
|    `ca@valencia` in the locale module. (Reported by Lliurex) | ||||
|  - *welcome* now has text labels on the special buttons (nominally, | ||||
|    this is part of the core, but the *About* button was always on the | ||||
|    welcome page). | ||||
|  | ||||
|  | ||||
| # 3.2.59 (2022-05-29) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Arjen Balfoort | ||||
|  | ||||
| This is the final release of Calamares 3.2 where the release is from | ||||
| the *calamares* branch -- that is, where the primary development | ||||
| branch is also the branch being released regularly. Future releases | ||||
| of the 3.2 series are bugfix-only, and no new feature development | ||||
| or translations are expected. This is also the final release done | ||||
| *as work-work* by the current maintainer. | ||||
|  | ||||
| ## Core ## | ||||
|  - Prep-work for moving the *About Calamares* button to the panels, | ||||
|    rather than keeping it in the Welcome module. The about information | ||||
|    is somewhat more flexible now, so that a new maintainer can be added | ||||
|    easily without frustrating translators. | ||||
|  - The progress panels (both Widgets and QML) now have an About button | ||||
|    on them, showing the traditional *About Calamares* dialog. | ||||
|  - Translations for the (QML) slideshow were not being loaded correctly. | ||||
|    The log is now somewhat more informative when that fails. | ||||
|  | ||||
| ## Modules ## | ||||
|  - *fstab* can now be configured to put `/tmp` on a *tmpfs*, and this can | ||||
|    depend on it being on an SSD or not. Options applicable to `/tmp` can | ||||
|    be configured separately as well. #1818 (Thanks Arjen) | ||||
|  - *partition* now has some support for re-using LUKS partitions. | ||||
|    (Thanks Arjen) | ||||
|  - *partition* will cycle out a LUKS key if all the key slots are in use | ||||
|    and a new key is added, rather than crashing the installer. (Thanks Arjen) | ||||
|  - *welcome* and *welcomeq* have no *About* button anymore; this is now | ||||
|    available from the progress panel, since it's also not-really about the | ||||
|    distro itself. | ||||
|  | ||||
|  | ||||
| # 3.2.58.2 (2022-05-24) | ||||
|  | ||||
| This is a extra-quick release for an issue that shows up when using a | ||||
| swap **file** on a btrfs filesystem; the installation would fail with | ||||
| a Python error, raised from btrfs-progs. Reported by Evan James, Erik | ||||
| Dubois, TechXero. | ||||
|  | ||||
|  | ||||
| # 3.2.58.1 (2022-05-20) | ||||
|  | ||||
| This is a hot-fix release for a regression in the *partition* module where | ||||
| it was impossible to proceed unless *Encrypt system* was checked. | ||||
|  | ||||
|  | ||||
| # 3.2.58 (2022-05-18) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Anke Boersma | ||||
|  - Arjen Balfoort | ||||
|  - Enrique Medina Gremaldos | ||||
|  - Evan James | ||||
|  | ||||
| ## Core ## | ||||
|  - Internal improvements to translations-setup means that Catalan (in the | ||||
|    Valencian dialect), Occitan (Lenga d'Oc) and Serbian (in Latin script) | ||||
|    are all better supported. Thanks Enrique. | ||||
|  | ||||
| ## Modules ## | ||||
|  - *netinstall* Now displays entries with an empty name slightly differently. | ||||
|    An empty name is not generally useful, but in combination with | ||||
|    *immutable:true* and *selected:false* can be used to introduce separators | ||||
|    or descriptive comments into the list of packages. | ||||
|  - *partition* does not offer full-disk encryption when using ZFS. ZFS and the | ||||
|    way Calamares sets up FDE don't mix well. (Thanks Evan) | ||||
|  - *partition* Various bugs related to LUKS have been fixed. (Thanks Arjen) | ||||
|  - *users* module now has a structured *user* key with settings specific | ||||
|    to the user (shell, in particular). This maintains backwards compatibility | ||||
|    with the *userShell* key. | ||||
|  - *users* module now has lists of forbidden login- and host-names, to | ||||
|    avoid settings that will mess up the install (e.g. using a login-name | ||||
|    that is one of the system's reserved names). #1944 | ||||
|  | ||||
|  | ||||
| # 3.2.57 (2022-05-04) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Arjen Balfoort (new contributor! Welcome!) | ||||
|  - Victor Fuentes | ||||
|  | ||||
| ## Core ## | ||||
|  - Calamares can now be started in Serbian (Latin Script) and Catalan | ||||
|    (Valencia) when the LANG environment variable is set to values | ||||
|    that indicate those languages. | ||||
|  | ||||
| ## Modules ## | ||||
|  - *fstab* and *luksbootkeyfile* have better support for an **un**encrypted | ||||
|    `/boot` partition. #1931 (thanks Arjen) | ||||
|  - *packagechooser* and *packagechooserq* can now be given a custom name | ||||
|    in the side-panel. #1932 (thanks Victor) | ||||
|  | ||||
|  | ||||
| # 3.2.56 (2022-04-22) # | ||||
|  | ||||
| As of this release, Calamares 3.2 development is winding down. The | ||||
| reason is simple: systems where the backwards-compatibility of Calamares | ||||
| 3.2 is important are becoming increasingly difficult to work with | ||||
| for **other** reasons. Foremost among these are deprecated versions | ||||
| of dependencies and tools. Calamares 3.2 branch remains open for | ||||
| bugfixes and will see a few more releases, but development is now | ||||
| shifting wholesale to the newer generation. | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Victor Fuentes (new contributor! Welcome!) | ||||
|  | ||||
| ## Core ## | ||||
|  - Changes in git forced some changes on the CI tooling. | ||||
|  | ||||
| ## Modules ## | ||||
|  - *locale* showed the wrong timezone for Dhaka, although it configured | ||||
|    the correct one. #1929 | ||||
|  - *users* module sets global storage key *fullname* to the full name | ||||
|    of the user (e.g. what is entered in the "your full name" box on the | ||||
|    users page). #1923 (Thanks Victor) | ||||
|  | ||||
|  | ||||
| # 3.2.55 (2022-04-11) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - vtriolet (new contributor! Welcome!) | ||||
|  | ||||
| ## Core ## | ||||
|  - `readTargetFile()` did not properly return all the lines of the target | ||||
|    file. #1918 (thanks vtriolet) | ||||
|  | ||||
| ## Modules ## | ||||
|  - *users* module has rearranged configuration for setting the hostname. | ||||
|    Legacy settings are preserved, but produce a warning. Please see | ||||
|    `users.conf` for details. | ||||
|  - *users* module has a new hostname.location setting, *Transient*, which | ||||
|    will force the installed system to transient-hostname-setting by removing | ||||
|    the file `/etc/hostname`. | ||||
|  - *users* module has a new hostname.template setting, which allows some | ||||
|    tweaking of how the hostname suggestion is constructed. In particular, | ||||
|    it can be configured to use the current hostname (whatever that may be). | ||||
|    See the example `users.conf` for details on available keys. | ||||
|  | ||||
|  | ||||
| # 3.2.54 (2022-03-21) # | ||||
|  | ||||
| This release contains contributions from (alphabetically): | ||||
|  - Bob van der Linden (new contributor! Welcome!) | ||||
|  - El-Wumbus (new contributor! Welcome!) | ||||
|  - Evan James | ||||
|  - Santosh Mahto (new contributor! Welcome!) | ||||
|  | ||||
| ## Core ## | ||||
|  - During the installation ("exec") step, while the slideshow is displayed, | ||||
|    there is also a button to show the scrolling installation log as it | ||||
|    is written. (Thanks Bob) | ||||
|  | ||||
| ## Modules ## | ||||
|  - *fstab* module correctly handles empty UUID strings. (Thanks Evan) | ||||
|  - *partition* module no longer forgets configured partition-layouts. | ||||
|    It also respects configured partition labels better. (Thanks Santosh) | ||||
|  | ||||
|  | ||||
| # 3.2.53 (2022-03-04) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Huang Jia Wen (new contributor! Welcome!) | ||||
|  | ||||
| ## Core ## | ||||
|  - Automount-manipulation (to switch off KDE Plasma automounting new devices) | ||||
|    now logs slightly more as it works. Defaults have changed in KDE Plasma | ||||
|    5.24 and it turns out the automount-manipulation does not work well. | ||||
|    Distro's are encouraged to turn off automount in the live ISO (see #1885). | ||||
|  | ||||
| ## Modules ## | ||||
|  - *bootloader* now knows about loongarch64 and can install suitable EFI | ||||
|    files for this CPU type. (Thanks Huang Jia Wen) | ||||
|  - Progress reporting for `pacman` from the *packages* module has been switched | ||||
|    off. The progress reporting works under low load, but there are many reports | ||||
|    of it crashing (from XeroLinux and from Evan James, who has been debugging | ||||
|    the issue) during a regular installation with thousands of updates. This | ||||
|    will be revisited in the next release. | ||||
|  - The *umount* module was buggy and did not actually unmount anything. | ||||
|  | ||||
|  | ||||
| # 3.2.52 (2022-02-25) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Evan James | ||||
|  | ||||
| ## Core ## | ||||
|  - No core changes yet | ||||
|  | ||||
| ## Modules ## | ||||
|  - *fstab* recognizes nvme and mmc devices correctly as SSDs now. #1883 | ||||
|  - *luksbootkeyfile* handles trailing slashes in mount point | ||||
|  - *partition* can be built with a new `SKIP` option, which skips | ||||
|    the actual formatting steps but does not fail. The old `LAME` | ||||
|    option is renamed `BAIL_OUT`. | ||||
|  - *users* has a new key *sudoersConfigureWithGroup* to allow for | ||||
|    different styles of sudo configuration. #1887 | ||||
|  | ||||
|  | ||||
| # 3.2.51 (2022-02-01) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Evan James | ||||
|  | ||||
| **WARNING** The *umount* module has been rewritten in C++. Check your | ||||
| configuration if you previously used the copy-a-log functionality. | ||||
|  | ||||
| ## Core ## | ||||
|  - Evan has made a start on documenting which Global Storage keys there | ||||
|    are and how they tie modules together. This can be found in the | ||||
|    `src/modules/README.md` documentation. | ||||
|  | ||||
| ## Modules ## | ||||
|  - *bootloader* can now be configured to try to generate a unique | ||||
|    suffix for the bootloader-id. #1820 | ||||
|  - *grubcfg* now has a configurable default for kernel parameters, | ||||
|    which allows distributions to change the value from `quiet`. | ||||
|    The default, if nothing is set, remains `quiet`. Use an explicitly- | ||||
|    empty list to specify no-arguments-at-all. | ||||
|  - *packagechooser* can now export its choices for use by the *netinstall* | ||||
|    module. This makes it possible to use *packagechooser* for large-scale | ||||
|    choices, followed by *netinstall* for fine-grained control. (Thanks Evan) | ||||
|  - When the *partition* module has a conflicting configuration for the | ||||
|    swap choices, it prints a warning and uses the configured choice, rather | ||||
|    than always using "suspend". #1881 | ||||
|  - The *umount* module has been re-written in C++. The copy-a-log-file | ||||
|    functionality has been removed. Use the *preservefiles* module for that. | ||||
|  | ||||
|  | ||||
| # 3.2.50 (2022-01-18) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Anke Boersma | ||||
|  - Erik Dubois | ||||
|  - Evan James | ||||
|  - Johannes Kamprad | ||||
|  - Taejun Park (new contributor, welcome!) | ||||
|  | ||||
| **Replacement notice:** The *umount* module will be replaced by a C++ | ||||
| implementation in the next release. The "preserve log file" feature | ||||
| will be removed in that release. Use the *preservefiles* module instead. | ||||
|  | ||||
| ## Core ## | ||||
|  - No core changes yet | ||||
|  | ||||
| ## Modules ## | ||||
|  - *initcpiocfg* mentioned a special kernel-name "all", which did not work, | ||||
|    and a special kernel-name "$uname" which cannot work. Fixed the former | ||||
|    and removed the "$uname" special key. (Thanks Evan) | ||||
|  - *luksswaphookcfg* has been converted to a C++ module. | ||||
|  - *networkcfg* could fail to update the NetworkManager configuration | ||||
|    if the SSID or username contained non-ASCII characters **and** the | ||||
|    default Python text-file encoding was set to ASCII. The files are | ||||
|    now read and written in UTF-8, explicitly. #1848 | ||||
|  - *partition* always sets *bigtime* option on XFS filesystems, if possible. | ||||
|    Requires sufficiently-recent xfsprogs. #1874 | ||||
|  - *preservefiles* was missing some necessary features, needed for it | ||||
|    to replace the deprecated log-file-saving functionality in the *umount* | ||||
|    module. (Thanks Erik and Joe for testing) #1851 | ||||
|  - *umount* is now marked as an emergency module in the example configuration, | ||||
|    since it should **probably** be run as a cleanup. (Thanks Evan) | ||||
|  - *welcome* and *locale* could be confusing, together, and configure | ||||
|    the target system with a language that does not match the installer | ||||
|    language, even though the user did not make any explicit choice. | ||||
|    (Thanks Taejun) #1864 | ||||
|  | ||||
|  | ||||
| # 3.2.49.1 (2021-12-11) # | ||||
|  | ||||
| This is a hot-fix release, to fix a regression in the calculation of | ||||
| swap-size. Reported by EndeavourOS (Joe Kamprad) and Xero Linux. | ||||
|  | ||||
|  | ||||
| # 3.2.49 (2021-12-10) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Artem Grinev | ||||
|  - Evan James | ||||
|  | ||||
| Distributions are **specifically** reminded to update the *umount* module | ||||
| configuration (and to use *preservefiles* if needed). | ||||
|  | ||||
| ## Core ## | ||||
|  - Errors (e.g. when an installation fails for whatever reason) are displayed | ||||
|    in a dialog with a scrollable details panel, rather than growing up | ||||
|    to the size of the screen. (Thanks Artem) | ||||
|  | ||||
| ## Modules ## | ||||
|  - *bootloader* better supports multiple installations of the same OS. | ||||
|  - *mount* supports btrfs subvolumes on subdirectories of / now. | ||||
|  - *partition* now supports "deep" btrfs subvolume names, e.g. a | ||||
|    separate subvolume for `/usr/local`. (Thanks Evan) | ||||
|  - The *umount* module now warns if the "preserve log file" feature is used. | ||||
|    This has been deprecated for a long time: use the *preservefiles* module | ||||
|    instead. A future release will turn this into an error. | ||||
|  | ||||
|  | ||||
| # 3.2.48 (2021-12-03) # | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|   | ||||
							
								
								
									
										293
									
								
								CHANGES-3.3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								CHANGES-3.3
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,293 @@ | ||||
| <!-- 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.1 (unreleased) | ||||
|  | ||||
| This release contains contributions from (alphabetically by first name): | ||||
|  - Adriaan de Groot | ||||
|  - Aleksey Samoilov | ||||
|  - Emir Sari | ||||
|  | ||||
| ## Core ## | ||||
|  - No changes of note. | ||||
|  | ||||
| ## 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 `@@`. | ||||
|  | ||||
							
								
								
									
										702
									
								
								CMakeLists.txt
									
									
									
									
									
								
							
							
						
						
									
										702
									
								
								CMakeLists.txt
									
									
									
									
									
								
							| @@ -19,54 +19,78 @@ | ||||
| # | ||||
| #   SKIP_MODULES    : a space or semicolon-separated list of directory names | ||||
| #                     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 | ||||
| #                     a list of WITH_<foo> grep CMakeCache.txt after running | ||||
| #                     CMake once. These affect the ABI offered by Calamares. | ||||
| #                       - PYTHON (enable Python Job modules) | ||||
| #                       - QML (enable QML UI View modules) | ||||
| #                       - PYTHONQT # TODO:3.3: remove | ||||
| #                       - PYBIND11 (use bundled pybind11, default ON, needs WITH_PYTHON) | ||||
| #                       - PYTHON (enable Python Job modules, default ON if Python is found) | ||||
| #                       - 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 | ||||
| #                       - 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) | ||||
| #   DEBUG_<foo>     : special developer flags for debugging | ||||
| #                       - TESTING (standard CMake option) | ||||
| #   DEBUG_<foo>     : special developer flags for debugging. | ||||
| # | ||||
| # Example usage: | ||||
| # | ||||
| #   cmake . -DSKIP_MODULES="partition luksbootkeycfg" | ||||
| # | ||||
| # One special target is "show-version", which can be built | ||||
| # to obtain the version number from here. | ||||
| # To obtain the version number of calamares, run CMake in script mode, e.g. | ||||
| #   cmake -P CMakeLists.txt | ||||
|  | ||||
| # TODO:3.3: Require CMake 3.12 | ||||
| cmake_minimum_required( VERSION 3.3 FATAL_ERROR ) | ||||
| project( CALAMARES | ||||
|     VERSION 3.2.48 | ||||
|     LANGUAGES C CXX | ||||
| ) | ||||
| cmake_minimum_required(VERSION 3.16 FATAL_ERROR) | ||||
|  | ||||
| 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 ) | ||||
|     message( FATAL_ERROR "Do not build development versions in the source-directory." ) | ||||
| set(CALAMARES_VERSION 3.3.1) | ||||
| set(CALAMARES_RELEASE_MODE OFF) # Set to ON during a release | ||||
|  | ||||
| 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.") | ||||
| 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 | ||||
| # | ||||
| option( INSTALL_CONFIG "Install configuration files" OFF ) | ||||
| option( INSTALL_POLKIT "Install Polkit configuration" ON ) | ||||
| option( INSTALL_COMPLETION "Install shell completions" OFF ) | ||||
| # Options for the calamares executable | ||||
| 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 | ||||
| option(INSTALL_POLKIT "Install Polkit configuration" ON) | ||||
| option(INSTALL_COMPLETION "Install shell completions" OFF) | ||||
| option(INSTALL_CONFIG "Install configuration files" OFF) | ||||
| # When adding WITH_* that affects the ABI offered by libcalamares, | ||||
| # also update libcalamares/CalamaresConfig.h.in | ||||
| option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON ) | ||||
| option( WITH_PYTHONQT "Enable Python view modules API (deprecated, requires PythonQt)." OFF )  # TODO:3.3: remove | ||||
| option( WITH_QML "Enable QML UI options." ON ) | ||||
| option(WITH_PYBIND11 "Use bundled pybind11 instead o Boost::Python" ON) | ||||
| option(WITH_PYTHON "Enable Python modules API." ON) | ||||
| option(WITH_QML "Enable QML UI options." ON) | ||||
| option(WITH_QT6 "Use Qt6 instead of Qt5" OFF) | ||||
| # | ||||
| # Additional parts to build | ||||
| option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON ) | ||||
|  | ||||
| # Additional parts to build that do not affect ABI | ||||
| 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: | ||||
| #  - DEBUG_TIMEZONES draws latitude and longitude lines on the timezone | ||||
| @@ -75,8 +99,7 @@ option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON ) | ||||
| #  - DEBUG_FILESYSTEMS does extra logging and checking when looking at | ||||
| #    partition configuration. Lists known KPMCore FS types. | ||||
| #  - DEBUG_PARTITION_UNSAFE (see partition/CMakeLists.txt) | ||||
| #  - DEBUG_PARTITION_LAME (see partition/CMakeLists.txt) | ||||
|  | ||||
| #  - DEBUG_PARTITION_BAIL_OUT (see partition/CMakeLists.txt) | ||||
|  | ||||
| ### USE_* | ||||
| # | ||||
| @@ -101,15 +124,14 @@ option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON ) | ||||
| #  - *services* picks one of the two service-configuration modules, | ||||
| #    for either systemd or openrc. This defaults to empty so that | ||||
| #    **both** modules are available. | ||||
| set( USE_services "" CACHE STRING "Select the services module to use" ) | ||||
| set(USE_services "" CACHE STRING "Select the services module to use") | ||||
|  | ||||
| ### Calamares application info | ||||
| # | ||||
| set( CALAMARES_ORGANIZATION_NAME "Calamares" ) | ||||
| set( CALAMARES_ORGANIZATION_DOMAIN "github.com/calamares" ) | ||||
| set( CALAMARES_APPLICATION_NAME  "Calamares" ) | ||||
| set( CALAMARES_DESCRIPTION_SUMMARY | ||||
|     "The distribution-independent installer framework" ) | ||||
| set(CALAMARES_ORGANIZATION_NAME "Calamares") | ||||
| set(CALAMARES_ORGANIZATION_DOMAIN "github.com/calamares") | ||||
| set(CALAMARES_APPLICATION_NAME "Calamares") | ||||
| set(CALAMARES_DESCRIPTION_SUMMARY "The distribution-independent installer framework") | ||||
|  | ||||
| ### Transifex (languages) info | ||||
| # | ||||
| @@ -120,56 +142,77 @@ set( CALAMARES_DESCRIPTION_SUMMARY | ||||
| # | ||||
| # Language en (source language) is added later. It isn't listed in | ||||
| # 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. | ||||
| # | ||||
| # When adding a new language, take care that it is properly loaded | ||||
| # by the translation framework. Languages with alternate scripts | ||||
| # (sr@latin in particular) may need special handling in CalamaresUtils.cpp. | ||||
| # (sr@latin in particular) or location (ca@valencia) need special | ||||
| # handling in libcalamares/locale/Translation.h . | ||||
| # | ||||
| # TODO: drop the es_ES translation from Transifex | ||||
| # | ||||
| # 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: update these lines by running `txstats.py`, or for full automation | ||||
| #       `txstats.py -e`. See also | ||||
| # | ||||
| # Total 81 languages | ||||
| set( _tx_complete az az_AZ ca de fa fi_FI he hr ja ko lt pt_PT si | ||||
|     sq tr_TR uk zh_TW ) | ||||
| set( _tx_good as be ca@valencia cs_CZ da fr fur hi it_IT ml nl | ||||
|     pt_BR ru sk sv tg vi zh_CN ) | ||||
| set( _tx_ok ar ast bg bn el en_GB es es_MX et eu gl hu id is mr nb | ||||
|     pl ro sl sr sr@latin th ) | ||||
| set( _tx_incomplete en_HK en_IN eo es_PE es_PR fr_CH gu hi_IN id_ID | ||||
|     ie kk kn ko_KR lo lv mk ne ne_NP te te_IN ur zh zh_HK ) | ||||
| # Total 80 languages | ||||
| set( _tx_complete az_AZ ca en es fi_FI fr he hr ja lt pl sq sv | ||||
|     tr_TR uk zh_TW ) | ||||
| set( _tx_good as az be bg ca@valencia cs_CZ da de fa fur hi is | ||||
|     it_IT ko nl pt_BR pt_PT ru si sk tg vi zh_CN ) | ||||
| set( _tx_ok ar ast bn el en_GB eo es_AR es_MX et eu gl hu id ml mr | ||||
|     nb oc ro sl sr sr@latin th ) | ||||
| set( _tx_incomplete bqi es_PR gu ie ja-Hira ka kk kn lo lv mk ne_NP | ||||
|     ro_RO ta_IN te ur uz zh zh_HK ) | ||||
| # Total 80 languages | ||||
|  | ||||
| ### Required versions | ||||
| # | ||||
| # 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 ) | ||||
| 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) | ||||
| set(PYTHONLIBS_VERSION 3.6) | ||||
| set(YAMLCPP_VERSION 0.5.1) | ||||
|  | ||||
| ### CMAKE SETUP | ||||
| # | ||||
| set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules" ) | ||||
| set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules") | ||||
|  | ||||
| # Enable IN_LIST | ||||
| if( POLICY CMP0057 ) | ||||
|     cmake_policy( SET CMP0057 NEW ) | ||||
| if(POLICY CMP0057) | ||||
|     cmake_policy(SET CMP0057 NEW) | ||||
| endif() | ||||
| # Let ``AUTOMOC`` and ``AUTOUIC`` process ``GENERATED`` files. | ||||
| if( POLICY CMP0071 ) | ||||
|     cmake_policy( SET CMP0071 NEW ) | ||||
| if(POLICY CMP0071) | ||||
|     cmake_policy(SET CMP0071 NEW) | ||||
| endif() | ||||
| # 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_EXPORT_PLASMA_DATAENGINE_WITH_JSON" | ||||
|         "K_EXPORT_PLASMA_RUNNER" | ||||
| @@ -177,40 +220,50 @@ if(NOT CMAKE_VERSION VERSION_LESS "3.10.0") | ||||
| endif() | ||||
|  | ||||
| # CMake Modules | ||||
| include( CMakePackageConfigHelpers ) | ||||
| include( CTest ) | ||||
| include( FeatureSummary ) | ||||
| include(CMakePackageConfigHelpers) | ||||
| include(CTest) | ||||
| include(FeatureSummary) | ||||
|  | ||||
| # Calamares Modules | ||||
| include( CMakeColors ) | ||||
| include(CMakeColors) | ||||
|  | ||||
| ### C++ SETUP | ||||
| # | ||||
| set( CMAKE_CXX_STANDARD 17 ) | ||||
| set( CMAKE_CXX_STANDARD_REQUIRED ON ) | ||||
| set( CMAKE_CXX_FLAGS                "${CMAKE_CXX_FLAGS} -Wall -Werror=return-type" ) | ||||
| set( CMAKE_CXX_FLAGS_DEBUG          "-Og -g ${CMAKE_CXX_FLAGS_DEBUG}" ) | ||||
| set( CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG" ) | ||||
| set( CMAKE_CXX_FLAGS_RELEASE        "-O3 -DNDEBUG" ) | ||||
| set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g" ) | ||||
| set(CMAKE_CXX_STANDARD 17) | ||||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror=return-type") | ||||
| set(CMAKE_CXX_FLAGS_DEBUG "-Og -g ${CMAKE_CXX_FLAGS_DEBUG}") | ||||
| set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") | ||||
| set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") | ||||
| set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") | ||||
|  | ||||
| set( CMAKE_C_STANDARD 99 ) | ||||
| set( CMAKE_C_STANDARD_REQUIRED ON ) | ||||
| set( CMAKE_C_FLAGS                  "${CMAKE_C_FLAGS} -Wall" ) | ||||
| set( CMAKE_C_FLAGS_DEBUG            "-Og -g" ) | ||||
| set( CMAKE_C_FLAGS_MINSIZEREL       "-Os -DNDEBUG" ) | ||||
| set( CMAKE_C_FLAGS_RELEASE          "-O4 -DNDEBUG" ) | ||||
| set( CMAKE_C_FLAGS_RELWITHDEBINFO   "-O2 -g" ) | ||||
| set(CMAKE_C_STANDARD 99) | ||||
| set(CMAKE_C_STANDARD_REQUIRED ON) | ||||
| set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") | ||||
| set(CMAKE_C_FLAGS_DEBUG "-Og -g") | ||||
| set(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG") | ||||
| set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") | ||||
| 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( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) | ||||
|     message( STATUS "Found Clang ${CMAKE_CXX_COMPILER_VERSION}, setting up Clang-specific compiler 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") | ||||
|     message(STATUS "Found Clang ${CMAKE_CXX_COMPILER_VERSION}, setting up Clang-specific compiler flags.") | ||||
|  | ||||
|     # Clang warnings: doing *everything* is counter-productive, since it warns | ||||
|     # about things which we can't fix (e.g. C++98 incompatibilities, but | ||||
|     # Calamares is C++17). | ||||
|     foreach( CLANG_WARNINGS | ||||
|     foreach( | ||||
|         CLANG_WARNINGS | ||||
|         -Weverything | ||||
|         -Wno-c++98-compat | ||||
|         -Wno-c++98-compat-pedantic | ||||
| @@ -222,229 +275,247 @@ if( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) | ||||
|         -Wno-documentation-unknown-command | ||||
|         -Wno-unknown-warning-option | ||||
|     ) | ||||
|         string( APPEND CMAKE_CXX_FLAGS " ${CLANG_WARNINGS}" ) | ||||
|         string(APPEND CMAKE_CXX_FLAGS " ${CLANG_WARNINGS}") | ||||
|     endforeach() | ||||
|  | ||||
|     # The dwarf-debugging flags are slightly different, too | ||||
|     string( APPEND CMAKE_CXX_FLAGS_DEBUG " -gdwarf" ) | ||||
|     string( APPEND CMAKE_C_FLAGS_DEBUG " -gdwarf" ) | ||||
|     string(APPEND CMAKE_CXX_FLAGS_DEBUG " -gdwarf") | ||||
|     string(APPEND CMAKE_C_FLAGS_DEBUG " -gdwarf") | ||||
|  | ||||
|     # Third-party code where we don't care so much about compiler warnings | ||||
|     # (because it's uncomfortable to patch) get different flags; use | ||||
|     #       mark_thirdparty_code( <file> [<file>...] ) | ||||
|     # to switch off warnings for those sources. | ||||
|     set( SUPPRESS_3RDPARTY_WARNINGS "-Wno-everything" ) | ||||
|     set(SUPPRESS_3RDPARTY_WARNINGS "-Wno-everything") | ||||
|  | ||||
|     set( CMAKE_TOOLCHAIN_PREFIX "llvm-" ) | ||||
|     set(CMAKE_TOOLCHAIN_PREFIX "llvm-") | ||||
|  | ||||
|     # The path prefix is only relevant for CMake 3.16 and later, fixes #1286 | ||||
|     set( CMAKE_AUTOMOC_PATH_PREFIX OFF ) | ||||
|     set( CALAMARES_AUTOMOC_OPTIONS "-butils/moc-warnings.h" ) | ||||
|     set( CALAMARES_AUTOUIC_OPTIONS --include utils/moc-warnings.h ) | ||||
|     set(CMAKE_AUTOMOC_PATH_PREFIX OFF) | ||||
|     set(CALAMARES_AUTOMOC_OPTIONS "-butils/moc-warnings.h") | ||||
|     set(CALAMARES_AUTOUIC_OPTIONS --include utils/moc-warnings.h) | ||||
| else() | ||||
|     set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual" ) | ||||
|     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual") | ||||
|  | ||||
|     set( SUPPRESS_3RDPARTY_WARNINGS "" ) | ||||
|     set(SUPPRESS_3RDPARTY_WARNINGS "") | ||||
| endif() | ||||
|  | ||||
| # 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. | ||||
| macro(mark_thirdparty_code) | ||||
|     set_source_files_properties( ${ARGV} | ||||
|         PROPERTIES | ||||
|             COMPILE_FLAGS "${SUPPRESS_3RDPARTY_WARNINGS}" | ||||
|             COMPILE_DEFINITIONS "THIRDPARTY" | ||||
|     set_source_files_properties( | ||||
|         ${ARGV} | ||||
|         PROPERTIES COMPILE_FLAGS "${SUPPRESS_3RDPARTY_WARNINGS}" COMPILE_DEFINITIONS "THIRDPARTY" | ||||
|     ) | ||||
| endmacro() | ||||
|  | ||||
| if( CMAKE_COMPILER_IS_GNUCXX ) | ||||
|     if( CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9 OR | ||||
|         CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.9 ) | ||||
|         message( STATUS "Found GNU g++ ${CMAKE_CXX_COMPILER_VERSION}, enabling colorized error messages." ) | ||||
|         set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=auto" ) | ||||
| if(CMAKE_COMPILER_IS_GNUCXX) | ||||
|     if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.9) | ||||
|         message(STATUS "Found GNU g++ ${CMAKE_CXX_COMPILER_VERSION}, enabling colorized error messages.") | ||||
|         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=auto") | ||||
|     endif() | ||||
| endif() | ||||
|  | ||||
|  | ||||
| ### DEPENDENCIES | ||||
| # | ||||
| find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Concurrent Core Gui LinguistTools Network Svg Widgets ) | ||||
| if( WITH_QML ) | ||||
|     find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Quick QuickWidgets ) | ||||
| find_package(${qtname} ${QT_VERSION} CONFIG REQUIRED Concurrent Core DBus Gui LinguistTools Network Svg Widgets) | ||||
| if(WITH_QML) | ||||
|     find_package(${qtname} ${QT_VERSION} CONFIG REQUIRED Quick QuickWidgets) | ||||
| endif() | ||||
| # Optional Qt parts | ||||
| find_package( Qt5DBus CONFIG ) | ||||
| # Note that some modules need more Qt modules, optionally. | ||||
|  | ||||
| find_package( YAMLCPP ${YAMLCPP_VERSION} REQUIRED ) | ||||
| if( INSTALL_POLKIT ) | ||||
|     find_package( PolkitQt5-1 REQUIRED ) | ||||
| else() | ||||
|     # Find it anyway, for dependencies-reporting | ||||
|     find_package( PolkitQt5-1 ) | ||||
| 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) | ||||
|     set_package_properties( | ||||
|         Polkit${qtname}-1 | ||||
|         PROPERTIES | ||||
|         TYPE REQUIRED | ||||
|     ) | ||||
| endif() | ||||
| set_package_properties( | ||||
|     PolkitQt5-1 PROPERTIES | ||||
|     DESCRIPTION "Qt5 support for Polkit" | ||||
|     Polkit${qtname}-1 | ||||
|     PROPERTIES | ||||
|     DESCRIPTION "${qtname} support for Polkit" | ||||
|     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 | ||||
| # 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. | ||||
| 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}) | ||||
|     if ( BUILD_TESTING ) | ||||
|     if(BUILD_TESTING) | ||||
|         # ECM implies that we can build the tests, too | ||||
|         find_package( Qt5 COMPONENTS Test REQUIRED ) | ||||
|         include( ECMAddTests ) | ||||
|         find_package(${qtname} COMPONENTS Test REQUIRED) | ||||
|         include(ECMAddTests) | ||||
|     endif() | ||||
|     include(KDEInstallDirs) | ||||
| endif() | ||||
|  | ||||
| find_package( KF5 QUIET COMPONENTS CoreAddons Crash DBusAddons ) | ||||
| find_package(${kfname}CoreAddons ${KF_VERSION} QUIET) | ||||
| set_package_properties( | ||||
|     KF5::CoreAddons PROPERTIES | ||||
|     ${kfname}CoreAddons | ||||
|     PROPERTIES | ||||
|     TYPE REQUIRED | ||||
|     DESCRIPTION "Classes built on QtCore for About Data" | ||||
|     URL "https://api.kde.org/frameworks/kcoreaddons/" | ||||
|     PURPOSE "About Calamares" | ||||
|     DESCRIPTION "KDE Framework CoreAddons" | ||||
|     URL "https://api.kde.org/frameworks/" | ||||
|     PURPOSE "Essential Framework for AboutData and Macros" | ||||
| ) | ||||
| if( NOT KF5Crash_FOUND ) | ||||
|     if( WITH_KF5Crash ) | ||||
|         message(WARNING "WITH_KF5Crash is set, but KF5::Crash is not available.") | ||||
|     endif() | ||||
|     set( WITH_KF5Crash 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() | ||||
|  | ||||
| # TODO:3.3: Use FindPython3 instead | ||||
| find_package( PythonInterp ${PYTHONLIBS_VERSION} ) | ||||
| # After this point, there should be no REQUIRED find_packages, | ||||
| # 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( | ||||
|     PythonInterp PROPERTIES | ||||
|     DESCRIPTION "Python 3 interpreter." | ||||
|     URL "https://python.org" | ||||
|     PURPOSE "Python 3 interpreter for certain tests." | ||||
|     ${kfname}Crash | ||||
|     PROPERTIES | ||||
|     TYPE OPTIONAL | ||||
|     DESCRIPTION "KDE Framework Crash" | ||||
|     URL "https://api.kde.org/frameworks/" | ||||
|     PURPOSE "Framework for sending Crash Dumps" | ||||
| ) | ||||
|  | ||||
| set( _schema_explanation "" ) | ||||
| if ( PYTHONINTERP_FOUND ) | ||||
|     if ( BUILD_SCHEMA_TESTING ) | ||||
| if(NOT TARGET ${kfname}::Crash) | ||||
|     if(BUILD_CRASH_REPORTING) | ||||
|         message(WARNING "BUILD_CRASH_REPORTING is set, but ${kfname}::Crash is not available.") | ||||
|     endif() | ||||
|     set(BUILD_CRASH_REPORTING OFF) | ||||
| endif() | ||||
|  | ||||
| find_package(Python ${PYTHONLIBS_VERSION} COMPONENTS Interpreter Development) | ||||
| set_package_properties( | ||||
|     Python | ||||
|     PROPERTIES | ||||
|     DESCRIPTION "Python3 interpreter." | ||||
|     URL "https://python.org" | ||||
|     PURPOSE "Python3 interpreter for certain tests." | ||||
| ) | ||||
|  | ||||
| set(_schema_explanation "") | ||||
| if(Python_Interpreter_FOUND) | ||||
|     if(BUILD_SCHEMA_TESTING) | ||||
|         # The configuration validator script has some dependencies, | ||||
|         # and if they are not installed, don't run. If errors out | ||||
|         # with exit(1) on missing dependencies. | ||||
|         if ( CALAMARES_CONFIGVALIDATOR_CHECKED ) | ||||
|             set( _validator_deps ${CALAMARES_CONFIGVALIDATOR_RESULT} ) | ||||
|         if(CALAMARES_CONFIGVALIDATOR_CHECKED) | ||||
|             message(STATUS "Using cached config-validation result") | ||||
|             set(_validator_deps ${CALAMARES_CONFIGVALIDATOR_RESULT}) | ||||
|         else() | ||||
|             exec_program( ${PYTHON_EXECUTABLE} ARGS "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" -x RETURN_VALUE _validator_deps ) | ||||
|             set( CALAMARES_CONFIGVALIDATOR_CHECKED TRUE CACHE INTERNAL "Dependencies for configvalidator checked" ) | ||||
|             set( CALAMARES_CONFIGVALIDATOR_RESULT ${_validator_deps} CACHE INTERNAL "Result of configvalidator dependency check" ) | ||||
|             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_RESULT ${_validator_deps} | ||||
|                 CACHE INTERNAL "Result of configvalidator dependency check" | ||||
|             ) | ||||
|         endif() | ||||
|         # It should never succeed, but only returns 1 when the imports fail | ||||
|         if ( _validator_deps EQUAL 1 ) | ||||
|             set( _schema_explanation " Missing dependencies for configvalidator.py." ) | ||||
|             set( BUILD_SCHEMA_TESTING OFF ) | ||||
|         if(_validator_deps EQUAL 1) | ||||
|             message(STATUS "Checked for config-validation dependencies: NOT-FOUND") | ||||
|             set(_schema_explanation " Missing dependencies for configvalidator.py.") | ||||
|             set(BUILD_SCHEMA_TESTING OFF) | ||||
|         else() | ||||
|             message(STATUS "Checked for config-validation dependencies: found") | ||||
|         endif() | ||||
|     else() | ||||
|         set(CALAMARES_CONFIGVALIDATOR_CHECKED OFF CACHE INTERNAL "Dependencies for configvalidator checked") | ||||
|     endif() | ||||
| else() | ||||
|     # Can't run schema tests without Python3. | ||||
|     set( _schema_explanation " Missing Python3." ) | ||||
|     set( BUILD_SCHEMA_TESTING OFF ) | ||||
|     set(_schema_explanation " Missing Python3.") | ||||
|     set(BUILD_SCHEMA_TESTING OFF) | ||||
|     set(CALAMARES_CONFIGVALIDATOR_CHECKED OFF CACHE INTERNAL "Dependencies for configvalidator checked") | ||||
| 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} ) | ||||
| set_package_properties( | ||||
|     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(NOT Python_Development_FOUND) | ||||
|     message(STATUS "Disabling Python modules") | ||||
|     set(WITH_PYTHON OFF) | ||||
|     set(WITH_PYBIND11 OFF) | ||||
| endif() | ||||
|  | ||||
| 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." | ||||
| if(WITH_PYTHON AND NOT WITH_PYBIND11) | ||||
|     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 | ||||
|         ) | ||||
|     # 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 ) | ||||
| endif() | ||||
| if( NOT PYTHONLIBS_FOUND OR NOT PYTHONQT_FOUND ) | ||||
|     message(STATUS "Disabling PythonQt modules") | ||||
|     set( WITH_PYTHONQT OFF ) | ||||
|     else() | ||||
|         message(STATUS "Found boost_python with target Boost::python") | ||||
|         set(Boost_FOUND ON) | ||||
|     endif() | ||||
| endif() | ||||
|  | ||||
| # Now we know the state of the ABI-options, copy them into "Calamares_" | ||||
| # prefixed variables, to match how the variables would-be-named | ||||
| # when building out-of-tree. | ||||
| set(Calamares_WITH_PYBIND11 ${WITH_PYBIND11}) | ||||
| set(Calamares_WITH_PYTHON ${WITH_PYTHON}) | ||||
| set(Calamares_WITH_PYTHONQT ${WITH_PYTHONQT}) | ||||
| set(Calamares_WITH_QML ${WITH_QML}) | ||||
| set(Calamares_WITH_QT6 ${WITH_QT6}) | ||||
|  | ||||
| ### Transifex Translation status | ||||
| # | ||||
| # Construct language lists for use. This massages the language lists | ||||
| # for use with older Qt (which does not support Esperanto) and checks | ||||
| # for some obvious error. The actual work of compiling translations | ||||
| # is done in the lang/ directory. | ||||
| # Construct language lists for use. This massages the language lists if | ||||
| # needed and checks for some obvious errors. The actual work of | ||||
| # compiling translations 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( tx_errors OFF ) | ||||
| if ( curr_tx ) | ||||
| set(curr_tx ${_tx_complete} ${_tx_good} ${_tx_ok} ${_tx_incomplete}) | ||||
| set(tx_errors OFF) | ||||
| if(curr_tx) | ||||
|     # New in list | ||||
|     foreach( l ${curr_tx} ) | ||||
|         set( p_l "lang/calamares_${l}.ts" ) | ||||
|         if( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${p_l} ) | ||||
|     foreach(l ${curr_tx}) | ||||
|         set(p_l "lang/calamares_${l}.ts") | ||||
|         if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${p_l}) | ||||
|             message(WARNING "Language ${l} has no .ts file yet.") | ||||
|             set( tx_errors ON ) | ||||
|             set(tx_errors ON) | ||||
|         endif() | ||||
|     endforeach() | ||||
|  | ||||
|     unset( p_l ) | ||||
|     unset( l ) | ||||
|     unset(p_l) | ||||
|     unset(l) | ||||
| endif() | ||||
| unset( curr_tx ) | ||||
| if( tx_errors ) | ||||
|     message( FATAL_ERROR "Translation warnings, see above." ) | ||||
| unset(curr_tx) | ||||
| if(tx_errors) | ||||
|     message(FATAL_ERROR "Translation warnings, see above.") | ||||
| endif() | ||||
|  | ||||
| set( CALAMARES_TRANSLATION_LANGUAGES en ${_tx_complete} ${_tx_good} ${_tx_ok} ) | ||||
| list( SORT CALAMARES_TRANSLATION_LANGUAGES ) | ||||
| 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(REMOVE_DUPLICATES CALAMARES_TRANSLATION_LANGUAGES) | ||||
|  | ||||
| add_subdirectory( lang )  # i18n tools | ||||
| add_subdirectory(lang) # i18n tools | ||||
|  | ||||
| ### Example Distro | ||||
| # | ||||
| @@ -463,22 +534,22 @@ add_subdirectory( lang )  # i18n tools | ||||
| # | ||||
| #   make example-distro | ||||
| # | ||||
| find_program( mksquashfs_PROGRAM mksquashfs ) | ||||
| if( mksquashfs_PROGRAM ) | ||||
|     set( mksquashfs_FOUND ON ) | ||||
|     set( src_fs ${CMAKE_SOURCE_DIR}/data/example-root/ ) | ||||
|     set( dst_fs ${CMAKE_BINARY_DIR}/example.sqfs ) | ||||
|     if( EXISTS ${src_fs} ) | ||||
| find_program(mksquashfs_PROGRAM mksquashfs) | ||||
| if(mksquashfs_PROGRAM) | ||||
|     set(mksquashfs_FOUND ON) | ||||
|     set(src_fs ${CMAKE_SOURCE_DIR}/data/example-root/) | ||||
|     set(dst_fs ${CMAKE_BINARY_DIR}/example.sqfs) | ||||
|     if(EXISTS ${src_fs}) | ||||
|         # based on the build host. If /lib64 exists, assume it is needed. | ||||
|         # Collect directories needed for a minimal binary distro, | ||||
|         # Note that the last path component is added to the root, so | ||||
|         # if you add /usr/sbin here, it will be put into /sbin_1. | ||||
|         # Add such paths to /etc/profile under ${src_fs}. | ||||
|         set( candidate_fs /sbin /bin /lib /lib64 ) | ||||
|         set( host_fs "" ) | ||||
|         foreach( c_fs ${candidate_fs} ) | ||||
|             if( EXISTS ${c_fs} ) | ||||
|                 list( APPEND host_fs ${c_fs} ) | ||||
|         set(candidate_fs /sbin /bin /lib /lib64) | ||||
|         set(host_fs "") | ||||
|         foreach(c_fs ${candidate_fs}) | ||||
|             if(EXISTS ${c_fs}) | ||||
|                 list(APPEND host_fs ${c_fs}) | ||||
|             endif() | ||||
|         endforeach() | ||||
|         add_custom_command( | ||||
| @@ -489,105 +560,92 @@ if( mksquashfs_PROGRAM ) | ||||
|         add_custom_target(example-distro DEPENDS ${dst_fs}) | ||||
|     endif() | ||||
| else() | ||||
|     set( mksquashfs_FOUND OFF ) | ||||
|     set(mksquashfs_FOUND OFF) | ||||
| endif() | ||||
| # Doesn't list mksquashfs as an optional dep, though, because it | ||||
| # hasn't been sent through the find_package() scheme. | ||||
| # | ||||
| # "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 | ||||
| # | ||||
| 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 | ||||
| # with date and git information (commit, dirty status) 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. | ||||
| if( NOT BUILD_RELEASE AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git/" ) | ||||
|     include( ExtendedVersion ) | ||||
|     extend_version( "${CALAMARES_VERSION}" OFF CALAMARES_VERSION_SHORT CALAMARES_VERSION ) | ||||
| if(NOT CALAMARES_RELEASE_MODE AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git/") | ||||
|     include(ExtendedVersion) | ||||
|     extend_version( "${CALAMARES_VERSION}" OFF CALAMARES_VERSION_SHORT CALAMARES_VERSION_LONG ) | ||||
| endif() | ||||
|  | ||||
| # Special target for not-RC (e.g. might-be-release) builds. | ||||
| # This is used by the release script to get the version. | ||||
| if ( CALAMARES_VERSION_RC EQUAL 0 ) | ||||
|     add_custom_target(show-version | ||||
|         ${CMAKE_COMMAND} -E echo CALAMARES_VERSION=${CALAMARES_VERSION_SHORT} | ||||
|         USES_TERMINAL | ||||
|     ) | ||||
| # Special define for RC (e.g. not-a-release) builds. | ||||
| # This is consumed via the CalamaresConfig.h header. | ||||
| if(NOT CALAMARES_RELEASE_MODE) | ||||
|     set(CALAMARES_VERSION_RC 1) | ||||
| endif() | ||||
|  | ||||
| # enforce using constBegin, constEnd for const-iterators | ||||
| add_definitions( | ||||
|     -DQT_STRICT_ITERATORS | ||||
|     -DQT_SHARED | ||||
|     -DQT_SHAREDPOINTER_TRACK_POINTERS | ||||
| ) | ||||
| add_definitions(-DQT_STRICT_ITERATORS -DQT_SHARED -DQT_SHAREDPOINTER_TRACK_POINTERS) | ||||
|  | ||||
| # set paths | ||||
| set( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) | ||||
| set( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) | ||||
| set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) | ||||
| set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") | ||||
| set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") | ||||
| set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") | ||||
|  | ||||
| # Better default installation paths: GNUInstallDirs defines | ||||
| # CMAKE_INSTALL_FULL_SYSCONFDIR to be CMAKE_INSTALL_PREFIX/etc by default | ||||
| # but we really want /etc | ||||
| if( NOT DEFINED CMAKE_INSTALL_SYSCONFDIR ) | ||||
|     set( CMAKE_INSTALL_SYSCONFDIR "/etc" ) | ||||
| if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR) | ||||
|     set(CMAKE_INSTALL_SYSCONFDIR "/etc") | ||||
| endif() | ||||
|  | ||||
| # make predefined install dirs available everywhere | ||||
| include( GNUInstallDirs ) | ||||
| include(GNUInstallDirs) | ||||
|  | ||||
| # This is used by CalamaresAddLibrary; once Calamares is installed, | ||||
| # the CalamaresConfig.cmake module sets this variable to the IMPORTED | ||||
| # libraries for Calamares. | ||||
| set( Calamares_LIBRARIES calamares ) | ||||
| set(Calamares_LIBRARIES calamares) | ||||
|  | ||||
| add_subdirectory( src ) | ||||
| add_subdirectory(3rdparty/kdsingleapplication) | ||||
| if(WITH_PYBIND11) | ||||
|     add_subdirectory(3rdparty/pybind11) | ||||
| endif() | ||||
| add_subdirectory(src) | ||||
|  | ||||
| add_feature_info(Python ${WITH_PYTHON} "Python job modules") | ||||
| add_feature_info(PythonQt ${WITH_PYTHONQT} "Python view modules") | ||||
| add_feature_info(Config ${INSTALL_CONFIG} "Install Calamares configuration") | ||||
| add_feature_info(KCrash ${WITH_KF5Crash} "Crash dumps via KCrash") | ||||
| add_feature_info(KDBusAddons ${WITH_KF5DBus} "Unique-application via DBus") | ||||
| add_feature_info(Pybind11 ${WITH_PYBIND11} "Python using bundled pybind11") | ||||
| add_feature_info(Qml ${WITH_QML} "QML UI support") | ||||
| add_feature_info(Polkit ${INSTALL_POLKIT} "Install Polkit files") | ||||
| 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 | ||||
| # | ||||
| # | ||||
| set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH  "Installation directory for CMake files" ) | ||||
| set( CMAKE_INSTALL_FULL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}" ) | ||||
| set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH "Installation directory for CMake files") | ||||
| set(CMAKE_INSTALL_FULL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}") | ||||
|  | ||||
| export( PACKAGE Calamares ) | ||||
| export(PACKAGE Calamares) | ||||
| configure_package_config_file( | ||||
|     "CalamaresConfig.cmake.in" | ||||
|     "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" | ||||
|     INSTALL_DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" | ||||
|     PATH_VARS | ||||
|         CMAKE_INSTALL_INCLUDEDIR | ||||
|         CMAKE_INSTALL_LIBDIR | ||||
|         CMAKE_INSTALL_DATADIR | ||||
|     PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_DATADIR | ||||
| ) | ||||
| write_basic_package_version_file( | ||||
|     ${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake | ||||
|     VERSION ${PROJECT_VERSION} | ||||
|     COMPATIBILITY SameMajorVersion | ||||
| ) | ||||
| install( | ||||
|     EXPORT Calamares | ||||
|     DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" | ||||
|     FILE "CalamaresTargets.cmake" | ||||
|     NAMESPACE Calamares:: | ||||
| ) | ||||
| install(EXPORT Calamares DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" FILE "CalamaresTargets.cmake" NAMESPACE Calamares::) | ||||
|  | ||||
| # Install the cmake files | ||||
| install( | ||||
| @@ -604,69 +662,61 @@ install( | ||||
|         "CMakeModules/CalamaresCheckModuleSelection.cmake" | ||||
|         "CMakeModules/CMakeColors.cmake" | ||||
|         "CMakeModules/FindYAMLCPP.cmake" | ||||
|     DESTINATION | ||||
|         "${CMAKE_INSTALL_CMAKEDIR}" | ||||
|     DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" | ||||
| ) | ||||
|  | ||||
| ### Miscellaneous installs | ||||
| # | ||||
| # | ||||
| if( INSTALL_CONFIG ) | ||||
|     install( | ||||
|         FILES settings.conf | ||||
|         DESTINATION share/calamares | ||||
|     ) | ||||
| if(INSTALL_POLKIT) | ||||
|     install(FILES com.github.calamares.calamares.policy DESTINATION "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}") | ||||
| endif() | ||||
|  | ||||
| if( INSTALL_POLKIT ) | ||||
|     install( | ||||
|         FILES com.github.calamares.calamares.policy | ||||
|         DESTINATION "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}" | ||||
|     ) | ||||
| endif() | ||||
|  | ||||
| if ( INSTALL_COMPLETION ) | ||||
|     if( NOT CMAKE_INSTALL_BASHCOMPLETIONDIR ) | ||||
|         set( CMAKE_INSTALL_BASHCOMPLETIONDIR "${CMAKE_INSTALL_DATADIR}/bash-completion/completions" ) | ||||
| if(INSTALL_COMPLETION) | ||||
|     if(NOT CMAKE_INSTALL_BASHCOMPLETIONDIR) | ||||
|         set(CMAKE_INSTALL_BASHCOMPLETIONDIR "${CMAKE_INSTALL_DATADIR}/bash-completion/completions") | ||||
|     endif() | ||||
|  | ||||
|     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() | ||||
|  | ||||
| install( | ||||
|   FILES calamares.desktop | ||||
|   DESTINATION ${CMAKE_INSTALL_DATADIR}/applications | ||||
| ) | ||||
| install(FILES calamares.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) | ||||
|  | ||||
| install( | ||||
|     FILES man/calamares.8 | ||||
|     DESTINATION ${CMAKE_INSTALL_MANDIR}/man8/ | ||||
| ) | ||||
| install(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( | ||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" | ||||
|     "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" | ||||
|     IMMEDIATE @ONLY | ||||
|     IMMEDIATE | ||||
|     @ONLY | ||||
| ) | ||||
|  | ||||
| add_custom_target( uninstall | ||||
|     COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake | ||||
| ) | ||||
| add_custom_target(uninstall 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 | ||||
| # | ||||
| get_directory_property( SKIPPED_MODULES | ||||
|     DIRECTORY src/modules | ||||
|     DEFINITION LIST_SKIPPED_MODULES | ||||
| ) | ||||
| get_directory_property(SKIPPED_MODULES DIRECTORY src/modules DEFINITION LIST_SKIPPED_MODULES) | ||||
| calamares_explain_skipped_modules( ${SKIPPED_MODULES} ) | ||||
|  | ||||
| feature_summary( | ||||
|     WHAT DISABLED_FEATURES | ||||
|     DESCRIPTION "The following features have been disabled:" | ||||
|     QUIET_ON_EMPTY | ||||
| ) | ||||
| feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "The following features have been disabled:" QUIET_ON_EMPTY) | ||||
| feature_summary( | ||||
|     WHAT OPTIONAL_PACKAGES_NOT_FOUND | ||||
|     DESCRIPTION "The following OPTIONAL packages were not found:" | ||||
| @@ -683,11 +733,11 @@ feature_summary( | ||||
| # | ||||
| # Note: most distro's will do distro-specific packaging rather than | ||||
| #       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_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_HOMEPAGE_URL "https://calamares.io") | ||||
| 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_ICON "data/images/squid.png") | ||||
|  | ||||
| include(CPack) | ||||
|   | ||||
							
								
								
									
										74
									
								
								CMakeModules/AppStreamHelper.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								CMakeModules/AppStreamHelper.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| # === 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)" ON) | ||||
|  | ||||
| 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(NOT _appstream_name) | ||||
|     # 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}) | ||||
|     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" ) | ||||
|     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} | ||||
|             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/ | ||||
|   | ||||
| @@ -62,8 +62,10 @@ function(calamares_add_library) | ||||
|         add_library(${target} STATIC ${LIBRARY_SOURCES}) | ||||
|     elseif(LIBRARY_TARGET_TYPE STREQUAL "MODULE") | ||||
|         add_library(${target} MODULE ${LIBRARY_SOURCES}) | ||||
|     else() # default | ||||
|     elseif(LIBRARY_TARGET_TYPE STREQUAL "SHARED") | ||||
|         add_library(${target} SHARED ${LIBRARY_SOURCES}) | ||||
|     else() # default | ||||
|         message(FATAL_ERROR "Invalid library type '${LIBRARY_TARGET_TYPE}'") | ||||
|     endif() | ||||
|  | ||||
|     calamares_automoc(${target}) | ||||
| @@ -86,9 +88,9 @@ function(calamares_add_library) | ||||
|     # add link targets | ||||
|     target_link_libraries(${target} | ||||
|         LINK_PUBLIC ${Calamares_LIBRARIES} | ||||
|         Qt5::Core | ||||
|         Qt5::Gui | ||||
|         Qt5::Widgets | ||||
|         ${qtname}::Core | ||||
|         ${qtname}::Gui | ||||
|         ${qtname}::Widgets | ||||
|     ) | ||||
|     if(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 | ||||
|         file(STRINGS "${_mod_dir}/module.desc" MODULE_INTERFACE REGEX "^interface") | ||||
|         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_testing OFF ) | ||||
|         elseif ( MODULE_INTERFACE MATCHES "python" ) | ||||
| @@ -152,12 +153,10 @@ function( _calamares_add_module_subdirectory_impl ) | ||||
|  | ||||
|                     get_filename_component( FLEXT ${MODULE_FILE} EXT ) | ||||
|                     if( "${FLEXT}" STREQUAL ".conf" ) | ||||
|                         if( INSTALL_CONFIG ) | ||||
|                             install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${MODULE_FILE} | ||||
|                                     DESTINATION ${MODULE_DATA_DESTINATION} ) | ||||
|                         endif() | ||||
|                         message(STATUS "Config ${MODULE_FILE}") | ||||
|                         list( APPEND MODULE_CONFIG_FILES ${MODULE_FILE} ) | ||||
|                     else() | ||||
|                         message(STATUS "Non-Config ${MODULE_FILE}") | ||||
|                         install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${MODULE_FILE} | ||||
|                                  DESTINATION ${MODULE_DESTINATION} ) | ||||
|                     endif() | ||||
| @@ -168,12 +167,14 @@ function( _calamares_add_module_subdirectory_impl ) | ||||
|             message( "   ${Green}TYPE:${ColorReset} jobmodule" ) | ||||
|             message( "   ${Green}MODULE_DESTINATION:${ColorReset} ${MODULE_DESTINATION}" ) | ||||
|             if( MODULE_CONFIG_FILES ) | ||||
|                 if ( INSTALL_CONFIG ) | ||||
|                     set( _destination "${MODULE_DATA_DESTINATION}" ) | ||||
|                 if (INSTALL_CONFIG) | ||||
|                     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() | ||||
|                     set( _destination "[Build directory only]" ) | ||||
|                     message("   ${Green}CONFIGURATION_FILES:${ColorReset} ${MODULE_CONFIG_FILES} => [Build directory only]") | ||||
|                 endif() | ||||
|                 message( "   ${Green}CONFIGURATION_FILES:${ColorReset} ${MODULE_CONFIG_FILES} => ${_destination}" ) | ||||
|             endif() | ||||
|             message( "" ) | ||||
|             # We copy over the lang directory, if any | ||||
|   | ||||
| @@ -19,7 +19,7 @@ | ||||
| # | ||||
| # calamares_add_plugin( | ||||
| #   module-name | ||||
| #   TYPE <view|job> | ||||
| #   TYPE <viewmodule|job> | ||||
| #   EXPORT_MACRO macro-name | ||||
| #   SOURCES source-file... | ||||
| #   UI ui-file... | ||||
| @@ -35,7 +35,7 @@ | ||||
| #   [WEIGHT w] | ||||
| # ) | ||||
| # | ||||
| # Function parameters: | ||||
| # Function optional parameters: | ||||
| #  - COMPILE_DEFINITIONS | ||||
| #       Definitions are set on the resulting module with a suitable | ||||
| #       flag (i.e. `-D`) so only state the name (optionally, also the value) | ||||
| @@ -65,6 +65,9 @@ | ||||
| # SKIPPED_MODULES is set in the parent (i.e. caller's) scope with the | ||||
| # reason why. This should rarely be a concern as AddModuleSubdirectory | ||||
| # 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". | ||||
|  | ||||
| include( CMakeParseArguments ) | ||||
|  | ||||
| @@ -104,10 +107,9 @@ function( calamares_add_plugin ) | ||||
|             message( FATAL_ERROR "${Red}NO_CONFIG${ColorReset} is set, with configuration ${Red}${PLUGIN_CONFIG_FILES}${ColorReset}" ) | ||||
|         endif() | ||||
|         set( _destination "(unknown)" ) | ||||
|         if ( INSTALL_CONFIG AND NOT PLUGIN_NO_INSTALL ) | ||||
|             set( _destination "${PLUGIN_DATA_DESTINATION}" ) | ||||
|         if(INSTALL_CONFIG AND NOT PLUGIN_NO_INSTALL) | ||||
|             set(_destination "${PLUGIN_DATA_DESTINATION}") | ||||
|         elseif( NOT PLUGIN_NO_INSTALL ) | ||||
|             # Not INSTALL_CONFIG | ||||
|             set( _destination "[Build directory only]" ) | ||||
|         else() | ||||
|             set( _destination "[Skipping installation]" ) | ||||
| @@ -127,7 +129,7 @@ function( calamares_add_plugin ) | ||||
|     set( target "calamares_${PLUGIN_TYPE}_${PLUGIN_NAME}" ) | ||||
|  | ||||
|     # 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) | ||||
|     elseif(PLUGIN_TYPE STREQUAL "job") | ||||
|         list(APPEND PLUGIN_LINK_PRIVATE_LIBRARIES Calamares::calamares) | ||||
| @@ -210,16 +212,14 @@ function( calamares_add_plugin ) | ||||
|  | ||||
|         set( _warned_config OFF ) | ||||
|         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 ) | ||||
|             else() | ||||
|                 message( "   ${BoldYellow}Not updating${ColorReset} ${PLUGIN_CONFIG_FILE}" ) | ||||
|                 set( _warned_config ON ) | ||||
|             endif() | ||||
|             if ( INSTALL_CONFIG ) | ||||
|                 install( | ||||
|                     FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE} | ||||
|                     DESTINATION ${PLUGIN_DATA_DESTINATION} ) | ||||
|             if(INSTALL_CONFIG) | ||||
|                 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE} DESTINATION ${PLUGIN_DATA_DESTINATION}) | ||||
|             endif() | ||||
|         endforeach() | ||||
|         if ( _warned_config ) | ||||
|   | ||||
| @@ -18,19 +18,17 @@ | ||||
| #   SOURCES <FILE..> | ||||
| #   ) | ||||
|  | ||||
| include( CMakeParseArguments ) | ||||
| include( CalamaresAutomoc ) | ||||
| include(CMakeParseArguments) | ||||
| include(CalamaresAutomoc) | ||||
|  | ||||
| function( calamares_add_test ) | ||||
|     # parse arguments (name needs to be saved before passing ARGN into the macro) | ||||
|     set( NAME ${ARGV0} ) | ||||
|     set( options GUI ) | ||||
|     set( oneValueArgs NAME RESOURCES ) | ||||
|     set( multiValueArgs SOURCES LIBRARIES DEFINITIONS ) | ||||
|     cmake_parse_arguments( TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) | ||||
|     set( TEST_NAME ${NAME} ) | ||||
| function(calamares_add_test name) | ||||
|     set(options GUI) | ||||
|     set(oneValueArgs RESOURCES) | ||||
|     set(multiValueArgs SOURCES LIBRARIES DEFINITIONS) | ||||
|     cmake_parse_arguments(TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) | ||||
|     set(TEST_NAME ${name}) | ||||
|  | ||||
|     if( ECM_FOUND AND BUILD_TESTING ) | ||||
|     if(ECM_FOUND AND BUILD_TESTING) | ||||
|         ecm_add_test( | ||||
|             ${TEST_SOURCES} ${TEST_RESOURCES} | ||||
|             TEST_NAME | ||||
| @@ -38,17 +36,20 @@ function( calamares_add_test ) | ||||
|             LINK_LIBRARIES | ||||
|                 Calamares::calamares | ||||
|                 ${TEST_LIBRARIES} | ||||
|                 Qt5::Core | ||||
|                 Qt5::Test | ||||
|                 ${qtname}::Core | ||||
|                 ${qtname}::Test | ||||
|         ) | ||||
|         calamares_automoc( ${TEST_NAME} ) | ||||
|         # We specifically pass in the source directory of the test-being- | ||||
|         # 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} ) | ||||
|         if( TEST_GUI ) | ||||
|             target_link_libraries( ${TEST_NAME} Calamares::calamaresui Qt5::Gui ) | ||||
|         target_compile_definitions( | ||||
|             ${TEST_NAME} | ||||
|             PRIVATE -DBUILD_AS_TEST="${CMAKE_CURRENT_SOURCE_DIR}" ${TEST_DEFINITIONS} | ||||
|         ) | ||||
|         if(TEST_GUI) | ||||
|             target_link_libraries(${TEST_NAME} Calamares::calamaresui ${qtname}::Gui) | ||||
|         endif() | ||||
|         if( TEST_RESOURCES ) | ||||
|         if(TEST_RESOURCES) | ||||
|             calamares_autorcc( ${TEST_NAME} ${TEST_RESOURCES} ) | ||||
|         endif() | ||||
|     endif() | ||||
|   | ||||
| @@ -100,3 +100,58 @@ function( install_calamares_gettext_translations ) | ||||
|         endif() | ||||
|     endforeach() | ||||
| 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( _v "${version}" ) | ||||
|     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" ) | ||||
|         if( CALAMARES_VERSION_DATE GREATER 0 ) | ||||
|             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,57 @@ | ||||
| # | ||||
| # Finds KPMcore and consistently sets API flags based on the version. | ||||
| # | ||||
| if ( NOT KPMcore_searched_for ) | ||||
|     set( KPMcore_searched_for TRUE ) | ||||
| # If KPMcore is not found, still create calamares::kpmcore interface | ||||
| # 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( | ||||
|         KPMcore PROPERTIES | ||||
|         KPMcore | ||||
|         PROPERTIES | ||||
|         URL "https://invent.kde.org/kde/kpmcore" | ||||
|         DESCRIPTION "KDE Partitioning library" | ||||
|         TYPE RECOMMENDED | ||||
|         PURPOSE "For disk partitioning support" | ||||
|     ) | ||||
|  | ||||
|     if( KPMcore_FOUND ) | ||||
|         set( KPMcore_API_DEFINITIONS "" ) | ||||
|         if( KPMcore_VERSION VERSION_GREATER "3.3.70" AND KPMcore_VERSION VERSION_LESS "4.0" ) | ||||
|             message( FATAL_ERROR "KPMCore beta versions ${KPMcore_VERSION} not supported" ) | ||||
|         endif() | ||||
|         if ( KPMcore_VERSION VERSION_GREATER "3.3.0") | ||||
|             list( APPEND KPMcore_API_DEFINITIONS WITH_KPMCORE331API) # kpmcore > 3.3.0 with deprecations | ||||
|         endif() | ||||
|         if ( KPMcore_VERSION VERSION_GREATER_EQUAL "4.0") | ||||
|             list( APPEND KPMcore_API_DEFINITIONS WITH_KPMCORE4API) # kpmcore 4 with new API | ||||
|         endif() | ||||
|         if( KPMcore_VERSION VERSION_GREATER_EQUAL "4.2" ) | ||||
|             list( APPEND KPMcore_API_DEFINITIONS WITH_KPMCORE42API) # kpmcore 4.2 with new API | ||||
|         endif() | ||||
|     # 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) | ||||
|         find_package(${qtname} REQUIRED DBus) # Needed for KPMCore | ||||
|         find_package(${kfname} REQUIRED I18n WidgetsAddons) # Needed for KPMCore | ||||
|  | ||||
|         target_link_libraries(calapmcore INTERFACE kpmcore ${qtname}::DBus ${kfname}::I18n ${kfname}::WidgetsAddons) | ||||
|         target_include_directories(calapmcore INTERFACE ${KPMCORE_INCLUDE_DIR}) | ||||
|         # If there were KPMcore API variations, figure them out here | ||||
|         # target_compile_definitions(calapmcore INTERFACE WITH_KPMcore) | ||||
|  | ||||
|         # Flag that this library has KPMcore support. A variable | ||||
|         # set here has the wrong scope. ENV{} would be visible | ||||
|         # 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() | ||||
|         set( KPMcore_API_DEFINITIONS WITHOUT_KPMcore ) | ||||
|         target_compile_definitions(calapmcore INTERFACE WITHOUT_KPMcore) | ||||
|     endif() | ||||
| else() | ||||
|     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() | ||||
|   | ||||
| @@ -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 | ||||
| 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/) | ||||
| room, `#calamares:kde.org`. The conversation is bridged with IRC | ||||
| on [Libera.Chat](https://libera.chat/). | ||||
| 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. | ||||
| room, `#calamares:kde.org`. Responsiveness is best during the day | ||||
| in Europe, but feel free to idle. | ||||
| 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. | ||||
|  | ||||
| * [](https://webchat.kde.org/#/room/%23calamares:kde.org) | ||||
| * [](https://kiwiirc.com/client/irc.libera.chat/#calamares) | ||||
|  | ||||
|  | ||||
| ## General Guidelines | ||||
| @@ -57,7 +57,7 @@ stay that way. | ||||
|  | ||||
| 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 | ||||
| yourself, **do** upstream things as much as you can. When you make cool | ||||
| @@ -74,26 +74,71 @@ Up to date | ||||
| [building-Calamares](https://github.com/calamares/calamares/wiki/Develop-Guide) | ||||
| 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:38` | ||||
|  | ||||
| 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. | ||||
| There is a script `ci/build.sh` that does this, too (without options). | ||||
| - `cmake -S /src -B /build -G Ninja` | ||||
| - `ninja -C /build` | ||||
|  | ||||
| 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. | ||||
|  | ||||
| ### 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: | ||||
| * Compiler with C++17 support: GCC >= 7 or Clang >= 5 | ||||
| * CMake >= 3.3 | ||||
| * Qt >= 5.9 | ||||
| * Compiler with C++17 support | ||||
| * CMake >= 3.16 | ||||
| * yaml-cpp >= 0.5.1 | ||||
| * Python >= 3.3 (required for some modules) | ||||
| * Boost.Python >= 1.55.0 (required for some modules) | ||||
| * KDE extra-cmake-modules >= 5.18 (recommended; required for some modules; | ||||
| * Qt >= 5.15 or Qt >= 6.5 | ||||
| * KDE Frameworks KCoreAddons >= 5.78 | ||||
| * KDE extra-cmake-modules >= 5.78 (recommended; required for some modules; | ||||
|   required for some tests) | ||||
| * KDE Frameworks KCoreAddons (>= 5.58 recommended) | ||||
| * PythonQt (optional, deprecated) | ||||
| * Python >= 3.6 (required for some modules) | ||||
| * Boost.Python >= 1.72.0 (required for some modules if WITH_PYBIND11 is OFF) | ||||
|  | ||||
| Individual modules may have their own requirements; | ||||
| these are listed in CMake output. | ||||
| Particular requirements (not complete): | ||||
|  | ||||
| * *fsresizer* KPMCore >= 3.3 (>= 4.2 recommended) | ||||
| * *partition* KPMCore >= 3.3 (>= 4.2 recommended) | ||||
| * *fsresizer* KPMCore >= 20.04 | ||||
| * *partition* KPMCore >= 20.04 | ||||
| * *users* LibPWQuality (optional) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -46,20 +46,27 @@ macro(accumulate_deps outvar target namespace) | ||||
|     endforeach() | ||||
| endmacro() | ||||
|  | ||||
| # Qt5 infrastructure for translations is required | ||||
| set(qt5_required Core Widgets LinguistTools) | ||||
| accumulate_deps(qt5_required Calamares::calamares Qt5::) | ||||
| accumulate_deps(qt5_required Calamares::calamaresui Qt5::) | ||||
| find_package(Qt5 CONFIG REQUIRED ${qt5_required}) | ||||
| set(Calamares_WITH_QT6 @WITH_QT6@) | ||||
| if(Calamares_WITH_QT6) | ||||
|     set(qtname "Qt6") | ||||
| else() | ||||
|     set(qtname "Qt5") | ||||
| endif() | ||||
|  | ||||
| # Qt infrastructure for translations is required | ||||
| set(qt_required Core Widgets LinguistTools) | ||||
| accumulate_deps(qt_required Calamares::calamares ${qtname}::) | ||||
| accumulate_deps(qt_required Calamares::calamaresui ${qtname}::) | ||||
| find_package(${qtname} CONFIG REQUIRED ${qt_required}) | ||||
|  | ||||
| set(kf5_required "") | ||||
| accumulate_deps(kf5_required Calamares::calamares KF5::) | ||||
| accumulate_deps(kf5_required Calamares::calamaresui KF5::) | ||||
| accumulate_deps(kf5_required Calamares::calamares ${kfname}::) | ||||
| accumulate_deps(kf5_required Calamares::calamaresui ${kfname}::) | ||||
| if(kf5_required) | ||||
|     find_package(ECM ${ECM_VERSION} NO_MODULE) | ||||
|     if( ECM_FOUND ) | ||||
|         list(INSERT CMAKE_MODULE_PATH 0 ${ECM_MODULE_PATH}) | ||||
|         find_package(KF5 REQUIRED COMPONENTS ${kf5_required}) | ||||
|         find_package(${kfname} REQUIRED COMPONENTS ${kf5_required}) | ||||
|     endif() | ||||
| endif() | ||||
|  | ||||
| @@ -87,5 +94,4 @@ include(CalamaresAddPlugin) | ||||
| # This list should match the one in libcalamares/CalamaresConfig.h, | ||||
| # which is the C++-language side of the same configuration. | ||||
| set(Calamares_WITH_PYTHON @WITH_PYTHON@) | ||||
| set(Calamares_WITH_PYTHONQT @WITH_PYTHONQT@) | ||||
| set(Calamares_WITH_QML @WITH_QML@) | ||||
|   | ||||
| @@ -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! | ||||
							
								
								
									
										34
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								README.md
									
									
									
									
									
								
							| @@ -7,26 +7,26 @@ | ||||
|  | ||||
| [](https://github.com/calamares/calamares/labels/hacking%3A%20in-progress) | ||||
| [](https://github.com/calamares/calamares/releases) | ||||
| [](https://github.com/calamares/calamares/actions?query=workflow%3Aci) | ||||
| [](https://github.com/calamares/calamares/blob/calamares/LICENSE) | ||||
| [](https://github.com/calamares/calamares/actions?query=workflow%3Aci) | ||||
| [](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 | ||||
| > feature for both manual and automated partitioning operations. Calamares is designed to | ||||
| > be customizable by distribution maintainers without need for cumbersome patching, | ||||
| > thanks to third party branding and external modules support. | ||||
| > be customizable by distribution maintainers without the need for cumbersome patching, | ||||
| > thanks to third-party branding and external modules support. | ||||
|  | ||||
| ## Target Audience | ||||
|  | ||||
| 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 | ||||
| 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 | ||||
| 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/) | ||||
| 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 | ||||
|  | ||||
| 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)). | ||||
|  | ||||
| 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. | ||||
|  | ||||
| ## Join the Conversation | ||||
|  | ||||
| GitHub Issues are **one** place for discussing Calamares if there are concrete | ||||
| 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/) | ||||
| room, `#calamares:kde.org`. The conversation is bridged with IRC | ||||
| on [Libera.Chat](https://libera.chat/). | ||||
| 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. | ||||
| room, `#calamares:kde.org`. Responsiveness is best during the day | ||||
| in Europe, but feel free to idle. | ||||
| Matrix is persistent, and we'll see your message eventually. | ||||
|  | ||||
| * [](https://webchat.kde.org/#/room/%23calamares:kde.org) | ||||
| * [](https://kiwiirc.com/client/irc.libera.chat/#calamares) | ||||
| * [](https://webchat.kde.org/#/room/%23calamares:kde.org) (needs a Matrix account) | ||||
|  | ||||
|   | ||||
| @@ -21,18 +21,26 @@ Name[as]=চিছটেম ইনস্তল কৰক | ||||
| Icon[as]=কেলামাৰেচ | ||||
| GenericName[as]=চিছটেম ইনস্তলাৰ | ||||
| Comment[as]=কেলামাৰেচ — চিছটেম ইনস্তলাৰ | ||||
| Name[ast]=Instalar el sistema | ||||
| Icon[ast]=calamares | ||||
| GenericName[ast]=Instalador del sistema | ||||
| Comment[ast]=Calamares — Instalador del sistema | ||||
| Name[az]=Sistemi Quraşdırmaq | ||||
| Icon[az]=calamares | ||||
| GenericName[az]=Sistem Quraşdırıcısı | ||||
| Comment[az]=Calamares Sistem Quraşdırıcısı | ||||
| Name[az_AZ]=Sistemi quraşdırmaq | ||||
| Icon[az_AZ]=calamares | ||||
| GenericName[az_AZ]=Sistem quraşdırcısı | ||||
| Comment[az_AZ]=Calamares — Sistem Quraşdırıcısı | ||||
| Name[be]=Усталяваць сістэму | ||||
| Icon[be]=calamares | ||||
| GenericName[be]=Усталёўшчык сістэмы | ||||
| Comment[be]=Calamares — усталёўшчык сістэмы | ||||
| Name[bg]=Инсталирай системата | ||||
| Icon[bg]=calamares | ||||
| GenericName[bg]=Системен Инсталатор | ||||
| Comment[bg]=Calamares — Системен Инсталатор | ||||
| GenericName[bg]=Системен инсталатор | ||||
| Comment[bg]=„Calamares“ – Системен инсталатор | ||||
| Name[bn]=সিস্টেম ইনস্টল করুন | ||||
| Icon[bn]=ক্যালামারেস | ||||
| GenericName[bn]=সিস্টেম ইনস্টলার | ||||
| @@ -41,6 +49,10 @@ Name[ca]=Instal·la el sistema | ||||
| Icon[ca]=calamares | ||||
| GenericName[ca]=Instal·lador de sistema | ||||
| Comment[ca]=Calamares — Instal·lador de sistema | ||||
| Name[cs_CZ]=Nainstalovat systém | ||||
| Icon[cs_CZ]=calamares | ||||
| GenericName[cs_CZ]=Instalátor systému | ||||
| Comment[cs_CZ]=Calamares – instalátor operačních systémů | ||||
| Name[da]=Installér system | ||||
| Icon[da]=calamares | ||||
| GenericName[da]=Systeminstallationsprogram | ||||
| @@ -57,10 +69,19 @@ Name[en_GB]=Install System | ||||
| Icon[en_GB]=calamares | ||||
| GenericName[en_GB]=System Installer | ||||
| Comment[en_GB]=Calamares — System Installer | ||||
| Name[es]=Instalar Sistema | ||||
| Name[eo]=Instali Sistemo | ||||
| Icon[eo]=calamares | ||||
| GenericName[eo]=Sistema Instalilo | ||||
| Comment[eo]=Calamares — Sistema Instalilo | ||||
| Name[es]=Instalar el sistema | ||||
| Icon[es]=calamares | ||||
| GenericName[es]=Instalador del Sistema | ||||
| Comment[es]=Calamares — Instalador del Sistema | ||||
| GenericName[es]=Instalador del sistema | ||||
| Comment[es]=Calamares — Instalador del sistema | ||||
| Name[es_MX]=Instalar el Sistema | ||||
| Icon[es_MX]=calamares | ||||
| GenericName[es_MX]=Instalador del sistema | ||||
| Comment[es_MX]=Calamares - Instalador del sistema | ||||
| Name[es_PR]=Instalar el sistema | ||||
| Name[et]=Paigalda süsteem | ||||
| Icon[et]=calamares | ||||
| GenericName[et]=Süsteemipaigaldaja | ||||
| @@ -73,7 +94,10 @@ Name[fa]=نصب سامانه | ||||
| Icon[fa]=کالامارس | ||||
| GenericName[fa]=نصبکننده سامانه | ||||
| Comment[fa]=کالامارس — نصبکننده سامانه | ||||
| Name[es_PR]=Instalar el sistema | ||||
| Name[fi_FI]=Asenna järjestelmä | ||||
| Icon[fi_FI]=calamares | ||||
| GenericName[fi_FI]=Järjestelmän asennusohjelma | ||||
| Comment[fi_FI]=Calamares — Järjestelmän asentaja | ||||
| Name[fr]=Installer le système | ||||
| Icon[fr]=calamares | ||||
| GenericName[fr]=Installateur système | ||||
| @@ -98,10 +122,6 @@ Name[hr]=Instaliraj sustav | ||||
| Icon[hr]=calamares | ||||
| GenericName[hr]=Instalacija sustava | ||||
| Comment[hr]=Calamares — Instalacija sustava | ||||
| Name[ie]=Installar li sistema | ||||
| Icon[ie]=calamares | ||||
| GenericName[ie]=Installator del sistema | ||||
| Comment[ie]=Calamares — Installator del sistema | ||||
| Name[hu]=Rendszer telepítése | ||||
| Icon[hu]=calamares | ||||
| GenericName[hu]=Rendszertelepítő | ||||
| @@ -110,14 +130,18 @@ Name[id]=Instal Sistem | ||||
| Icon[id]=calamares | ||||
| GenericName[id]=Pemasang | ||||
| Comment[id]=Calamares — Pemasang Sistem | ||||
| Name[ie]=Installar li sistema | ||||
| Icon[ie]=calamares | ||||
| GenericName[ie]=Installator del sistema | ||||
| Comment[ie]=Calamares — Installator del sistema | ||||
| Name[is]=Setja upp kerfið | ||||
| Icon[is]=calamares | ||||
| GenericName[is]=Kerfis uppsetning | ||||
| Comment[is]=Calamares — Kerfis uppsetning | ||||
| Name[cs_CZ]=Nainstalovat systém | ||||
| Icon[cs_CZ]=calamares | ||||
| GenericName[cs_CZ]=Instalátor systému | ||||
| Comment[cs_CZ]=Calamares – instalátor operačních systémů | ||||
| Name[it_IT]=Installa il sistema | ||||
| Icon[it_IT]=calamares | ||||
| GenericName[it_IT]=Programma d'installazione del sistema | ||||
| Comment[it_IT]=Calamares — Programma d'installazione del sistema | ||||
| Name[ja]=システムをインストール | ||||
| Icon[ja]=calamares | ||||
| GenericName[ja]=システムインストーラー | ||||
| @@ -130,10 +154,6 @@ Name[lt]=Įdiegti Sistemą | ||||
| Icon[lt]=calamares | ||||
| GenericName[lt]=Sistemos diegimas į kompiuterį | ||||
| Comment[lt]=Calamares — Sistemos diegimo programa | ||||
| Name[it_IT]=Installa il sistema | ||||
| Icon[it_IT]=calamares | ||||
| GenericName[it_IT]=Programma d'installazione del sistema | ||||
| Comment[it_IT]=Calamares — Programma d'installazione del sistema | ||||
| Name[mk]=Инсталирај го системот | ||||
| Icon[mk]=calamares | ||||
| GenericName[mk]=Системен Инсталер | ||||
| @@ -146,14 +166,14 @@ Name[nb]=Installer System | ||||
| Icon[nb]=calamares | ||||
| GenericName[nb]=Systeminstallatør | ||||
| Comment[nb]=Calamares-systeminstallatør | ||||
| Name[ne_NP]= सिस्टम इन्स्टल गर्नुहोस् | ||||
| Icon[ne_NP]=Calamares | ||||
| GenericName[ne_NP]=सिस्टम इन्स्टलर | ||||
| Comment[ne_NP]=Calamares - सिस्टम इन्स्टलर | ||||
| Name[nl]=Installeer systeem | ||||
| Icon[nl]=calamares | ||||
| GenericName[nl]=Installatieprogramma | ||||
| Comment[nl]=Calamares — Installatieprogramma | ||||
| Name[az_AZ]=Sistemi quraşdırmaq | ||||
| Icon[az_AZ]=calamares | ||||
| GenericName[az_AZ]=Sistem quraşdırcısı | ||||
| Comment[az_AZ]=Calamares — Sistem Quraşdırıcısı | ||||
| Name[pl]=Zainstaluj system | ||||
| Icon[pl]=calamares | ||||
| GenericName[pl]=Instalator systemu | ||||
| @@ -162,6 +182,10 @@ Name[pt_BR]=Sistema de Instalação | ||||
| Icon[pt_BR]=calamares | ||||
| GenericName[pt_BR]=Instalador de Sistema | ||||
| Comment[pt_BR]=Calamares — Instalador de Sistema | ||||
| Name[pt_PT]=Instalar Sistema | ||||
| Icon[pt_PT]=calamares | ||||
| GenericName[pt_PT]=Instalador de Sistema | ||||
| Comment[pt_PT]=Instalador de Sistema - Calamares | ||||
| Name[ro]=Instalează sistemul | ||||
| Icon[ro]=calamares | ||||
| GenericName[ro]=Instalator de sistem | ||||
| @@ -183,15 +207,11 @@ Name[sq]=Instalo Sistemin | ||||
| Icon[sq]=calamares | ||||
| GenericName[sq]=Instalues Sistemi | ||||
| Comment[sq]=Calamares — Instalues Sistemi | ||||
| Name[fi_FI]=Asenna järjestelmä | ||||
| Icon[fi_FI]=calamares | ||||
| GenericName[fi_FI]=Järjestelmän asennusohjelma | ||||
| Comment[fi_FI]=Calamares — Järjestelmän asentaja | ||||
| Name[sr@latin]=Instaliraj sistem | ||||
| Name[sr]=Инсталирај систем | ||||
| Icon[sr]=calamares | ||||
| GenericName[sr]=Инсталатер система | ||||
| Comment[sr]=Каламарес — инсталатер система | ||||
| Name[sr@latin]=Instaliraj sistem | ||||
| Name[sv]=Installera system | ||||
| Icon[sv]=calamares | ||||
| GenericName[sv]=Systeminstallerare | ||||
| @@ -201,6 +221,10 @@ Icon[tg]=calamares | ||||
| GenericName[tg]=Насбкунандаи низомӣ | ||||
| Comment[tg]=Calamares — Насбкунандаи низомӣ | ||||
| Name[th]=ติดตั้งระบบ | ||||
| Name[tr_TR]=Sistemi Yükle | ||||
| Icon[tr_TR]=calamares | ||||
| GenericName[tr_TR]=Sistem Yükleyici | ||||
| Comment[tr_TR]=Calamares — Sistem Yükleyici | ||||
| Name[uk]=Встановити Систему | ||||
| Icon[uk]=calamares | ||||
| GenericName[uk]=Встановлювач системи | ||||
| @@ -217,27 +241,3 @@ Name[zh_TW]=安裝系統 | ||||
| Icon[zh_TW]=calamares | ||||
| GenericName[zh_TW]=系統安裝程式 | ||||
| Comment[zh_TW]=Calamares ── 系統安裝程式 | ||||
| Name[ast]=Instalar el sistema | ||||
| Icon[ast]=calamares | ||||
| GenericName[ast]=Instalador del sistema | ||||
| Comment[ast]=Calamares — Instalador del sistema | ||||
| Name[eo]=Instali Sistemo | ||||
| Icon[eo]=calamares | ||||
| GenericName[eo]=Sistema Instalilo | ||||
| Comment[eo]=Calamares — Sistema Instalilo | ||||
| Name[ne_NP]= सिस्टम इन्स्टल गर्नुहोस् | ||||
| Icon[ne_NP]=Calamares | ||||
| GenericName[ne_NP]=सिस्टम इन्स्टलर | ||||
| Comment[ne_NP]=Calamares - सिस्टम इन्स्टलर | ||||
| Name[es_MX]=Instalar el Sistema | ||||
| Icon[es_MX]=calamares | ||||
| GenericName[es_MX]=Instalador del sistema | ||||
| Comment[es_MX]=Calamares - Instalador del sistema | ||||
| Name[pt_PT]=Instalar Sistema | ||||
| Icon[pt_PT]=calamares | ||||
| GenericName[pt_PT]=Instalador de Sistema | ||||
| Comment[pt_PT]=Instalador de Sistema - Calamares | ||||
| Name[tr_TR]=Sistemi Yükle | ||||
| Icon[tr_TR]=calamares | ||||
| GenericName[tr_TR]=Sistem Yükleyici | ||||
| Comment[tr_TR]=Calamares — Sistem Yükleyici | ||||
|   | ||||
| @@ -76,7 +76,7 @@ Follow the instructions printed by the release script. | ||||
| * Upload tarball and signature. | ||||
| * Publish release article on `calamares.io`. | ||||
| * 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 | ||||
|  | ||||
|   | ||||
| @@ -7,8 +7,6 @@ | ||||
| # | ||||
| # Release script for Calamares | ||||
| # | ||||
| # NOTE: this script contains Linuxisms (in particular, expects GNU mktemp(1)) | ||||
| # | ||||
| # This attempts to perform the different steps of the RELEASE.md | ||||
| # document automatically. It's not tested on other machines or | ||||
| # setups other than [ade]'s development VM. | ||||
| @@ -29,11 +27,13 @@ | ||||
| #   * `-B` do not build (before tagging) | ||||
| #   * `-P` do not package (tag, sign, tarball) | ||||
| #   * `-T` do not respect string freeze | ||||
| #   * '-b' do not build-and-test tarball | ||||
| # | ||||
| # The build / package settings can be influenced via environment variables: | ||||
| #   * BUILD_DEFAULT set to `false` to avoid first build with gcc | ||||
| #   * BUILD_CLANG   set to `false` to avoid second build with clang | ||||
| #   * BUILD_ONLY    set to `true` to break after building | ||||
| #   * TEST_TARBALL  set to 'false' to skip build-and-test phase after tarring | ||||
| # | ||||
| ### END USAGE | ||||
|  | ||||
| @@ -45,9 +45,10 @@ which cmake > /dev/null 2>&1 || { echo "No cmake(1) available." ; exit 1 ; } | ||||
| test -z "$BUILD_DEFAULT" && BUILD_DEFAULT=true | ||||
| test -z "$BUILD_CLANG" && BUILD_CLANG=true | ||||
| test -z "$BUILD_ONLY" && BUILD_ONLY=false | ||||
| test -z "$TEST_TARBALL" && TEST_TARBALL=true | ||||
| STRING_FREEZE=true | ||||
|  | ||||
| while getopts "hBPT" opt ; do | ||||
| while getopts "hBbPT" opt ; do | ||||
|     case "$opt" in | ||||
|     h|\?) | ||||
|         sed -e '1,/USAGE/d' -e '/END.USAGE/,$d' < "$0" | ||||
| @@ -57,6 +58,9 @@ while getopts "hBPT" opt ; do | ||||
|         BUILD_DEFAULT=false | ||||
|         BUILD_CLANG=false | ||||
|         ;; | ||||
|     b) | ||||
| 	TEST_TARBALL=false | ||||
| 	;; | ||||
|     P) | ||||
|         BUILD_ONLY=true | ||||
|         ;; | ||||
| @@ -74,14 +78,24 @@ fi | ||||
| ### Setup | ||||
| # | ||||
| # | ||||
| BUILDDIR=$(mktemp -d --suffix=-build --tmpdir=.) | ||||
| KEY_ID="CFDDC96F12B1915C" | ||||
| BUILDDIR=$(mktemp -d ./cala-tmp-XXXXXX) | ||||
| KEY_ID="328D742D8807A435" | ||||
|  | ||||
| # Try to make gpg cache the signing key, so we can leave the process | ||||
| # to run and sign. | ||||
| rm -f CMakeLists.txt.gpg | ||||
| 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 | ||||
| # | ||||
| # | ||||
| @@ -120,12 +134,6 @@ else | ||||
|     ( cd "$BUILDDIR" && cmake .. ) || { echo "Could not run cmake in $BUILDDIR ." ; exit 1 ; } | ||||
| 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 | ||||
| # | ||||
| # This is the signing key ID associated with the GitHub account adriaandegroot, | ||||
| @@ -144,12 +152,14 @@ SHA256=$(sha256sum "$TAR_FILE" | cut -d" " -f1) | ||||
| ### Build the tarball | ||||
| # | ||||
| # | ||||
| D=$(date +%Y%m%d-%H%M%S) | ||||
| TMPDIR=$(mktemp -d --suffix="-calamares-$D") | ||||
| test -d "$TMPDIR" || { echo "Could not create tarball-build directory." ; exit 1 ; } | ||||
| tar xzf "$TAR_FILE" -C "$TMPDIR" || { echo "Could not unpack tarball." ; exit 1 ; } | ||||
| test -d "$TMPDIR/$TAR_V" || { echo "Tarball did not contain source directory." ; exit 1 ; } | ||||
| ( cd "$TMPDIR/$TAR_V" && cmake . && make -j4 && make test ) || { echo "Tarball build failed in $TMPDIR ." ; exit 1 ; } | ||||
| if test "x$TEST_TARBALL" = "xtrue" ; then | ||||
|     D=$(date +%Y%m%d-%H%M%S) | ||||
|     TMPDIR=$(mktemp -d ./cala-tar-XXXXXX) | ||||
|     test -d "$TMPDIR" || { echo "Could not create tarball-build directory." ; exit 1 ; } | ||||
|     tar xzf "$TAR_FILE" -C "$TMPDIR" || { echo "Could not unpack tarball." ; exit 1 ; } | ||||
|     test -d "$TMPDIR/$TAR_V" || { echo "Tarball did not contain source directory." ; exit 1 ; } | ||||
|     ( cd "$TMPDIR/$TAR_V" && cmake . && make -j4 && make test ) || { echo "Tarball build failed in $TMPDIR ." ; exit 1 ; } | ||||
| fi | ||||
| gpg -s -u $KEY_ID --detach --armor $TAR_FILE  # Sign the tarball | ||||
|  | ||||
| ### Cleanup | ||||
|   | ||||
							
								
								
									
										74
									
								
								ci/abicheck.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										74
									
								
								ci/abicheck.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| #! /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 base version can be a tag or git-hash; it will be checked-out | ||||
| # in a worktree. | ||||
| # | ||||
| # Note that the hash here now is 3.3-alpha1, when ABI | ||||
| # compatibility was not expected much. From 3.3-beta, | ||||
| # whenever that is, ABI compatibility should be more of a concern. | ||||
| BASE_VERSION=0c794183936b6d916a109784829e605cc4582e9f | ||||
|  | ||||
| ### 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 | ||||
| 	mkdir $BUILD_DIR | ||||
|  | ||||
| 	if ( cd $BUILD_DIR && cmake $SOURCE_DIR -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-Og -g -gdwarf" -DCMAKE_C_FLAGS="-Og -g -gdwarf" && make -j12 ) > /dev/null 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 | ||||
| 	else | ||||
| 		echo "! failed to build $LABEL" | ||||
| 		exit 1 | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| ### Build current tree and get ABI info | ||||
| # | ||||
| # | ||||
| do_build current `pwd -P` | ||||
|  | ||||
| ### 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 | ||||
| 	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 $( cd tree-abi-$BASE_VERSION && pwd -P ) | ||||
| 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 | ||||
| style=break | ||||
| add-brackets | ||||
| add-braces | ||||
|  | ||||
| # Spaces | ||||
| pad-paren-in | ||||
|   | ||||
							
								
								
									
										20
									
								
								ci/build.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										20
									
								
								ci/build.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| #! /bin/sh | ||||
| # | ||||
| # Generic build (driven by environment variables) | ||||
| # | ||||
|  | ||||
| # Sanity check | ||||
| test -n "$BUILDDIR" || { echo "! \$BUILDDIR 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,8 +4,7 @@ | ||||
| #   SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org> | ||||
| #   SPDX-License-Identifier: BSD-2-Clause | ||||
| # | ||||
| # Calls astyle with settings matching Calamares coding style | ||||
| # Requires astyle >= 2.04 and clang-format-8 or later | ||||
| # Apply Calamares-style formatting to sources. Requires clang-format-15. | ||||
| # | ||||
| # You can pass in directory names, in which case the files | ||||
| # in that directory (NOT below it) are processed. | ||||
| @@ -19,12 +18,10 @@ BASEDIR=$(dirname $0) | ||||
| TOPDIR=$( cd $BASEDIR/.. && pwd -P ) | ||||
| 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 -f "$TOPDIR/.clang-format.base" || { echo "! No .clang-format support files in $TOPDIR" ; exit 1 ; } | ||||
|  | ||||
| AS=$( which astyle ) | ||||
| test -f "$TOPDIR/.clang-format" || { echo "! No .clang-format support files in $TOPDIR" ; exit 1 ; } | ||||
|  | ||||
| # Allow specifying CF_VERSIONS outside already | ||||
| CF_VERSIONS="$CF_VERSIONS clang-format-8 clang-format80 clang-format90 clang-format-9.0.1 clang-format" | ||||
| CF_VERSIONS="$CF_VERSIONS clang-format15 clang-format-15 clang-format-16 clang-format-16.0.6 clang-format" | ||||
| for _cf in $CF_VERSIONS | ||||
| do | ||||
| 	# Not an error if this particular clang-format isn't found | ||||
| @@ -32,39 +29,33 @@ do | ||||
| 	test -n "$CF" && break | ||||
| 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 -x "$AS" || { echo "! $AS is not executable."; exit 1 ; } | ||||
| test -x "$CF" || { echo "! $CF is not executable."; exit 1 ; } | ||||
|  | ||||
| ### CLANG-FORMAT-WRANGLING | ||||
| # | ||||
| # Version 7 and earlier doesn't understand all the options we would like | ||||
| # Version 8 is ok | ||||
| # Version 9 is ok | ||||
| # Later versions change some defaults so need extra wrangling. | ||||
| # .. there are extra files that are appended to the settings, per | ||||
| # .. clang-format version. | ||||
| # Version 7 and earlier doesn't understand all the options we would like. | ||||
| # Version 12 handled lambdas nicely and was the norm for Calamares 3.2. | ||||
| # Version 13 was also ok. | ||||
| # Version 14 behaves differently with short-functions-in-class, | ||||
| #   spreading functions out that 13 keeps on one line. To avoid | ||||
| #   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` | ||||
| case "$format_version" in | ||||
| 	[0-7] ) | ||||
| 		echo "! Clang-format version 8+ required" | ||||
| 		exit 1 | ||||
| 		;; | ||||
| 	[89] ) | ||||
| 	15|16|17 ) | ||||
| 		: | ||||
| 		;; | ||||
| 	* ) | ||||
| 		echo "! Clang-format version '$format_version' unsupported." | ||||
| 		echo "! Clang-format version '$format_version' unsupported, versions 15-17 are ok." | ||||
| 		exit 1 | ||||
| 		;; | ||||
| esac | ||||
| _fmt="$TOPDIR/.clang-format" | ||||
| cp "$_fmt.base" "$_fmt" | ||||
| for f in "$extra_settings" ; do | ||||
| 	test -f "$_fmt.$f" && cat "$_fmt.$f" >> "$_fmt" | ||||
| done | ||||
|  | ||||
|  | ||||
| ### FILE PROCESSING | ||||
| @@ -81,7 +72,6 @@ done | ||||
| style_some() | ||||
| { | ||||
| 	if test -n "$*" ; then | ||||
| 		$AS --options=$BASEDIR/astylerc --quiet "$@" | ||||
| 		$CF -i -style=file "$@" | ||||
| 	fi | ||||
| } | ||||
| @@ -98,8 +88,3 @@ if test "x$any_dirs" = "xyes" ; then | ||||
| else | ||||
| 	style_some "$@" | ||||
| fi | ||||
|  | ||||
| ### CLANG-FORMAT-WRANGLING | ||||
| # | ||||
| # Restore the original .clang-format | ||||
| cp "$_fmt.base" "$_fmt" | ||||
|   | ||||
| @@ -48,7 +48,6 @@ ERR_IMPORT, ERR_USAGE, ERR_FILE_NOT_FOUND, ERR_SYNTAX, ERR_INVALID = range(1,6) | ||||
| # | ||||
| try: | ||||
|     from jsonschema import validate, SchemaError, ValidationError | ||||
|     from jsonschema import draft7_format_checker | ||||
|     from yaml import safe_load, YAMLError | ||||
| except ImportError as 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 | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user