Compare commits

...

960 Commits

Author SHA1 Message Date
59bde93b91 add services-dinit 2023-12-26 02:44:23 +01:00
Adriaan de Groot
115f00f5cd [libcalamares] Rename tr() functions to avoid confusing lupdate 2023-12-25 14:24:06 +01:00
Adriaan de Groot
e73f5fb9fe [libcalamaresui] update percentage indicator on language change
Otherwise starting in one language will never change the
formatting of percentages when the language changes
later (example: Turkish writes %30, while Dutch writes 30%).

FIXES #2258
2023-12-25 00:06:00 +01:00
Adriaan de Groot
cd0a381a35 CI: make the openSUSE docker (Qt5) container more comfortable 2023-12-24 23:37:36 +01:00
Adriaan de Groot
709296940c i18n: suppress duplicated languages
The list of translations from Transifex contains "en", and we
add it explicitly a second time -- instead of fixing those and
needing to ensure that the source language is returned, or optionally
adding "en" if it isn't in the list already, just de-duplicate.

FIXES #2257
2023-12-24 23:01:37 +01:00
Adriaan de Groot
00821945c5 Changes: post-release housekeeping 2023-12-15 15:59:58 +01:00
Adriaan de Groot
1d8a197242 [partition] Repair test
Was picking up settings stored from a previous test,
leading to a spurious failure.
2023-12-12 00:04:06 +01:00
Adriaan de Groot
8e5fbef390 [users] Repair test of now-removed "nonempty" option 2023-12-11 22:55:36 +01:00
Adriaan de Groot
15710ef814 Changes: pre-release housekeeping 2023-12-11 22:53:48 +01:00
Calamares CI
1554424e1b i18n: [python] Automatic merge of Transifex translations 2023-12-11 22:20:33 +01:00
Calamares CI
8818a0381a i18n: [calamares] Automatic merge of Transifex translations 2023-12-11 22:20:28 +01:00
Adriaan de Groot
558f045b65 Merge pull request #2252 from calamares/issue-2225
Add support for systemd-machine-id variations
2023-12-11 22:18:03 +01:00
Adriaan de Groot
dd848142ad Merge pull request #2253 from Conan-Kudo/fix-mount-defaults
Fix mount defaults
2023-12-10 20:17:54 +01:00
Neal Gompa
5f897468ef [mount] Set btrfs compression default to zstd:1 to match comment default
The comment and examples above the mountOptions already indicate
zstd:1 for compression. Empirically, this has proven out to be a
reasonable default choice and should be actually used in the default
configuration.
2023-12-09 17:45:55 -05:00
Neal Gompa
84e66f8512 [mount] Drop noatime for baseline and btrfs defaults
The usage of noatime has subtle negative impacts on the system,
including breaking various utilities that rely on that information.

If a user or distribution explicitly chooses this, then they
acknowledge this problem and account for it, but it should not be
an uninformed default.

It's left in place for swap because it does not matter there and
likely reduces thrashing for swap files.
2023-12-09 17:45:40 -05:00
Adriaan de Groot
6b0d52ca5b Changes: add credits 2023-12-09 01:01:50 +01:00
Adriaan de Groot
acd0875f1d [users] Use more-modern CMake constructs 2023-12-09 00:59:26 +01:00
Adriaan de Groot
b2d9b20edc Merge pull request #2248 from EbonJaeger/add-crypt-gensalt-support
users: Add support for crypt_gensalt for user passwords
2023-12-09 00:25:43 +01:00
Adriaan de Groot
1b37eb1262 [machineid] Read systemd-style from config 2023-12-09 00:08:38 +01:00
Adriaan de Groot
89348910c3 [machineid] Document aliases (not visible in schema) 2023-12-09 00:08:19 +01:00
Adriaan de Groot
2f740564c6 [machineid] Run systemd-machine-id in host, telling it to modify target 2023-12-08 23:37:48 +01:00
Adriaan de Groot
e04e0260c9 [machineid] Apply coding style 2023-12-08 23:15:32 +01:00
Adriaan de Groot
e5ee28329d [machineid] Handle different settings of systemd-style 2023-12-08 22:43:00 +01:00
Adriaan de Groot
0eb387d6de [machineid] Default to running systemd-machine-id 2023-12-08 22:26:32 +01:00
Adriaan de Groot
0d11de4525 [libcalamares] Add missing parameter name 2023-12-08 22:04:46 +01:00
dalto8
82fd10408c Merge pull request #2234 from ArrayBolt3/calamares
[grubcfg] Don't silently ignore missing grub configuration items
2023-12-02 21:19:14 +00:00
Adriaan de Groot
e2899ffa1d CI: ensure the right ECM 2023-12-02 00:28:54 +01:00
Aaron Rainbolt
7e6ac140c4 [grubcfg] Write config keys even if they don't already exist 2023-12-01 15:46:36 -06:00
Adriaan de Groot
d2214b8d2e [users] Document retirement of 'nonempty' 2023-12-01 18:15:00 +01:00
Adriaan de Groot
4e3de90cd0 [users] Document password settings 2023-12-01 18:01:58 +01:00
Adriaan de Groot
4262d9f051 [users] Expand documentation of the settings 2023-11-29 21:55:20 +01:00
Adriaan de Groot
a73266dc4c Merge pull request #2250 from fhdk/patch-1
Update CHANGES-3.3
2023-11-28 23:44:45 +01:00
dalto8
e8d0fa140a Merge pull request #2249 from EbonJaeger/add-clr-boot-manager-support
bootloader: Add clr-boot-manager support
2023-11-28 18:51:21 +00:00
Frede H
7fb31de183 Update CHANGES-3.3 2023-11-28 10:03:44 +01:00
Evan Maddock
1b07de6fa7 Apply suggestions from code review
Co-authored-by: Adriaan de Groot <groot@kde.org>
2023-11-27 19:02:50 -05:00
dalto8
63ce03680b Merge pull request #2246 from fhdk/initcpiocfg-bash-array-update
[initcpiocfg] use f-string - use new style bash array (issue #2243)
2023-11-27 18:22:38 +00:00
Frede H
d5f8fa11d9 Update CHANGES-3.3 2023-11-27 18:57:50 +01:00
Evan Maddock
7a4d03e2c1 bootloader: Write all kernel params to the kernel cmdline file for CBM
Signed-off-by: Evan Maddock <maddock.evan@vivaldi.net>
2023-11-27 10:47:51 -05:00
Evan Maddock
e13dbc621a bootloader: Add clr-boot-manager support
This adds support for Clear Boot Manager to handle the bootloader installation and configuration.

When this option is selected in the bootloader.conf, clr-boot-manager will be used to install the bootloader (systemd-boot on EFI systems). If the system is non-EFI, Grub must be installed first, because clr-boot-manager doesn't do that, despite it running grub_mkconfig after.

Signed-off-by: Evan Maddock <maddock.evan@vivaldi.net>
2023-11-26 17:27:57 -05:00
Evan Maddock
559d19018c users: Add support for crypt_gensalt for user passwords
This attempts to locate the presense of the crypt_gensalt function in the crypto library in use. Many distributions have switched to libxcrypt, which provides this function. This means that Calamares can use the native library implementation instead of generating password salts itself, which, depending on the distro's configuration, may be more secure.

If the function can not be found, fallback to the current method of generating password salts.

Signed-off-by: Evan Maddock <maddock.evan@vivaldi.net>
2023-11-26 16:54:07 -05:00
Adriaan de Groot
7a9a50d702 [libcalamares] AutoMount / kded6 has been tested by KaOS 2023-11-26 21:53:04 +01:00
Frede Hundewadt
98d534d5dd [initcpiocfg] use f-string - use new style bash array (issue #2243) 2023-11-26 14:57:19 +01:00
Adriaan de Groot
26236fe63a Changes: post-release, add some credits 2023-11-23 21:08:05 +01:00
Adriaan de Groot
a3d06e6d77 Merge pull request #2242 from krop/calamares
Update openSUSE repositories
2023-11-23 21:06:09 +01:00
Christophe Marin
b37afd4269 Update openSUSE repositories
Also make sure refresh is enabled.
2023-11-22 18:31:46 +01:00
Adriaan de Groot
01e7cf44c2 [libcalamares] Placeholder for KF6 automount DBus calls 2023-11-21 15:22:09 +01:00
Adriaan de Groot
5809b32c98 CI: expand fedora dependencies 2023-11-21 15:11:59 +01:00
Adriaan de Groot
8748a52c68 [keyboard] Add explanatory translation comment 2023-11-20 20:31:58 +01:00
Adriaan de Groot
65f93168f2 Merge pull request #2240 from demmm/calamares
[CMake] use KPMCore version to select Qt6
2023-11-19 20:57:45 +01:00
demmm
0e2fa42b60 [CMake] use KPMCore version to select Qt6
with 2588d1e796
KPMCore is Qt6 only, so any version from 24.01.75 on is Qt6, no need to check for Qt version this way
add missing NO_CONFIG to summaryq
2023-11-19 15:40:29 +01:00
Adriaan de Groot
5f06b321b2 CMake: correct copy-paste-o for destination of config files 2023-11-16 23:23:58 +01:00
Adriaan de Groot
146f549552 [libcalamares] Return None for empty GS keys
All unknown-variants return None, but this only
happens in practice with an empty variant (e.g.
a configuration key that is empty in the YAML).

FIXES #2237
2023-11-16 23:17:33 +01:00
Adriaan de Groot
8305b6cb1a [dummypython] Demonstrator for #2237 2023-11-16 23:10:53 +01:00
Adriaan de Groot
51a1d06c51 Changes: pre-release housekeeping 2023-11-16 22:54:17 +01:00
Adriaan de Groot
63211c86de Merge pull request #2236 from demmm/calamares
[partition] make the tests also build with Qt6
2023-11-16 22:51:13 +01:00
demmm
de85a02f74 [partition] make the tests also build with Qt6 2023-11-15 14:19:15 +01:00
Adriaan de Groot
8868ae956a [partition] Repair comparison 2023-11-14 13:50:08 +01:00
Adriaan de Groot
65e0740c49 Changes: post-release housekeeping 2023-11-13 21:57:45 +01:00
Adriaan de Groot
12413ad9e8 [partition] Add test demonstrating size edge-case 2023-11-13 21:32:05 +01:00
Adriaan de Groot
5c0b20d06a [partition] Enforce minimum <= recommended. 2023-11-13 21:28:10 +01:00
Adriaan de Groot
2ab0041180 [localeq] Repair translation-related typo
This would lead to a runtime error when loading the QML.
2023-11-13 20:10:52 +01:00
Calamares CI
ab6b7102e0 i18n: [python] Automatic merge of Transifex translations 2023-11-13 19:51:20 +01:00
Calamares CI
849ece4bb0 i18n: [calamares] Automatic merge of Transifex translations 2023-11-13 19:51:20 +01:00
Adriaan de Groot
2cf2665b84 Changes: pre-release housekeeping 2023-11-13 19:48:10 +01:00
Adriaan de Groot
6b1226d5ea Merge pull request #2206 from geckolinux/patch-1
Correct the comment description of the "Replace" partition behavior
2023-11-13 19:18:00 +01:00
Adriaan de Groot
eb77b208f8 Merge pull request #2226 from bitigchi/strings
Improve string formatting and context
2023-11-13 19:17:12 +01:00
Adriaan de Groot
1e1e12fad2 Merge branch 'issue-2018' into calamares
FIXES #2018
2023-11-13 00:47:31 +01:00
Adriaan de Groot
196dd55784 [partition] Test mixed-with-overlap settings 2023-11-13 00:40:58 +01:00
Adriaan de Groot
3e758d2d5c [partition] Extend test, fix bug indicated by test
Copy-paste-o, was using wrong string value for minimum size,
found by failing unit test.
2023-11-13 00:37:03 +01:00
Adriaan de Groot
45c11135b8 [partition] Extend tests with more config examples 2023-11-13 00:31:18 +01:00
Adriaan de Groot
d9aeb88275 [libcalamares] Add a clear() to GlobalStorage
While this isn't useful in production, it makes tests a lot
simpler to write since you don't have to wrestle with
creating new GS objects in order to start fresh.
2023-11-12 22:41:02 +01:00
Adriaan de Groot
f07e31de29 [partition] Test for basic legacy configuration 2023-11-12 22:28:27 +01:00
Adriaan de Groot
13acdace42 [partition] Start of tests for config 2023-11-11 23:46:00 +01:00
Emir SARI
37178b2273 Improve context 2023-11-10 13:34:01 +03:00
Adriaan de Groot
85350e63ef [partition] Put EFI settings in a sub-map 2023-11-09 23:31:17 +01:00
Adriaan de Groot
eb08c3facd [partition] Use API for consistent EFI-size GS key
While here, remove the textual entry in GS, which was unused.
2023-11-09 22:29:33 +01:00
Adriaan de Groot
449fba03be [partition] Factor out GS keys for EFI-size sharing 2023-11-09 22:17:51 +01:00
Adriaan de Groot
b06afd9074 [partition] Read minimum EFI size from GS 2023-11-09 22:06:12 +01:00
Adriaan de Groot
b72508546c [partition] Simplify variables for error messages 2023-11-09 21:57:55 +01:00
Adriaan de Groot
2b0c41609d CMake: restore INSTALL_CONFIG 2023-11-09 21:52:12 +01:00
Adriaan de Groot
1e12ad344f Changes: notes on some modifications 2023-11-09 00:34:05 +01:00
Adriaan de Groot
94caa9338a Merge pull request #2230 from Conan-Kudo/ci-fedora-40
CI: Switch Fedora Qt 6 builds to Fedora Linux 40
2023-11-09 00:26:03 +01:00
Neal Gompa
2bd4c19a7d CI: Switch Fedora Qt 6 builds to Fedora Linux 40
Fedora Linux 40 has the necessary components as part of upgrading
to KDE Plasma 6.
2023-11-08 06:42:16 -05:00
Adriaan de Groot
6e9dac3417 libcalamares: apply coding style 2023-11-07 23:43:09 +01:00
Adriaan de Groot
c506808d72 partition: factor out 32_MiB constant 2023-11-07 23:41:10 +01:00
Adriaan de Groot
d0ae922439 partition: introduce accessor for minimum-size EFI 2023-11-07 23:37:31 +01:00
Adriaan de Groot
45529ebdc1 partition: rename API to emphasize recommended and strict-minimum 2023-11-07 23:30:56 +01:00
Adriaan de Groot
bc45f57b48 partition: introduce more settings for EFI size 2023-11-07 22:46:39 +01:00
Adriaan de Groot
ac265e6ff7 Changes: add contributor names 2023-11-07 21:56:49 +01:00
Adriaan de Groot
1051033324 libcalamares: create Python module libcalamares by hand
From inside Calamares, register libcalamares to the
interpreter by hand; from external Python processes
the regular extension library hooks are called.

Tested by running ./build/localmodule dummypython
(which means that the shared library is not present
in the current directory, so then `import libcalamares`
fails if the module is not already registered --
a test scenario that previous attempt at module
import missed).
2023-11-07 21:42:05 +01:00
Adriaan de Groot
a629e2650a libcalamares: importing the embedded python module can fail 2023-11-07 13:40:10 +01:00
Adriaan de Groot
5346008b7a libcalamares: repair names for recent translations
bqi is one possible name of Luri / Lhur language,
as far as I can tell -- there is also Northern Luri,
which is supported by Qt and has code lrc.

ie is Interlingue, which Qt maps to C locale.
Work around that by mapping it to interlingua.
2023-11-07 13:25:37 +01:00
Adriaan de Groot
cb42b3af6a i18n: update language list 2023-11-07 13:13:26 +01:00
Calamares CI
bcd753c28b i18n: [python] Automatic merge of Transifex translations 2023-11-07 13:13:26 +01:00
Calamares CI
637084511e i18n: [calamares] Automatic merge of Transifex translations 2023-11-07 13:13:26 +01:00
Adriaan de Groot
32f8a3cbac i18n: adapt txstats to newer Transifex API
The language list hasn't updated in a long time, and the API
changed underneath. Update the getter -- while at it, this
changes the "completion" criterium to count only the strings
in Calamares itself, not the fdo + python bits too.
2023-11-07 12:57:39 +01:00
Adriaan de Groot
d2c3f7a326 libcalamares: improve formatting of Qt error messages
These come through without function information, but we
can format them in one line by mis-using function info.
2023-11-07 00:53:10 +01:00
Adriaan de Groot
b57db97412 libcalamares: massage logging
Make the log-to-file always follow columns (with time
at the start of each line) so that stdout and the
log file look more alike.
2023-11-07 00:53:10 +01:00
Adriaan de Groot
cdd50681cd calamares: log settings and logfile paths again
When setting up the application, output goes to stdout,
so do it again once the logfile is configured, so that
these specific settings are in the log file as well.
2023-11-07 00:53:10 +01:00
Adriaan de Groot
18689074a8 libcalamares: add accessor for settings path 2023-11-07 00:53:10 +01:00
Adriaan de Groot
cfadf8f95a CI: add a -deps shell script for EndeavourOS 2023-11-07 00:53:10 +01:00
dalto8
ce1ecdba32 Merge pull request #2227 from jpwhiting/work/whiting/dontmountemptysubvolume
If a mountPoint has subvolume: "" don't try to mount the subvolume with a wrong "subvol=," argument.
2023-11-05 18:55:23 +00:00
Adriaan de Groot
848137390e Merge pull request #2228 from jpwhiting/work/whiting/sparsersync
Use rsync option -S
2023-11-04 22:41:17 +01:00
Gaël PORTAY
194ebeba94 Use rsync option -S
The filesystems may contains huge sparse files (for example the docker
data file at path /var/lib/docker/devicemapper/devicemapper/data that is
100G big).

These files causes rsync to fail if the target file-system is too small
to copy them.

The option --sparse tells rsync to turn sequences of nulls into sparse
blocks.

        --sparse, -S

        Try to handle sparse files efficiently so they take up less
        space on the destination. If combined with --inplace the file
        created might not end up with sparse blocks with some
        combinations of kernel version and/or filesystem type. If
        --whole-file is in effect (e.g. for a local copy) then it will
        always work because rsync truncates the file prior to writing
        out the updated version.

        Note that versions of rsync older than 3.1.3 will reject the
        combination of --sparse and --inplace.

This adds the rsync short option -S to let rsync handle sparse files.

Fixes:

        18:03:36 [6]: static CalamaresUtils::ProcessResult CalamaresUtils::System::runCommand(CalamaresUtils::System::RunLocation, const QStringList&, const QString&, const QString&, std::chrono::seconds)
            Running "env" ("sync")
            ..  Finished. Exit code: 0
            ..  Target cmd: ("sync") output:

        rsync: [receiver] write failed on "/tmp/calamares-root-81qie5d1/var/lib/docker/devicemapper/devicemapper/data": No space left on device (28)
        rsync error: error in file IO (code 11) at receiver.c(378) [receiver=v3.2.3]

Signed-off-by: Jeremy Whiting <jpwhiting@kde.org>
2023-11-03 09:59:06 -06:00
Jeremy Whiting
deb35d8b49 If a mountPoint has subvolume: "" don't use subvol= arguments.
When testing with a / mountPoint set to subvolume: "" it tried and
failed to mount the subvolume:

    .. Running ("mount", "-t", "btrfs", "-o", "subvol=,", "/dev/sda3", "/tmp/calamares-root-ylvhpxys/")
    .. Target cmd: ("mount", "-t", "btrfs", "-o", "subvol=,", "/dev/sda3", "/tmp/calamares-root-ylvhpxys/") Exit code: 32 output:
 mount: /tmp/calamares-root-ylvhpxys: wrong fs type, bad option, bad superblock on /dev/sda3, missing codepage or helper program, or other error.

This fix makes the following config in mount.conf let us drop out of any
subvolume handling:

btrfsSubvolumes:
    - mountPoint: /
      subvolume: ""
2023-11-03 08:27:36 -06:00
Adriaan de Groot
44d12379bd machineid: pass around enum for style 2023-11-02 21:22:35 +01:00
Adriaan de Groot
97da73b170 CI: don't fail the deps-installation scripts
Let CMake detect missing dependencies, one stage later in CI
2023-10-31 16:29:54 +01:00
Adriaan de Groot
083b0fb1e5 machineid: add configuration option for machine-id
SEE #2225
2023-10-30 23:25:21 +01:00
Adriaan de Groot
d3a767bad8 Merge branch 'issue-2018' into calamares
FIXES #2018
2023-10-30 22:40:34 +01:00
Adriaan de Groot
f6d1d81b01 partition: re-jig the EFI partition messages 2023-10-30 22:40:13 +01:00
Adriaan de Groot
026d1cb5e4 partition: add checks for absolute minimum size of EFI 2023-10-30 21:24:24 +01:00
Adriaan de Groot
f55161c06a Merge branch 'issue-2202' into calamares
FIXES #2202
2023-10-30 20:08:52 +01:00
Adriaan de Groot
757f8a8f9e packagechooser: handle differences in AppStreamQt API 2023-10-30 20:08:19 +01:00
Adriaan de Groot
a6dd49ac07 packagechooser: rename #define for AppStreamQt
Make explicit that it is set to a version (if it is defined at all).
2023-10-30 00:37:38 +01:00
Adriaan de Groot
b7545fded3 dummypython: add a ton of calls to setprogress()
Stress testing for #1912
2023-10-29 22:03:28 +01:00
Adriaan de Groot
8688285a25 CI: enable schema checks in the openSUSE nightly 2023-10-29 21:47:03 +01:00
Adriaan de Groot
741fe03969 netinstall: repair schema
The URIs were now being resolved (to the calamares.io domain) rather
than looked up locally. Make them local by prepending #/ in $ref s
2023-10-29 21:41:33 +01:00
Adriaan de Groot
82b5d50c34 CI: adapt schema tool to recent releases of pyyaml
Don't import a specific draft validator (it isn't used anyway,
and the validator is picked up from the schema's version)
2023-10-29 21:40:31 +01:00
Adriaan de Groot
350be92cd1 Merge branch 'work/adridg/pybind-fix' into calamares
FIXES #2223
2023-10-29 00:38:22 +02:00
Adriaan de Groot
fe45d32ef9 luksbootkeyfile: repair schema (add missing enum value) 2023-10-29 00:34:57 +02:00
Adriaan de Groot
db02ae0ce7 bootloader: repair schema (add missing properties) 2023-10-29 00:30:57 +02:00
Adriaan de Groot
ee90fee7bb CMake: be more chatty around results of validation-dependency check 2023-10-28 22:32:11 +02:00
Adriaan de Groot
627cb6b90a CMake: adapt to deprecations in CMake 3.28 2023-10-28 22:31:12 +02:00
demmm
27934ddaac Merge pull request #2224 from demonkillerr/calamares
Fix small typo in module config documentation
2023-10-26 11:02:48 +02:00
DemonKiller
8f82dc8668 fix small typo in docs 2023-10-26 13:17:50 +05:30
Adriaan de Groot
5f011e5d19 CI: bump fedora to latest 2023-10-25 23:58:05 +02:00
Adriaan de Groot
e68f7b0bf3 dummypython: log things more sensibly 2023-10-25 00:35:50 +02:00
Adriaan de Groot
c5139e62bc libcalamares: one more round with module
Tested with:

- python -c 'import libcalamares ; print(libcalamares.VERSION);'
- loadmodule dummypython
- full install of KaOS
2023-10-24 23:46:58 +02:00
Adriaan de Groot
1c0559affa libcalamares: don't bind to temporaries
Clang warns about range-for-loop binding a reference
to temporaries, and these are pybind11 handles anyway
so are cheap to copy.
2023-10-24 22:18:10 +02:00
Adriaan de Groot
d435ddd955 libcalamares: don't name unused parameters 2023-10-24 22:15:10 +02:00
Adriaan de Groot
5d1b94a708 libcalamares: don't name unused parameters 2023-10-24 22:14:26 +02:00
Adriaan de Groot
f24df7ccc9 libcalamares: use Pybind11Helpers consistently
This header includes all of the needed pybind11 headers,
but also wrangles defines and warnings in one spot.
2023-10-24 22:13:06 +02:00
Adriaan de Groot
019450132e libcalamares: add missing parent constructor call to PythonJob 2023-10-24 22:06:25 +02:00
Adriaan de Groot
1c2480a308 packagechooser: suppres signedness warning 2023-10-24 21:55:03 +02:00
Adriaan de Groot
d0bb6134ae keyboard: remove unused variable 2023-10-24 21:48:58 +02:00
Adriaan de Groot
dac6931e81 libcalamares: switch Python to an embedded module
This breaks python scripts that `import libcalamares` running
outside of the framework (e.g. outside of a Calamares job).
2023-10-24 15:33:26 +02:00
Adriaan de Groot
8bea736651 libcalamares: make VERSION in Python modules the full-version 2023-10-24 15:31:09 +02:00
Adriaan de Groot
da0ce1d3d6 libcalamares: move Python module-definitions to the Job 2023-10-24 15:29:07 +02:00
Adriaan de Groot
3ffa4f5bf6 libcalamares: mount() is part of the Python API 2023-10-24 15:24:12 +02:00
Adriaan de Groot
0d3519fe79 libcalamares: tidy up API documentation
The __attribute__ on the namespace confuses clang-tidy, which is
why this one namespace is indented.
2023-10-24 15:14:08 +02:00
Adriaan de Groot
ede1c29a0e libcalamares: embed the pybind11 API differently 2023-10-24 15:04:08 +02:00
Adriaan de Groot
f496570df4 CI: accept more clang-format versions 2023-10-24 14:55:24 +02:00
Adriaan de Groot
367c434754 Merge branch 'work/adridg/nam-thread' into calamares 2023-10-24 14:10:02 +02:00
Adriaan de Groot
4f585b6f2e CI: improve KaOS dependencies installation 2023-10-24 11:32:14 +02:00
Adriaan de Groot
7790d52a4d CI: improve KaOS deps installation 2023-10-24 02:15:34 +02:00
Adriaan de Groot
6ba8d9fd7d modules: adapt to changes in network manager 2023-10-24 02:01:19 +02:00
Adriaan de Groot
8ebba4fcff libcalamares*: adapt consumers of network manager 2023-10-24 02:01:19 +02:00
Adriaan de Groot
35998066c2 libcalamares: re-do singleton-ness of NetworkAccessManager
The Calamares Manager should not be a singleton; it is needed
in multiple threads (e.g. from QML). It can have a singleton
Private manager that caches and shares things, though.
2023-10-24 02:01:19 +02:00
Adriaan de Groot
cfc5b03264 contextualprocess: repair typo from string-fix 2023-10-24 00:01:06 +02:00
Adriaan de Groot
01564695a6 CI: add a deps-kaos for convenience in building there 2023-10-24 00:00:21 +02:00
Adriaan de Groot
7141450e37 Changes: credit for openSUSE CI updates 2023-10-23 23:07:31 +02:00
Adriaan de Groot
8edb5f4290 Merge pull request #2222 from bitigchi/strings
Improve string formatting and context
2023-10-23 23:06:23 +02:00
Adriaan de Groot
0e9d7bc446 CI: fix up opensuse depends, find Python 2023-10-23 22:45:06 +02:00
Adriaan de Groot
f0d13fc9c4 libcalamares: repair build for Qt6 2023-10-23 22:20:02 +02:00
Adriaan de Groot
594bc5b169 Merge pull request #2221 from krop/calamares
Improve the openSUSE CI files
2023-10-23 21:54:37 +02:00
Emir SARI
682cbe6951 Improve string formatting and context 2023-10-23 13:39:26 +03:00
Christophe Marin
107def4594 CI: openSUSE: prefer CMake provides over package name
Even if the package name changes, installation will still work.
2023-10-23 09:41:13 +02:00
Christophe Marin
aee0786c22 CI: change the openSUSE Qt6 repository
home:krop:Qt6 is only used to prepare new releases and disabled afterwards.
Use KDE:Qt6 instead.
2023-10-23 09:16:39 +02:00
Adriaan de Groot
8bd2d684b9 libcalamares: catch Python errors in more places
- (syntax) errors in the pre-script or the module's script
  should not trigger a fatal error in Calamares (i.e. terminate
  called because of uncaught Python exception).
- Log more clearly where the error is being caught.
2023-10-23 01:18:45 +02:00
Adriaan de Groot
e5c2066d28 libcalamares: fix build 2023-10-22 14:38:25 +02:00
Adriaan de Groot
f81383901d Changes: document translation updates 2023-10-22 13:52:21 +02:00
Adriaan de Groot
4297a00537 Merge pull request #2210 from bitigchi/strings
Improve string formatting and context
2023-10-22 13:50:38 +02:00
Adriaan de Groot
ff760d84a3 libcalamares: implement mount() for Python 2023-10-22 13:32:22 +02:00
Adriaan de Groot
af9b41e1a9 libcalamares: provide pybind11 constructor for GS
This constructor (of the proxy object) is used only by
test-code (see also comment in the Boost implementation)
but needs to be made explicit now.
2023-10-22 13:20:29 +02:00
Adriaan de Groot
b2337c82a7 libcalamares: repair submodule utils 2023-10-21 16:34:07 +02:00
Adriaan de Groot
945180e1d3 CI: accept clang-format-16 as well 2023-10-21 16:22:37 +02:00
Adriaan de Groot
71d27eee8e hostinfo: ditch flaky test 2023-10-21 15:47:10 +02:00
Adriaan de Groot
5846ea384a machineid: ditch flaky test 2023-10-21 15:43:19 +02:00
Adriaan de Groot
a649b67880 machineid: document flaky test 2023-10-17 22:54:08 +02:00
Adriaan de Groot
aaa82386d8 libcalamaresui: always use KOSRelease
The places where KOSRelease was ifdeffed always set the ifdef in
the surrounding CMake code, so make it unconditional.
2023-10-17 22:46:11 +02:00
Adriaan de Groot
63b0589382 CI: apply style tool across the entire codebase 2023-10-17 22:24:46 +02:00
Adriaan de Groot
e1747af296 CI: use clang-format to add braces 2023-10-17 22:17:01 +02:00
Adriaan de Groot
183f88a846 CI: Document changed coding style 2023-10-17 21:44:33 +02:00
Adriaan de Groot
dcce7d8a57 Merge branch 'work/adridg/remove-boost' into calamares 2023-10-16 20:08:06 +02:00
Adriaan de Groot
3594a64bd1 Python: add the processing-output functions, too 2023-10-16 20:07:39 +02:00
Adriaan de Groot
42172826ca loadmodule: extend test-module-loader application
- Introduce -S to load settings beforehand, allows testing
  in dont-chroot and debug and OEM modes.
2023-10-16 20:07:39 +02:00
Adriaan de Groot
d0dd4b765c Python: add checked and stdout-returning API 2023-10-16 20:07:39 +02:00
Adriaan de Groot
995f6c8ce3 Python: add target_env_call API 2023-10-16 20:07:39 +02:00
Adriaan de Groot
89ede4bcce Python: add the API to the public header again
- add libcalamares.job
- add libcalamares.globalstorage
2023-10-16 20:07:39 +02:00
Adriaan de Groot
ec5a4cb423 Python: support injected pre-script (for testing) 2023-10-16 20:07:39 +02:00
Adriaan de Groot
24de6b69c4 Python: deal with Qt5 compatibility
QDebug can't log std::string in Qt5, it seems
2023-10-16 20:07:39 +02:00
Adriaan de Groot
0468ff400b Python: add top-level descriptive variables 2023-10-16 20:07:39 +02:00
Adriaan de Groot
30e677a762 Python: call the module's run() function 2023-10-16 20:07:39 +02:00
Adriaan de Groot
bfb23b3b84 Python: get pretty_name from Python module
Add a convenience method for logging pybind11 objects.
2023-10-16 20:07:39 +02:00
Adriaan de Groot
dd2da734ba Python: load a module
- add enough API so that the dummypython module does load
- interpreter only imports the module, does not run any part of it
2023-10-16 20:07:39 +02:00
Adriaan de Groot
4411c54ba2 Python: do preliminary script-checks 2023-10-16 20:07:39 +02:00
Adriaan de Groot
61f0100cd9 Python: add new Python job implementation
The implementation is quite incomplete: it does not
actually run any Python code.
2023-10-16 20:07:39 +02:00
Adriaan de Groot
1eba9c828c Python: mini-API implementation
Just some string-related functions for a very basic module.
2023-10-16 20:07:39 +02:00
Adriaan de Groot
5cad467a49 Python: use the vendored pybind11
Add a target that resembles what you would get from "normal"
use of pybind11 when following the examples. Link with it.
Drop Boost:Python sources from libcalamares.
2023-10-16 20:07:39 +02:00
Adriaan de Groot
35ae45e3ec Docs: mention Boost::Python retired 2023-10-15 22:23:27 +02:00
Emir SARI
125a58f7c0 Process more messages 2023-10-15 14:39:17 +03:00
Emir SARI
814f5f0ccc Improve formatting 2023-10-15 14:19:57 +03:00
Adriaan de Groot
546a4d0bbb CI: switch opensuse-qt6 away from boost 2023-10-15 00:58:56 +02:00
Adriaan de Groot
3a04d27455 3rdparty: import pybind11 v2.11.1
This is a stripped-down version, with the LICENSE and the
C++ headers intact.
2023-10-15 00:58:56 +02:00
Adriaan de Groot
74edf6aef4 Changes: mention Qt6-QML fix 2023-10-14 23:58:51 +02:00
Adriaan de Groot
2a314bd06e Merge pull request #2215 from demmm/calamares
[QML modules] add Qt6 needed files
2023-10-14 23:57:37 +02:00
Adriaan de Groot
7e456d5a8c Changes: post-release housekeeping 2023-10-14 23:39:39 +02:00
demmm
2d2436f9a5 [QML modules] add Qt6 needed files
use alias for all -qt6.qrc QML files, so no change is needed for Qml.cpp searchQML files
most QMl does not need QtGraphicalEffects
keyboardq duplicate all .xml files too
2023-10-14 19:56:53 +02:00
Adriaan de Groot
7abbcd685e users: repair broken tests
Applying the styling tool breaks the string literals.
2023-10-14 00:33:04 +02:00
Adriaan de Groot
d8415cfd53 shellprocess: repair broken tests
Applying calamaresstyle to this file re-formats the
raw-string-literals, which breaks the tests. Restore
the previous string formatting.
2023-10-14 00:27:44 +02:00
Adriaan de Groot
9bd600cab6 CMake: repair ca9006a1bc
Misplaced $, and looking for translation sources in the
wrong directory, led to a test-case failure before release.
2023-10-14 00:15:05 +02:00
Adriaan de Groot
d196dde23f Changes: pre-release housekeeping 2023-10-13 23:49:06 +02:00
Calamares CI
6ed627f7b7 i18n: [python] Automatic merge of Transifex translations 2023-10-13 23:44:46 +02:00
Calamares CI
7a17df6bcd i18n: [calamares] Automatic merge of Transifex translations 2023-10-13 23:44:46 +02:00
Adriaan de Groot
19473f8b5d Docs: mention that you can use any Matrix account, not just a KDE one 2023-10-12 23:01:50 +02:00
Adriaan de Groot
0ed3dd4af9 Changes: document more contributors 2023-10-12 22:51:03 +02:00
Adriaan de Groot
7f594b0069 Changes: document Qt6-QML compatibility 2023-10-12 22:49:58 +02:00
Adriaan de Groot
2b147a2998 welcomeq: have Qt5 and Qt6 versions of the QML as an example 2023-10-12 22:35:32 +02:00
Adriaan de Groot
4a5e7af9a4 libcalamaresui: support Qt6 QMLViewStep 2023-10-10 23:51:52 +02:00
Adriaan de Groot
628c98becb libcalamaresui: apply coding style (include order) 2023-10-10 23:51:52 +02:00
Emir SARI
e60d981e07 Improve string formatting and context 2023-10-10 12:55:31 +03:00
Adriaan de Groot
cf9f283a8e Merge pull request #2209 from lubuntu-team/lubuntu/netplan-configs
Quick vendor patch to add support for Netplan-based configs
2023-10-09 22:31:34 +02:00
Adriaan de Groot
367c5097e0 Merge pull request #2208 from bitigchi/strings
Improve string formatting and context
2023-10-09 22:30:19 +02:00
Simon Quigley
e5db326a7e Quick vendor patch to add support for Netplan-based configs 2023-10-08 21:37:26 -05:00
Adriaan de Groot
d4b0513993 CI: neon use ninja for install step 2023-10-07 10:37:12 +02:00
Adriaan de Groot
ca76392d28 CI: missing tools for debian build 2023-10-07 10:37:12 +02:00
Emir SARI
108b6759f7 Improve string formatting and context
Improves some strings according to the KDE HIG, and specifies
whether they are titles, buttons, or tooltips.
2023-10-06 07:05:42 +03:00
Adriaan de Groot
215b0790fd CI: add fedora to the mix 2023-10-03 16:18:06 +02:00
Adriaan de Groot
ed1f4876aa CI: switch example & CI builds to ninja 2023-10-03 15:04:33 +02:00
Adriaan de Groot
6b61197402 Docs: repair CONTRIBUTING, mention neon-unstable 2023-10-03 15:04:33 +02:00
Adriaan de Groot
125f54d830 CI: add a nightly neon-unstable 2023-10-03 13:56:58 +02:00
Adriaan de Groot
54d0e7dc53 CI: repair permissions on Debian deps 2023-10-03 13:53:30 +02:00
Adriaan de Groot
d940675445 Docs: repair CONTRIBUTING
The docker images are ok, but the install-the-dependencies scripts have
moved away from GitHub-specific.
2023-10-03 13:43:13 +02:00
GeckoLinux
d4accae21b Correct the comment description of the "Replace" partition behavior
The described behavior of the "Replace" option was incorrect, it does not keep the same filesystem type that the partition already had, rather it uses the `defaultFileSystemType` value. See:
https://github.com/calamares/calamares/issues/1970
2023-10-01 19:23:35 -05:00
Adriaan de Groot
309fa9718e users: repair build on openSUSE Qt6
Build failure looks like

/usr/lib64/gcc/x86_64-suse-linux/13/../../../../x86_64-suse-linux/bin/ld:
  src/modules/users/CMakeFiles/users_internal.dir/users_internal_autogen/mocs_compilation.cpp.o:
  relocation R_X86_64_32 against symbol `_ZN6Config16staticMetaObjectE' can not be used when making a shared object; recompile with -fPIC
/usr/lib64/gcc/x86_64-suse-linux/13/../../../../x86_64-suse-linux/bin/ld: failed to set dynamic section sizes: bad value

This was the original reason for starting to change the library type.
2023-10-02 00:37:59 +02:00
Adriaan de Groot
fb9b20e234 CI: need newer Qt6 for now on openSUSE 2023-10-02 00:27:50 +02:00
Adriaan de Groot
1fb9af4823 CI: fix up Debian scripts 2023-10-01 16:38:03 +02:00
Calamares CI
add7ed3731 i18n: [python] Automatic merge of Transifex translations 2023-09-28 22:41:46 +02:00
Calamares CI
4eef62a481 i18n: [calamares] Automatic merge of Transifex translations 2023-09-28 22:41:45 +02:00
Adriaan de Groot
ed2a5a7973 CMake: pre-release housekeeping 2023-09-28 22:34:54 +02:00
Adriaan de Groot
7c475e1198 CI: remove appstreamqt5 from deps-neon
Package doesn't exist. See #2202.
2023-09-28 22:25:58 +02:00
Adriaan de Groot
445f1c0f56 CI: script-tidying 2023-09-28 22:22:43 +02:00
Adriaan de Groot
74a5d76145 CI: switch Debian to ci/ scripts 2023-09-28 22:21:25 +02:00
Adriaan de Groot
4499d7590d CI: switch opensuse workflows to simple script 2023-09-28 22:14:31 +02:00
Adriaan de Groot
7b5a2ad68c CI: switch push workflow to simple script 2023-09-28 22:13:23 +02:00
Adriaan de Groot
0eb84acc4b CI: migrate push workflow to ci/ scripts 2023-09-28 22:05:07 +02:00
Adriaan de Groot
675d17fe59 CI: migrate opensuse CI to ci/ scripts 2023-09-28 22:04:07 +02:00
Adriaan de Groot
aef757cc20 fixup-prev 2023-09-28 21:56:56 +02:00
Adriaan de Groot
6f346d635e CI: move the dependency-scripts to non-GH locations 2023-09-28 21:55:17 +02:00
Adriaan de Groot
3637914aea CI: remove pullrequest workflow, the GH widget does that 2023-09-28 21:52:11 +02:00
Adriaan de Groot
889d78deed CI: bump checkout action to latest version 2023-09-28 21:50:35 +02:00
Adriaan de Groot
7ece6f9d2c CI: install the right flavor of appstreamqt
Needs "qt5" for the Qt5 version, and no suffix for Qt6. Now we can
at least spot the build error in neon-nightly.

SEE #2202
2023-09-28 21:40:05 +02:00
Adriaan de Groot
0cc8842c42 CI: chase GitHub actions updates 2023-09-28 21:34:52 +02:00
Adriaan de Groot
364e940a9a CMake: don't default to SHARED libraries, require explicit 2023-09-28 20:56:09 +02:00
Adriaan de Groot
77d489b5e5 users: repair previous "fix"
The build failure on openSUSE is real, but the "fix" switched
the internal library accidentally to SHARED, without installing it.
It shouldn't be a library at all, really (if STATIC won't do).

FIXES #2203
2023-09-28 20:55:39 +02:00
Adriaan de Groot
44d26beb95 CI: install appstream in KDE neon
Let this run overnight so we can see the appstream-api-change locally.

See #2202
2023-09-19 23:47:41 +02:00
Adriaan de Groot
4cb8962668 CI: need to install git in opensuse before checkout 2023-09-12 10:09:26 +02:00
Adriaan de Groot
440f704930 Docs: update list of requirements, mention 3.2 is different 2023-09-12 10:05:28 +02:00
Adriaan de Groot
6e8e8a3d1b Changes: document Qt6 and CalamaresUtils 2023-09-11 21:05:43 +02:00
Adriaan de Groot
a62f060fdd CI: fix broken path, swap push to use shell script for dependencies 2023-09-11 20:46:55 +02:00
Adriaan de Groot
1efb12e332 libcalamares: rename CalamaresUtilsSystem and Gui 2023-09-11 20:40:10 +02:00
Adriaan de Groot
eb840d4117 libcalamares: ditch namespace CalamaresUtils
- Most CalamaresUtils things go to Calamares
- YAML support to Calamares::YAML and then remove redundant "yaml"
  from the function names.
2023-09-11 20:34:01 +02:00
Adriaan de Groot
f4e3964ee5 libcalamares: use namespace Calamares::Partition consistently 2023-09-11 00:09:31 +02:00
Adriaan de Groot
641e186b7c libcalamares: use namespace Calamares::Packages consistently 2023-09-10 23:55:48 +02:00
Adriaan de Groot
a9ef587705 libcalamares: use namespace Calamares::Network consistently 2023-09-10 22:32:49 +02:00
Adriaan de Groot
d199288034 libcalamares: use namespace Calamares::GeoIP consistently 2023-09-10 22:26:32 +02:00
Adriaan de Groot
47cbcbd348 libcalamares: move all locale-related things into namespace Calamares::Locale
The locale bits were spread over Calamares::Locale and CalamaresUtils::Locale.
2023-09-10 22:26:32 +02:00
Adriaan de Groot
766c28ca82 interactiveterminal: prepare for Qt6
- Try to build with KF6
- Bodge out the actual loading-of-konsole-part
2023-09-10 22:26:32 +02:00
Adriaan de Groot
f4a80c1a01 Docs: deal with variations between Docker images 2023-09-10 22:26:32 +02:00
Adriaan de Groot
15b476bb80 CI: expand coverage of Qt6/KF6 dependencies 2023-09-10 22:26:32 +02:00
Adriaan de Groot
2b495a3781 Docs: update required versions 2023-09-10 21:40:37 +02:00
Adriaan de Groot
f2f1052da3 Docs: add a using-Docker section for builds 2023-09-10 21:35:39 +02:00
Adriaan de Groot
d04f17bb72 CMake: re-jig required/optional reporting again
- Don't use the ${kfname} package itself, use it as a prefix for
  specific components of that package (e.g. ${kfname}CoreAddons)
- Use TYPE to indicate required packages, rather than using
  REQUIRED in the find_package call, to more-helpfully collect
  missing requirements.
2023-09-10 21:34:15 +02:00
Adriaan de Groot
8925c34ff7 CMake: massage finding-of-things to be less demanding
1- Need to be careful switching dependencies from REQUIRED to OPTIONAL
2- Don't do ECM REQUIRED all over the place
3- Workaround neon CI not having KCrash (which translated to KF5 not
   found, which translated to a missing REQUIRED dependency, see 1).
2023-09-10 21:10:02 +02:00
Adriaan de Groot
63b7ecb97e CI: massage neon to use an in-repo shell script as well 2023-09-10 21:10:02 +02:00
Adriaan de Groot
472c07008e keyboardq: don't bother re-finding required Qt components 2023-09-10 20:23:19 +02:00
Adriaan de Groot
1b9d8b1f91 CI: tweak opensuse-qt6 nightly build
Split the install-dependencies off into a shell script instead of
being part of the workflow, so that it can be run manually or
by other means than the GH workflow.
2023-09-10 20:23:06 +02:00
dalto
f3f5bd8a5d [initcpiocfg] Revert addition of setfont 2023-09-10 12:53:31 -05:00
dalto
09ccdb4ecb [initcpiocfg] Fix typo in initcpiocfg.conf 2023-09-09 10:10:02 -05:00
dalto
23c4aa0aa4 [bootloader] Fix error in condition with uses_sd_encrypt 2023-09-09 10:09:30 -05:00
Adriaan de Groot
0a0edfada0 CMake: do REQUIRED searches at beginning, avoid toggle of KF5 status 2023-09-09 11:59:02 +02:00
Adriaan de Groot
0500eb54da users: workaround build failure
x86_64-suse-linux/bin/ld: libusers_internal.a(mocs_compilation.cpp.o):
  relocation R_X86_64_32 against symbol `_ZN6Config16staticMetaObjectE'
  can not be used when making a shared object; recompile with -fPIC
x86_64-suse-linux/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
2023-09-09 01:27:13 +02:00
Adriaan de Groot
60df29d734 Merge pull request #2164 from ivan1986/add-keyboard-group
add keyboard layout switch selector
2023-09-08 21:45:36 +02:00
Adriaan de Groot
c2064124b9 libcalamares: needs to link in QtNetwork 2023-09-08 21:41:31 +02:00
Adriaan de Groot
c2e4ba324f CI: try to work around KF5 staying 'required' at the end
The find_package() in the plasmalnf module seems to mark KF5 as not-found,
because one component is not found right then -- after that, CMake-time
fails because KF5 is still-required and not-found.
2023-09-08 21:34:50 +02:00
Adriaan de Groot
7f51aac81b CI: replace KDE neon by openSUSE 2023-09-07 23:47:39 +02:00
Adriaan de Groot
57746be66e kpmcore: factor out sometimes-needed dependencies 2023-09-07 23:45:57 +02:00
Adriaan de Groot
0d1adc0692 CMake: drop KDE-neon weirdness for KF6 2023-09-07 23:41:26 +02:00
Adriaan de Groot
7dffabef43 netinstall, tracking: KF6 use 2023-09-07 23:39:39 +02:00
Ivan Borzenkov
4d00eef822 fixes 2023-09-07 23:31:48 +03:00
Ivan Borzenkov
ea725da79b keyboard switch to same line 2023-09-07 21:57:58 +03:00
Ivan Borzenkov
1ac3459afa add keyboard layout switch selector 2023-09-07 21:57:58 +03:00
Adriaan de Groot
1b235e56a3 Merge pull request #2199 from demmm/calamares
[users] CheckPWQuality.cpp Qt6 correction
2023-09-07 20:03:32 +02:00
demmm
b8dd4ef20a [partition] Qt6 conversion completed
adjust QMouseEvents, update CHANGES
2023-09-07 18:10:21 +02:00
demmm
07e5a3a113 [partition] start Qt6 work
make kpmcorehelper usable for both kf5 & 6, though no section added yet dealing with set to NOT for Qt6
adjust CalamaresConfig to not be hardcoded to kf5
one more var needed in Variant.h, used in PartitionInfo.cpp
adjust QVariant & QtConcurrent use
2023-09-07 13:03:16 +02:00
dalto8
7c55529072 [initcpiocfg] Remove noconfig since a config file was added 2023-09-06 22:20:53 +00:00
demmm
14419ac26f [users] CheckPWQuality.cpp Qt6 correction
2 additional QVariant replacements
2023-09-06 18:33:24 +02:00
Adriaan de Groot
d4a06b4477 Changes: document Qt6-compatibility 2023-09-06 00:07:03 +02:00
Adriaan de Groot
bf7983dac8 Merge branch 'work/qt6-i18n' into calamares 2023-09-05 23:55:14 +02:00
Adriaan de Groot
1a865fd2fb CMake: reduce required KF5 version to support Debian 2023-09-05 23:54:44 +02:00
Adriaan de Groot
e1bb6f1eb3 CMake: remove Qt6 handholding of modules 2023-09-05 23:54:44 +02:00
Adriaan de Groot
ead610b429 zfs: adapt to Qt6 2023-09-05 23:54:44 +02:00
Adriaan de Groot
9d324bcccd users: adapt to Qt6 2023-09-05 23:54:36 +02:00
Adriaan de Groot
680d4f8dc2 preservefiles: adapt to Qt6 2023-09-05 23:54:36 +02:00
Adriaan de Groot
2eff5f74a5 plasmalnf: not compatible with Qt6 2023-09-05 23:54:36 +02:00
Adriaan de Groot
d7df1a8eca packagechooser: Adapt to Qt6
While here, deal with the WITH_ -> BUILD_ change of options.
2023-09-05 23:54:36 +02:00
Adriaan de Groot
90fefa9382 CI: repair name of Qt6 nightly 2023-09-05 16:01:06 +02:00
Adriaan de Groot
7b36dfb351 Merge pull request #2196 from AsahiLinux/keyboard-init-order
keyboard: Do the autodetection stuff after setConfigurationMap
2023-09-05 15:54:15 +02:00
Adriaan de Groot
1ca6b27afe Merge pull request #2195 from AsahiLinux/wayland-hidpi
Make HiDPI SVG rendering work on Wayland
2023-09-05 15:53:53 +02:00
Adriaan de Groot
07e7757c31 oemid: adjust to Qt6 2023-09-05 15:36:09 +02:00
Adriaan de Groot
f56250624f netinstall: adjust to Qt6 2023-09-05 15:34:04 +02:00
Adriaan de Groot
e781e4eb5f license: adapt to Qt6 2023-09-05 15:24:02 +02:00
Adriaan de Groot
427311f2c3 keyboard: port to QRegularExpression 2023-09-05 15:18:02 +02:00
Adriaan de Groot
22bd80daac hostinfo: adjust to Qt6 2023-09-05 00:05:57 +02:00
Adriaan de Groot
1b5206cb90 locale: adjust to Qt6 2023-09-05 00:05:57 +02:00
Adriaan de Groot
93e9990df8 keyboard: adapt to Qt6 2023-09-05 00:05:46 +02:00
Adriaan de Groot
6ffafe1c45 interactiveterminal: consider this KF5-only for now
It seems unlikely that a KF6-based terminal part from konsole
becomes available any time soon, so don't bother.
2023-09-05 00:05:46 +02:00
Adriaan de Groot
5f8b6ed437 dummycpp: adapt to Qt6
- since HashVariantType has more than one consumer, move it to header
2023-09-05 00:05:46 +02:00
Adriaan de Groot
e07b6c90d3 contextualprocess: adapt to Qt6 2023-09-05 00:05:46 +02:00
Adriaan de Groot
3173a8ee3c i18n: expand helper function to handle more cases
- move template QRC file to the module that defines the function
- add parameters to accept more files (prefixes) per language
2023-09-04 23:26:43 +02:00
Adriaan de Groot
ca9006a1bc i18n: move translation helper-function to CMakeModules 2023-09-04 22:44:08 +02:00
Adriaan de Groot
8a8860e75c Qt6: resolve TODOs against missing KF6
- On FreeBSD, no KF6 was available
- On KDE Neon Unstable, there are somewhat wonky KF6 packages available
- Adjust CMake to find the KDE Neon versions, then fix the C++ code
2023-09-04 21:51:03 +02:00
Hector Martin
1ca3ce7145 keyboard: Do the autodetection stuff after setConfigurationMap
Since we now rely on the layout1 mode being set from the config, we need
to defer the initial keymap detection until after that's initialized.

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-09-04 17:11:46 +09:00
Hector Martin
15027f40b2 Make HiDPI SVG rendering work on Wayland
Branding SVGs were rendering at 1x on Wayland and then scaling up to the
display DPI, which looks ugly. To get this to work properly we need to
explicitly multiply the devicePixelRatio into the dimensions that
QPixmaps render at, since QPixmap is DPI-unaware.

This probably only takes care of a subset of the problem codepaths, but
at least it makes the sidebar logo and welcome screen work properly.

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-09-04 14:35:14 +09:00
Adriaan de Groot
4b3278058b libcalamares: repair test
The calamaresstyle tool reformatted a bunch of R-strings,
leading to test failures. Mark them with INDENT-OFF so
astyle doesn't break them again.
2023-09-03 23:16:54 +02:00
Adriaan de Groot
30f65a0b62 CI: add a Qt6 build 2023-09-03 23:11:28 +02:00
Adriaan de Groot
8f836969eb Merge branch 'work/qt6' into calamares 2023-09-03 23:04:12 +02:00
Adriaan de Groot
95aa8d8127 libcalamares: update maintainer and sponsor 2023-09-03 23:02:47 +02:00
Adriaan de Groot
246d3f243d branding: update silly fake distro to 2023 2023-09-03 23:02:47 +02:00
Adriaan de Groot
30a8b337e1 finished: enable Qt6 build 2023-09-03 23:02:47 +02:00
Adriaan de Groot
c5929e30d1 welcome: enable Qt6 build
- Adjust for QVariant changes
- Fix tests, no more conversion available from QFile to QFileInfo
2023-09-03 23:02:09 +02:00
Adriaan de Groot
2ffcfb3ddd calamares: adapt UI-parts to Qt6 2023-09-03 23:02:09 +02:00
Adriaan de Groot
e1b20fe0a9 calamares: ignore about data (KF5) and highdpi
The application attribute for HighDPI is gone in Qt6.
2023-09-03 23:02:09 +02:00
Adriaan de Groot
8ea7c578b3 libcalamaresui: deal with QMessageBox::question 2023-09-03 23:02:09 +02:00
Adriaan de Groot
159eccbda0 libcalamaresui: enable build for Qt6
Compatibility code for mutex and variant is already in place.
2023-09-03 23:02:09 +02:00
Adriaan de Groot
bc9d5aae58 libcalamares: repair locale tests for Qt6 compatibility 2023-09-03 23:02:09 +02:00
Adriaan de Groot
49d449c211 i18n: enable Qt6 build of lang/ and libcalamares translations 2023-09-03 23:00:13 +02:00
Adriaan de Groot
ad8c87e5d3 libcalamares: repair tests for Qt6 compatibility 2023-09-03 23:00:13 +02:00
Adriaan de Groot
25250179da libcalamares: handle variants in Python
The Python helpers need a couple of obscure QVariants,
do not add them to the "global" list of compatible variant types.
2023-09-03 23:00:13 +02:00
Adriaan de Groot
cdb2eb8b9a libcalamares: deal with KF5 macro expansion
Since KF5 is not looked-for in the Qt6 build, mock up
a useless macro-expander in its place.
2023-09-03 23:00:13 +02:00
Adriaan de Groot
e0b820abbc libcalamares: deal with QtConcurrent::run
In Qt5, you pass the pointer-to-object for a member-function-call
first, and in Qt6, as a regular parameter.
2023-09-03 22:58:49 +02:00
Adriaan de Groot
fe8939e745 libcalamares: deal with QRegExp 2023-09-03 22:58:49 +02:00
Adriaan de Groot
99d012c5ce libcalamares: deal with QVariant
Compatibility header required, and logging was missing
a (transitively included in Qt5) include for QVariant.
2023-09-03 22:58:44 +02:00
Adriaan de Groot
27329a497a libcalamares: deal with QMutexLocker
- Add a compat/ directory with support for Calamares-named
  variations of Qt classes where there are relevant differences
  between Qt5 and Qt6
2023-09-03 22:58:33 +02:00
Adriaan de Groot
50f2a6ad4a libcalamares: deal with QPair
Use std::pair instead. Also applies to Qt5 build.
2023-09-03 22:53:43 +02:00
Adriaan de Groot
dfb778984c kdsingleapplication: make Qt5/6 independent 2023-09-03 22:53:43 +02:00
Adriaan de Groot
179796d598 CMake: can't mix KF5 and Qt6
This will fail to build because we require KDE Frameworks
CoreAddons, but I don't have one just now.
2023-09-03 22:53:43 +02:00
Adriaan de Groot
2b40ab9a5b CMake: make tests independent of Qt5/6 2023-09-03 22:53:43 +02:00
Adriaan de Groot
b905afb169 CMake: restrict Qt6 build
- build **only** libcalamares
- switch the finding and linking of Qt modules to use qtname
2023-09-03 22:53:43 +02:00
Adriaan de Groot
953479422c CMake: export Qt6 setting to the config file 2023-09-03 22:53:43 +02:00
Adriaan de Groot
cbdd3fc928 CMake: add top-level option for Qt6 2023-09-03 22:53:43 +02:00
Adriaan de Groot
5ff9fcd59a libcalamares: prevent astyle from reformatting string 2023-09-03 22:53:30 +02:00
Adriaan de Groot
e6ce29ed33 Merge pull request #2194 from AsahiLinux/passwd-fix
[users] Use usermod to disable passwords
2023-09-03 21:19:01 +02:00
Adriaan de Groot
4b87d094fb initcpiocfg: repair test
Empty example config files break tests; there should be at
least a single key in there (for instance, *bogus*, but
setting a flag to the default value is also acceptable)
2023-09-03 21:15:44 +02:00
Hector Martin
a377df2e65 [users] Use usermod to disable passwords
On Fedora 38 (and probably others), this step fails with:

passwd -dl root
passwd: Only one of -l, -u, -d, -S may be specified.

Use usermod to wipe and disable the root password instead, which should
work properly. We use '!' (opinions seem to differ on how to mark
disabled/unused accounts, but all of '*' '!' '!!' should have the same
effect in practice).

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-09-03 19:58:13 +09:00
dalto
7fa8fa680c [initcpiocfg] Make using systemd hook optional 2023-09-02 10:01:05 -05:00
Adriaan de Groot
741c7b75d8 Merge pull request #2193 from AsahiLinux/locale1-fix
[keyboard] Fix locale1 support for alternate layouts
2023-09-02 16:11:34 +02:00
Hector Martin
7806d264ab [keyboard] Fix locale1 support for alternate layouts
Copy&paste error caused setting the layout to fail for non-ASCII layouts
with an alternate layout/variant.

Fixes: 812d86130 (\"[keyboard] Add support for setting the layout via locale1\")
Signed-off-by: Hector Martin <marcan@marcan.st>
2023-09-02 22:15:45 +09:00
Adriaan de Groot
102c55d67d Changes: document keyboard improvement 2023-08-29 14:59:39 +02:00
Adriaan de Groot
6733815269 keyboard: prefer to clean up lists only once 2023-08-29 14:59:13 +02:00
Adriaan de Groot
b85fcff990 keyboard: removeEmpty doesn't need to be a method 2023-08-29 14:55:54 +02:00
Adriaan de Groot
55a2d71e3e Merge pull request #2136 from ivan1986/fix-non-ascii-keyboard
Write layout information for non-ASCII keyboard to X11 and console settnigs.

FIXES #2135
2023-08-29 14:48:12 +02:00
Adriaan de Groot
da7ec3f7cc Changes: document keyboard change 2023-08-29 14:39:43 +02:00
Adriaan de Groot
3fc8febeea keyboard: require QtDBus at top-level, tidy includes 2023-08-29 14:37:01 +02:00
Adriaan de Groot
7157ed3854 keyboard: add new keys to schema
The stated schema-default for useLocale1 is not entirely correct,
since the code checks for X11 vs. Wayland to determine what the
default should be.
2023-08-29 14:33:21 +02:00
Adriaan de Groot
6c6b7956d2 i18n: update English sources 2023-08-29 14:32:51 +02:00
Adriaan de Groot
8d61345cd6 Merge pull request #2180 from AsahiLinux/keyboard-locale1
keyboard: Add locale1 support & option to keep defaults
2023-08-29 11:41:37 +02:00
Adriaan de Groot
cf88ddbaa5 CMake: post-release housekeeping 2023-08-28 23:53:04 +02:00
Adriaan de Groot
8e19d6080d mount: use False as default for "claimed"
The regular tests would fail, because the sample global
configuration does not set the "claimed" value of a partition.
2023-08-28 22:54:22 +02:00
Adriaan de Groot
72bad83022 luksbootkeyfile: support explicit 'default' setting 2023-08-28 22:45:56 +02:00
Adriaan de Groot
3757fcf0bf libcalamares: drop useless variable 2023-08-28 22:33:56 +02:00
Adriaan de Groot
dc666d29b8 libcalamares: suppress unused-variable warning 2023-08-28 22:33:00 +02:00
Adriaan de Groot
8dfa123e81 CMake: pre-release housekeeping 2023-08-28 22:29:54 +02:00
Adriaan de Groot
ef47932deb CI: Remove some of the Matrix notification scripts
The GitHub Matrix-integration widget does these notifications,
more efficiently than running curl by hand.
2023-08-28 21:55:58 +02:00
dalto8
f804965a8d Merge pull request #2183 from Boria138/initcpiocfg
Updated the initcpiocfg module
2023-08-27 20:54:37 +00:00
Adriaan de Groot
66f36b2d03 docs: drop mention of IRC, prefer Matrix for communication 2023-08-27 22:42:44 +02:00
dalto8
0ddffad57c Merge pull request #2187 from bkmo/bkmo
Update LuksBootKeyFileJob.cpp to check for unencrypted boot with encrypted root
2023-08-26 19:40:45 +00:00
dalto
b5e0ebe4c9 [luksBootKeyFile] Remove unused function hasEncryptedRoot() 2023-08-26 14:15:18 -05:00
dalto
3552691e57 [grubcfg] Add rd.luks.key for systemd-encrypt hook 2023-08-26 11:22:41 -05:00
dalto
d12e40bc34 [initcpiocfg] Fix encryption hook not being added with encrypted /boot 2023-08-26 09:55:45 -05:00
Brian Morison
ab8159a77f Update LuksBootKeyFileJob.cpp 2023-08-20 13:28:06 -06:00
Brian Morison
f0fb39edd8 Update LuksBootKeyFileJob.cpp 2023-08-20 13:07:58 -06:00
dalto8
0eb431dd2b Merge pull request #2181 from AsahiLinux/hello-im-a-mac
[users] Handle Device Tree platforms (e.g. Apple Silicon) for guessing the product name
2023-08-20 17:02:17 +00:00
dalto
a9547af8e2 [initcpiocfg,grubcfg,bootloader] Minor code improvements 2023-08-20 10:39:36 -05:00
Boria138
b97a5d535c Fixed a stupid typo 2023-08-19 23:08:44 +06:00
Boria138
950e9d1d0a Added setfont check in mkinitcpiocfg 2023-08-19 21:00:25 +06:00
Boria138
9f8b848631 uses_sd-encrypt was changed to uses_sd_encrypt to make it a valid variable name 2023-08-19 15:29:49 +06:00
Boria138
c0396cf28b Deleted quot 2023-08-19 14:26:36 +06:00
Boria138
bf7f5c6032 Fixed initcpiocfg 2023-08-19 12:52:35 +06:00
Boria138
7d6a04d3a8 Added the necessary edits 2023-08-17 21:14:47 +06:00
Boria138
543de65f33 Added rd.luks.name to grubcfg 2023-08-17 13:04:24 +06:00
Boria138
5769c9c6da Fixes https://github.com/calamares/calamares/issues/2182 2023-08-17 12:44:13 +06:00
Boria138
438e0c6575 Updated the initcpiocfg module
Added systemd (I took the code from CachyOS and modified it a bit)
Fixed the error "setfont: KDFONTOP: Function not implemented"
2023-08-17 11:13:19 +06:00
dalto8
3bec262d2d Merge pull request #2176 from nintyfan/WIP/Packaging-Flatpak-2
Wip/packaging flatpak 2
2023-08-12 15:00:12 +00:00
Hector Martin
a899f76da2 [users] Clean up DMI model more for hostname
Remove anything in parentheses, and also drop the "Apple" prefix for
Apple machines. This converts:

"Apple MacBook Air (13-inch, M2, 2022)"

into:

"MacBookAir"

which is a lot more reasonable.

Other vendors could be added as needed (it's inconsistent whether DT
platforms prefix the model with the vendor or not).

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-08-12 22:48:26 +09:00
Hector Martin
17e1027ea2 [users] Read product from the device tree on DT platforms
Non-DMI platforms may have a device tree instead (e.g. many embedded
devices, Apple Silicon Macs). If we find a model string in the DT, use
that as a fallback when DMI is not available.

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-08-12 22:48:26 +09:00
Hector Martin
8be65003ce [keyboard] Use the current keyboard model as the default
If there is a valid keyboard model set in the system already, keep it.
This allows distributors to preconfigure the correct model if known.

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-08-12 22:09:31 +09:00
Hector Martin
6678d95a5d [keyboard] Add an option to disable layout guessing
If the system has already pre-configured a sensible keyboard layout, we
do not need to guess based on the locale. Add a config option to keep
the existing keyboard layout as the default. This should work on both
XKB/X11 and locale1 modes.

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-08-12 21:42:54 +09:00
Hector Martin
9e81d7cf21 [keyboard] Do not update configs in locale1 mode when root is /
If Calamares is running with no root path and we are using locale1 to
manage the keyboard configs, then the service has already updated the
X11 and VConsole keymap configs for us. In that case, we should not
touch the config files ourselves.

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-08-12 21:42:32 +09:00
Hector Martin
25bb41f549 [keyboard] Add support for getting the layout via locale1
Getter counterpart to the previous commit, to support using locale1 to
fetch the current keyboard config.

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-08-12 21:42:32 +09:00
Hector Martin
812d861307 [keyboard] Add support for setting the layout via locale1
setxkbmap only works on X11/XWayland, and even on XWayland does not
correctly change the Wayland keyboard layout.

The "modern" way to control the system keyboard layout is via the
locale1 DBus interface (or the localectl frontend). On compositors like
KWin, this will update the keyboard layout on the fly, which is what we
want.

Implement support for setting the layout/model configs using locale1.
This is enabled by default when Calamares runs under Wayland, and can be
controlled via a config setting.

Signed-off-by: Hector Martin <marcan@marcan.st>
2023-08-12 21:18:05 +09:00
Calamares CI
f53b064296 i18n: [python] Automatic merge of Transifex translations 2023-08-06 23:41:28 +02:00
Calamares CI
c43deac0a6 i18n: [desktop] Automatic merge of Transifex translations 2023-08-06 23:41:28 +02:00
Calamares CI
ea8b6255e3 i18n: [calamares] Automatic merge of Transifex translations 2023-08-06 23:41:28 +02:00
dalto8
44da0b24e5 Merge pull request #2161 from abalfoort/showbootmsg
partitioning: Show/hide "Boot partition not encrypted" warning
2023-08-05 14:05:32 +00:00
Sławomir Lach
ab7b78e9ce Newer flatpak will remove unused, so do not instruct for do that 2023-08-05 15:55:00 +02:00
Sławomir Lach
79085b5e80 - Uninstalling flatpak is possible (repair bad command) 2023-08-03 19:08:55 +02:00
Sławomir Lach
ec30fe1b61 - Force flatpak do not asks questions 2023-08-02 17:42:11 +02:00
Sławomir Lach
3666e3af7b Revert "Made possible to select flatpaks to install (fill list of netinstall)"
This reverts commit cc90dcf556.
2023-08-02 10:28:50 -04:00
Sławomir Lach
cc90dcf556 Made possible to select flatpaks to install (fill list of netinstall) 2023-08-01 08:30:05 -04:00
Sławomir Lach
d77215c227 - Made installing of flatpaks possible 2023-08-01 08:28:48 -04:00
Ivan Borzenkov
8ca841d08e refactor after review - use QStringList 2023-07-08 19:19:38 +03:00
Ivan Borzenkov
2d0940e555 fix non ascii keyboard 2023-07-08 18:41:05 +03:00
dalto8
11e1659cad Merge pull request #2163 from Ficelloo/calamares
Fixing partutils.cpp
2023-07-06 20:23:04 +00:00
Ficelloo
39e2b527eb Update PartUtils.cpp 2023-07-06 21:05:51 +02:00
Ficelloo
cb7258249d Fixing partutils.cpp 2023-07-06 19:16:37 +02:00
Adriaan de Groot
e7161443d6 partition: simplify Arm code
- introduce a helper function for accessing the globalstorage value
- add consts and calculate the initial gap in a single expression
2023-06-25 22:21:01 +02:00
Adriaan de Groot
baf580f0ac partition: apply layout 2023-06-25 22:15:56 +02:00
Adriaan de Groot
25de501eb8 CI: adjust astyle configuration to match current option names 2023-06-25 22:15:21 +02:00
Adriaan de Groot
e78f8840ea Merge branch 'calamares' of github.com:calamares/calamares into calamares 2023-06-25 22:05:28 +02:00
Adriaan de Groot
f00fa429bf Merge pull request #2142 from Rippanda12/armInstall
partition: Add armInstall
2023-06-25 22:05:10 +02:00
abalfoort
48fd148b8a Handle show warning in function 2023-06-25 10:53:19 +02:00
abalfoort
240f18e5bd Show/hide "Boot partition not encrypted" warning 2023-06-23 15:56:02 +02:00
demmm
1cec7912de Merge pull request #2160 from zencatalyst/patch-1
Update README.md
2023-06-23 11:07:16 +02:00
Kasra Hashemi
197cbec82c Update README.md
Fixed punctuation and grammar issues plus spelling inconsistencies
2023-06-22 14:47:29 +03:30
dalto8
f1e4bcd8e5 Merge pull request #2146 from abalfoort/luksbootkeyfile
Create key file for LUKS2 devices
2023-06-13 11:51:57 +00:00
ABalfoort
20b4cefedb Merge branch 'calamares:calamares' into luksbootkeyfile 2023-06-13 08:49:54 +02:00
abalfoort
33aeabd617 Implement requested changes 2023-05-31 18:25:16 +02:00
abalfoort
1963dd3412 Optional luks2Hash with enum 2023-05-31 18:23:00 +02:00
abalfoort
c4496ef86b Add configurable variable m_luks2Hash 2023-05-31 14:43:39 +02:00
abalfoort
1e2a51f952 Remove NO_CONFIG 2023-05-31 14:42:39 +02:00
abalfoort
06d6f217b5 Added luksbootkeyfile.conf/yaml 2023-05-31 14:42:18 +02:00
dalto8
63c3f68619 Merge pull request #2141 from Rippanda12/calamares
Initcipiocfg fix for non x86 cpus
2023-05-27 13:24:11 +00:00
Philip Müller
ca2e36b3f3 Update services-systemd.conf
- reflect that file endings are now needed in the example
2023-05-26 13:15:19 +02:00
dalto8
2f6eb272c1 Merge pull request #2139 from Sunderland93/new_desktops
Add River and Hyprland to desktop list
2023-05-24 11:56:53 +00:00
abalfoort
e01b45f008 Check nr used slots 2023-05-23 17:18:10 +02:00
abalfoort
def9bf18d3 Revert removing check on root with unencrypted boot 2023-05-23 15:07:54 +02:00
abalfoort
5c4557e4d1 Create key file for LUKS2 devices 2023-05-23 13:47:39 +02:00
Kevin Kofler
9a88e0ab10 Merge pull request #2144 from evan-goode/evan-goode/f39
[packages] Call dnf-3 binary, not dnf
2023-05-22 23:10:16 +02:00
Evan Goode
7a67840c9b [packages] Call dnf-3 binary, not dnf
DNF is being replaced by a new package manager, DNF 5, in Fedora 39+.
The `dnf` binary will soon symlink to DNF 5 instead of DNF 5. The old
DNF 4 binary will still be (and always has been) available as
/usr/bin/dnf-3.

Until Calamares adds support for DNF 5, it should explicitly call the
old dnf-3 binary.
2023-05-22 12:03:22 -04:00
Panda
d662fb084d Add armInstall 2023-05-21 07:02:22 +00:00
Panda
b2c75a1af8 Fix initcpio
ARM cpus dont have vendor tag in /proc/cpuinfo
2023-05-20 09:11:47 +03:00
Sunderland93
4bf1b0fa7e Add River and Hyprland to desktop list 2023-05-17 16:25:57 +04:00
Adriaan de Groot
f385c94729 [libcalamaresui] Document 'we do not translate this' for developer-tooltip 2023-04-25 11:17:11 +02:00
Adriaan de Groot
6eff07eff2 i18n: no need to translate useless 'Form' text on UI pages 2023-04-25 11:14:55 +02:00
Adriaan de Groot
29ef9e909d i18n: update source language 2023-04-24 23:49:46 +02:00
Adriaan de Groot
5f51d84887 i18n: support BSD sed in the txpush script 2023-04-24 23:49:23 +02:00
Adriaan de Groot
9dfd83ab7c i18n: update to newer transifex client 2023-04-24 23:37:33 +02:00
Adriaan de Groot
69d771ae77 docs: Update Transifex links 2023-04-24 23:32:35 +02:00
Adriaan de Groot
9c2cbf7588 [libcalamares] Repair link to Translations 2023-04-24 23:32:24 +02:00
Adriaan de Groot
25b9e23330 i18n: update Transifex configuration
Use the new (go-based, APIv3) Transifex cli tool.
2023-04-24 22:43:06 +02:00
Adriaan de Groot
b07f0c2857 Changes: add credit for %p
While here, add a disambiguation to help translators.
2023-04-23 11:35:48 +02:00
Adriaan de Groot
3ceee01713 CI: bail out when Transifex script fails 2023-04-22 13:51:49 +02:00
Adriaan de Groot
6a236f7695 Merge pull request #2115 from ptr1337/cmake-O3
cmake: Change Release build from -O4 to -O3
2023-04-22 13:35:28 +02:00
Adriaan de Groot
61cc9c9791 Merge pull request #2125 from bitigchi/patch-1
Add i18n support for percent value
2023-04-22 13:35:04 +02:00
Emir SARI
2d118c7057 Add i18n support for percent value 2023-04-18 04:21:08 +03:00
Peter Jung
81c87dc5ac cmake: Change Release build from -O4 to -O3
Signed-off-by: Peter Jung <admin@ptr1337.dev>
2023-03-22 19:49:30 +01:00
Adriaan de Groot
4f2ab856a3 Changes: credit for PRs merged into calamares branch 2023-03-21 12:05:14 +01:00
Adriaan de Groot
74d30afad6 CMake: respect LDFLAGS from environment during build
Merge pull request #2113 from hamarituc/ldflags
2023-03-21 11:46:58 +01:00
Mario Haustein
4844534d7d respect LDFLAGS from environment during build 2023-03-18 21:15:31 +01:00
dalto
d35e69c8a9 [mount] Warn on failure to activate swap partition 2023-03-11 10:16:20 -06:00
dalto8
9a75b68ed8 Merge pull request #2109 from Sunderland93/greetd_environment_fix
greetd: Change environments entry from desktopFile to desktopExecutable
2023-03-10 23:26:26 +00:00
dalto8
70d4512635 Merge pull request #2103 from dalto8/zfsenhance
[partition] Add support for zfs encryption
2023-03-10 23:25:49 +00:00
dalto
da295e00f9 [displaymanager] Fix bug in lightdm preferred greeter implementation 2023-03-05 19:37:33 -06:00
dalto
079f608700 [displaymanager] Fix bug with find_preferred_greeters() 2023-03-05 13:58:13 -06:00
Sunderland93
3a0cb8d1fd change environments entry from desktopFile to desktopExecutable 2023-03-05 10:40:17 +04:00
dalto
f5b974984c [partition] Remove WITH_KPMCORE42 to fix luks2 support 2023-03-03 19:05:06 -06:00
dalto
ce6f498358 [mount] Post-merge cleanup of swap enablement 2023-02-28 18:35:18 -06:00
dalto8
8e1bd367c4 Merge pull request #2102 from phoepsilonix/calamares
During installation, if a swap partition exists, enable swap.
2023-03-01 00:18:25 +00:00
Masato TOYOSHIMA
c296f67356 Update main.py 2023-02-26 07:48:51 +09:00
Masato TOYOSHIMA
5513ffcd1c Update main.py 2023-02-26 07:24:12 +09:00
Masato TOYOSHIMA
0038751106 UAdded automatic enabling of swap partition before installation starts.
Mainly to suppress installer stoppages caused by oom killer.
2023-02-26 07:17:40 +09:00
Masato TOYOSHIMA
719c6f2ff1 Merge branch 'calamares:calamares' into calamares 2023-02-26 02:00:48 +09:00
Masato Toyoshima
6c25be670d Added automatic enabling of swap partition before installation starts.
Mainly to suppress installer stoppages caused by oom killer.
2023-02-26 02:00:12 +09:00
dalto8
ce9250acb5 Merge pull request #2101 from calamares/paolodongilli-calamares
Enable preferred-greeters with lightdm
2023-02-24 22:45:15 +00:00
Adriaan de Groot
92a208104b [displaymanager] lightdm: default to no-preferred-greeter
While here, drop nonsensical alternatives: if it's not a
.desktop file, it's not going to work anyway.
2023-02-24 21:10:20 +01:00
Adriaan de Groot
59fd4ee082 [displaymanager] lightdm: logging errors
Don't just use *any* file found in the xgreeters directory,
and log when no greeter was found (outside of the translated
error message).
2023-02-24 21:09:48 +01:00
Adriaan de Groot
bbc9d90888 [displaymanager] Allow configuring the preferred-greeter-list 2023-02-24 21:09:48 +01:00
Adriaan de Groot
d448be1077 [displaymanager] Handle preferred / deterministic greeter 2023-02-24 21:09:48 +01:00
Adriaan de Groot
48f61be73a [displaymanager] Factor out the find-a-greeter part 2023-02-24 21:09:48 +01:00
Paolo Dongilli
8ca6b56f56 Add detection of default lightdm-greeter 2023-02-24 21:09:48 +01:00
dalto
b7af2dd77d [partition] Add a config option for allowing zfs encryption 2023-02-23 17:17:37 -06:00
dalto8
1855e4f61e Merge pull request #2083 from dalto8/bootloader
Add refind, bootloader selection and general improvements
2023-02-23 23:04:59 +00:00
dalto
d88d2ce92e [partition] Make EncryptWidget::setFilesystem take a FileSystem::Type 2023-02-23 16:47:39 -06:00
dalto
2f8ef8fdf3 [partition] Fix crash caused by notification storm 2023-02-22 16:42:32 -06:00
dalto
d45819d552 [partition] Check minimum password length for zfs encryption 2023-02-21 18:56:04 -06:00
dalto
f156fc3562 [partition] Enable encryption for zfs with replace partition 2023-02-21 17:24:01 -06:00
dalto8
400dc6cbcc Merge pull request #2100 from dalto8/fixfsreplace
[partition] Fix issues with replace partition
2023-02-21 23:05:23 +00:00
Masato TOYOSHIMA
9050566bdb Merge branch 'calamares:calamares' into calamares 2023-02-21 21:02:13 +09:00
dalto
cea2b1e8d8 [partition] Enable zfs encryption for erase disk 2023-02-18 16:15:59 -06:00
dalto
ba33908f9f Merge branch 'calamares' into fixfsreplace 2023-02-18 15:40:46 -06:00
dalto
c54ce69e67 [partition] Fix merge error 2023-02-18 15:36:35 -06:00
dalto
ab51a2ea03 Merge branch 'calamares' into fixfsreplace 2023-02-18 15:20:51 -06:00
dalto8
ad0656953e Merge pull request #2070 from calamares/fixup-partition
Replace luks-is-a-string by an enum
2023-02-18 21:18:07 +00:00
dalto8
35e7474284 Merge branch 'calamares' into fixup-partition 2023-02-18 21:17:13 +00:00
dalto
a1c9dedc37 [partition] Make replace partition call setDefaultFsType() so the FS is updated 2023-02-18 09:43:03 -06:00
dalto
8080adbce2 [partition] Fix issues with replace partition 2023-02-17 15:33:37 -06:00
dalto8
35cc54a6b9 Merge pull request #2087 from dalto8/encrypt-options
[partition] Restore encryption option to alongside and replace options
2023-02-17 21:08:55 +00:00
dalto8
e97d3134d6 Merge pull request #2092 from Sunderland93/calamares
gtkgreet: disable window decoration in Cage
2023-02-13 20:17:37 +00:00
Masato Toyoshima
77e1407c51 During installation, if a swap partition exists, enable swap.
If there is no swap at all when the partition of the installation destination device is mounted,
    if a Swap partition exists, enable swap.
2023-02-14 04:30:24 +09:00
demmm
79d796a437 Merge pull request #2091 from calamares/issue-2090
Allow overriding greetd user/group
2023-02-14 04:30:04 +09:00
Aleksey Samoilov
cc2a458bce Merge pull request #1 from calamares/calamares
Sync
2023-02-13 19:16:48 +04:00
demmm
a5ae67f93c Merge pull request #2091 from calamares/issue-2090
Allow overriding greetd user/group
2023-02-13 11:00:11 +01:00
Sunderland93
81c316efd1 gtkgreet: disable window decoration in Cage 2023-02-06 17:12:21 +04:00
Adriaan de Groot
46a28543b9 [displaymanager] Add configuration items + schema for greetd user 2023-02-06 11:03:28 +01:00
Adriaan de Groot
f142710fee [displaymanager] Overwrite DM-instance settings with config-settings
If there are settings in the config-file, they can overwrite
settings in the DM-instance in code.
2023-02-06 10:52:25 +01:00
dalto8
f1f903ef9f [bootloader] Add refind to the comments for efiBootLoader 2023-02-05 16:28:05 +00:00
dalto8
d8a03bb34b Merge pull request #2069 from dalto8/grubcfg-alwaysdefault
[grubcfg] Fix bugs and add option to force defaults to update existing values
2023-01-22 16:47:10 +00:00
dalto
871651c0c1 [partition] Restore encryption option to alongside and replace partition options 2023-01-22 10:44:38 -06:00
dalto8
9647973983 Merge pull request #2086 from wiz64/calamares
Update license shields
2023-01-14 15:49:07 +00:00
wiz64
117e2fecf9 Update README.md 2023-01-14 21:17:10 +05:30
wiz64
a307d7d5c1 Update license shields 2023-01-13 21:11:42 +05:30
demmm
a8131c2be2 Merge pull request #2084 from wiz64/patch-1
Update actions shields.io image
2023-01-02 18:27:33 +01:00
wiz64
bf77a94721 Update actions shields.io image 2023-01-02 19:19:57 +05:30
dalto8
5670c459ca Merge pull request #2081 from ptr1337/initcpiokms
Add "kms" hook to initcpiocfg
2022-12-27 17:57:54 +00:00
Peter Jung
672cbc3d1a Use kms hook after autodetect
Signed-off-by: Peter Jung <admin@ptr1337.dev>
2022-12-23 11:47:19 +01:00
dalto
a3518e88d3 [bootloader] Add refind, bootloader selection and general improvements 2022-12-22 17:13:43 -06:00
Peter Jung
56fafb8769 Add "kms" hook to initcpiocfg
The "kms" hook got added with commit¹ to the default hooks array. Follow the archlinux defaults and add it also.

1. b99eb1c0d5

Signed-off-by: Peter Jung <admin@ptr1337.dev>
2022-12-18 14:22:10 +01:00
Adriaan de Groot
40b7274c85 CMake: copy settings.conf into the build directory
Having an up-to-date settings.conf in the build directory
makes `calamares -d` in that directory much more predicatable.

This should not have used CMake command `install()`.

FIXES #2075
CLOSEs #2079
2022-12-18 01:18:33 +01:00
Adriaan de Groot
61ce22338a Merge branch 'issue-1911' into calamares 2022-12-18 01:09:51 +01:00
Adriaan de Groot
93a24b65a9 [partition] (unrelated) switch types *again* to avoid compile warning 2022-12-18 01:02:08 +01:00
Adriaan de Groot
b022555198 [partition] Assign the replace-mode FS when reading the configuration 2022-12-18 00:58:44 +01:00
dalto
2ea11d4d63 [grubcfg] Minor update from PR feedback 2022-11-05 16:52:50 -05:00
dalto
152895b48c [grubcfg] Add newline to config 2022-11-05 16:50:05 -05:00
Adriaan de Groot
bca38907e6 [partition] Remove unused widget
The ReplaceWidget was mentioned only in comments,
also unused in 3.2 series.
2022-11-05 22:36:51 +01:00
Adriaan de Groot
8b29acfc59 [partition] Convert ReplaceWidget to use enum
Add a tag-class parameter, to demonstrate that the
ReplaceWidget class is never used.
2022-11-05 22:28:53 +01:00
Adriaan de Groot
8c8f2a14b6 [partition] Use config object in ChoicePage 2022-11-05 22:19:24 +01:00
Adriaan de Groot
859569e156 [partition] Convert layoutApply() 2022-11-05 22:13:30 +01:00
Adriaan de Groot
9c3f576cd2 [partition] Convert option struct to use the enum 2022-11-05 21:57:28 +01:00
dalto
a45f6a316e [grubcfg] Fix bugs and add option to force defaults to update existing values 2022-11-05 13:24:37 -05:00
Adriaan de Groot
bd3a1c5e2e [dracut] Avoid test failure
When the config file is all commented-out, then it's empty,
and that is not a valid configuration.
2022-11-05 16:58:00 +01:00
Adriaan de Groot
2ae02bedf8 [partition] Use enum values rather than strings
In the innermost APIs, use the enum value rather than
passing strings around.
2022-11-05 16:47:26 +01:00
Adriaan de Groot
5ef1af5aef [partition] Introduce helpers for Cala Luks generation to KPM generations 2022-11-05 16:28:54 +01:00
Adriaan de Groot
8f72d2541f No more INSTALL_CONFIG 2022-11-05 15:46:39 +01:00
Adriaan de Groot
5c95bc49af Merge pull request #2064 from dalto8/umountemergency
[umount] Change default config for emergency to true
2022-10-30 21:40:07 +01:00
dalto8
1ee2a2a364 Merge pull request #2057 from dalto8/dracutimagename
[dracut] Change image name terminology to match dracut
2022-10-22 17:48:44 +00:00
dalto
a4afddc4e1 [umount] Change default config for emergency to true 2022-10-22 08:23:55 -05:00
demmm
6fd1c90f23 Merge pull request #2058 from dalto8/doublesubvol
[mount] Remove duplicate subvol option
2022-10-18 20:38:56 +02:00
dalto8
7a00a68ab4 Merge pull request #2059 from calamares/hostid
Add zfshostid module
2022-10-18 05:57:00 -05:00
dalto
d13561e1c7 [dracut] Clean up error handling more 2022-10-16 09:08:42 -05:00
dalto
336a57fdf4 [dracut] Clean up error handling 2022-10-16 09:05:30 -05:00
demmm
26a9ca7a86 [zfshostid] simplify run call
required for schema.yaml seems to be for globalstorage entries, not modules
remove section
2022-10-16 14:12:27 +02:00
demmm
cbb01f70e7 Changes: add new parts for 3.3.0-aplha3 2022-10-16 13:41:54 +02:00
demmm
089d3086cc [zfshostid] adding new module
module created to copy zfs generated /etc/hostid, needed to have
hostid in zpool & initramfs in sync
2022-10-16 13:35:09 +02:00
demmm
1b96832bf7 [zfs] adding hostid
using ZFS in combination with dracut exposed a bug on system updates hostid from the Live session does not match hostid installed, thus zpool id no longer matches id created by dracut in the kernel img
to work around this, the zfs module now uses zgenhostid to create a hostid
2022-10-16 12:22:45 +02:00
dalto
5a10c58c35 [mount] Remove duplicate subvol option 2022-10-15 17:31:50 -05:00
dalto
596113c80f [dracut] Change image name terminology to match dracut 2022-10-15 07:06:26 -05:00
Adriaan de Groot
703cbb7bf3 [partition] Allow 'luks' as alias of 'luks1' 2022-10-10 21:12:28 +02:00
Adriaan de Groot
f31056faae [partition] Tidy formatting of enum tables
- the NamedEnumTable is one of the things that clang-format doesn't
  do nicely.
2022-10-10 21:09:24 +02:00
Adriaan de Groot
db20b79ac0 Changes: credits for 3.3 work 2022-10-10 21:03:50 +02:00
Adriaan de Groot
3344bf9439 Merge pull request #2052 from shivanandvp/calamares
[netinstall] "Noncheckable" option for netinstall package groups
2022-10-09 16:50:13 +02:00
Adriaan de Groot
2b7cc8088d Merge pull request #2047 from jtheoof/luks2-support
[partition] Add support for LUKS2
2022-10-09 16:48:52 +02:00
dalto8
831cfb57b4 Merge pull request #2051 from CachyOS/calamares
fix initcpiocfg filesystems loop
2022-09-25 12:06:24 +00:00
shivanandvp
f2ba0929d7 feat: "Noncheckable" option for netinstall package groups
The "Noncheckable" option, when true prevents a user from checking the whole group. This does not affect whether any child subgroups or packages can be selected or not

No breaking changes
2022-09-24 21:01:38 -05:00
Peter Jung
5c87452b67 fix initcpiocfg filesystems loop
Signed-off-by: Peter Jung <admin@ptr1337.dev>
2022-09-24 13:46:44 +02:00
Adriaan de Groot
f75b599e2a Merge pull request #2049 from killajoe/patch-1
Update services-systemd.conf
2022-09-22 16:29:49 +02:00
Johannes Kamprad
b00a2ede79 Update services-systemd.conf
removing mandatory: false from example for cups-socket as it is default same as for the other two (could confuse about may disable needs to set it? )
2022-09-18 14:43:15 +02:00
Jeremy Attali
9def0cb66f [partition] Add support for LUKS2
This commit adds support for LUKS2 behind a new `partition.conf` key:
`luksGeneration`.

A bit of context, LUKS2 is the default encryption operating mode since
cryptsetup >= 2.1.0 (See [Arch
wiki](https://wiki.archlinux.org/title/dm-crypt/Device_encryption#Encryption_options_with_dm-crypt).
It is considered more secured and allows additional extensions. It also
comes with Argon2id as the default Password Based Key Derivation
Function (`--pbkdf` option). So it's important to provide this as an
option for Calamares in order to make Linux installs more secure, for
those who wish to encrypt their system.

This commit was tested on a custom Manjaro installer with:

- grub bootloader with the [argon patches](https://aur.archlinux.org/packages/grub-improved-luks2-git).
- [rEFInd](https://wiki.archlinux.org/title/REFInd) bootloader with
  unencrypted `/boot` partition because rEFInd [doesn't support booting
  from an encrypted volume](https://sourceforge.net/p/refind/discussion/general/thread/400418ac/)

**Important consideration for distribution maintainers**:

- You need to have compile flag `WITH_KPMCORE4API` on
- If you are shipping with grub by default please note that you need to
  ship it with the Argon patches. Example on Arch Linux: [grub-improved-luks2-git](https://aur.archlinux.org/packages/grub-improved-luks2-git)
- If `luksGeneration` is not found in partition.conf, it will default to
  luks1
- Please test this on your own distribution as this was only tested on
  Manjaro installer (see above).
2022-09-09 20:41:12 -04:00
Jeremy Attali
ddf65a2437 [partition] Apply format
This part was not formated properly. Fixed using clang-format
2022-09-09 20:31:57 -04:00
Adriaan de Groot
4ced8279c6 Changes: document new bits for 3.3.0-a3 2022-09-09 22:10:07 +02:00
Adriaan de Groot
625693ac50 CMake: bump dependency versions 2022-09-09 22:09:56 +02:00
Adriaan de Groot
1821eb1b39 [libcalamaresui] Branding uses $-substitution
Replace @{name} with ${name} to be consistent with the rest
of the replacement-code in Calamares.
2022-09-09 22:04:49 +02:00
Adriaan de Groot
d1664f3502 [services-systemd] Correct Python key-checking
`has_key()` is a Python2-era form; use the `in` operator insteda.
2022-09-09 09:56:58 +02:00
Adriaan de Groot
6235e04ded Merge pull request #2046 from calamares/dracut_conf
[dracut] add option to make the kernel name configurable
2022-09-08 23:14:15 +02:00
demmm
9191748d82 Changes: updates for 3.3.0-alpha3 2022-09-03 16:22:00 +02:00
demmm
26166e8f51 [dracut] add asked for schema.yaml
corrected if statement
2022-09-03 14:36:45 +02:00
Adriaan de Groot
f9f4c6f36e Merge pull request #2045 from demmm/calamares
[localeq] move to using Drawer for fine tuning options
2022-09-03 01:34:49 +02:00
demmm
f16da0fde7 [dracut] add option to make the kernel name configurable 2022-09-02 21:53:42 +02:00
demmm
abdfeaa96c [localeq] move to using Drawer for fine tuning options
i18n.qml no longer needed
add color setting options to localeq.qml
Offline.qml updated to be inline with keyboardq UI, set index number according to default
America/New York
2022-08-26 15:43:47 +02:00
demmm
7e737977cb [keyboardq] add missing image license 2022-08-25 12:05:07 +02:00
Adriaan de Groot
a741663b20 SPDX: remove license information for removed module-translations 2022-08-25 00:26:31 +02:00
Adriaan de Groot
c0672d11c6 SPDX: license information for the locales-test-data 2022-08-25 00:25:45 +02:00
Adriaan de Groot
842b0925fe Merge pull request #2044 from demmm/calamares
[keyboardq] Move to using a Drawer
2022-08-25 00:19:42 +02:00
Adriaan de Groot
90d159a868 Changes: post-release housekeeping 2022-08-24 23:39:24 +02:00
Adriaan de Groot
130d26ce0a Changes: close off the 3.2 changelog in the development branch 2022-08-24 23:35:19 +02:00
Adriaan de Groot
bef731b9b9 Changes: post-release housekeeping
Note that in 3.2 branch, the version in CMakeLists now changes just before
the next release, not in post-release housekeeping. That is because
the CALAMARES_VERSION_RC remains 0 (release mode), by convention.

(cherry picked from commit aa09664601)
2022-08-24 23:32:47 +02:00
Adriaan de Groot
b0bd6245fa Changes: pre-release housekeeping
(cherry picked from commit c8eec51c5a)
2022-08-24 23:32:47 +02:00
Adriaan de Groot
54e19af0c5 Changes: document 3.2.61 work so far
(cherry picked from commit f2121197ff)
2022-08-24 23:32:47 +02:00
Adriaan de Groot
0e9cf861f4 CI: fix getting-the-version in release script 2022-08-24 00:34:11 +02:00
demmm
7876cdc71a [keyboardq] Move to using a Drawer
no longer use a ComboBox or stack view
if accepted, other QML models using a ComboBox will move to Drawer too
2022-08-23 18:56:49 +02:00
Adriaan de Groot
065647154e [displaymanager] Skip greetd test if there's no toml
toml is needed for greetd, but that shouldn't stop the tests
from running.
2022-08-23 16:04:24 +02:00
Adriaan de Groot
6558cd5150 CMake: add .so-version
This is basically PR #2002, from Undef-a.
2022-08-23 15:45:20 +02:00
Adriaan de Groot
c939fbce96 Changes: pre-release housekeeping 2022-08-23 15:17:55 +02:00
Adriaan de Groot
c34ee74d08 CI: update base for ABI compatibility 2022-08-23 14:08:50 +02:00
Adriaan de Groot
66cc1a74ec CMake: apply gersemi to libcalamares
Since this CMakeLists.txt writes out a C program, the formatting
is a bit weird; just start the written TU with a blank line to
make gersemi happy and keep the C-code aligned.
2022-08-23 12:23:13 +02:00
Adriaan de Groot
8de565f269 CMake: apply gersemi formatting 2022-08-23 12:22:09 +02:00
Adriaan de Groot
c3f366ce9e CI: check translations against detached branches
To avoid git complaining about duplicate worktrees, detach
the temporary trees. To avoid python modules translations
changing order (depending on how find traverses the tree),
sort the filenames before extraction.
2022-08-23 12:09:04 +02:00
Adriaan de Groot
7a262362df Merge branch 'issue-2008a' into calamares
This fixes all the **tests** of locale-detection. Now we can
test for user interaction.
2022-08-23 02:07:33 +02:00
Adriaan de Groot
9a4d992778 [locale] Repair tests
- Esperanto now doesn't quite self-match because it has no country
- sr prefers RS as country over ME
2022-08-23 02:06:06 +02:00
Adriaan de Groot
fb3112b75d [locale] Repair tests
- prefers language default country (ca_ES over ca_AD)
- prefers non-empty country match
2022-08-23 02:02:54 +02:00
Adriaan de Groot
3540121449 [locale] Prefer non-empty country matches
Prefer "en_US" over "en" even when asking for "en".
2022-08-23 02:02:24 +02:00
Adriaan de Groot
a422fd80d9 [locale] Refactor matching some more
- find the best score and match relative to a specific
  set of parts; make it easy to update the country-setting
- look for a complete match, or best match, with three
  country settings
2022-08-23 00:46:40 +02:00
Adriaan de Groot
6cbf2d7e32 [locale] Factor out the guess-language part 2022-08-23 00:03:04 +02:00
Adriaan de Groot
40527ffd4e [locale] Be more chatty while matching locales 2022-08-22 23:48:21 +02:00
Adriaan de Groot
eb242168bf [locale] Log what we matched with (for language) 2022-08-14 21:45:45 +02:00
Adriaan de Groot
cfb8ef9f65 [locale] Use locale-similarity for searching 2022-08-14 17:16:31 +02:00
Adriaan de Groot
a988298a65 [localeq] Needs more shared sources from locale 2022-08-14 17:16:12 +02:00
Adriaan de Groot
78e216fedb [locale] Introduce a similarity-score for locales 2022-08-14 16:26:46 +02:00
Adriaan de Groot
115f493676 [bootloader] Repair Python 3.6 compatibility
Argument *text* is an addition in 3.7, while the Calamares 3.3
branch supports Python 3.6 and later. Use the 'backwards compatibility'
name of the parameter, *universal_newlines*.

Cherry-picked from 33961ff6f (in the 3.2 branch, though, Python 3.3
is supported).
2022-08-07 14:44:31 +02:00
demmm
e9f011b686 Merge pull request #2032 from codesardine/calamares
add HDPI support, fix #1945
2022-07-29 21:02:54 +02:00
Vitor Lopes
8c873e0f49 add HDPI support 2022-07-29 18:03:44 +01:00
Adriaan de Groot
af045ab8b2 [calamares] Restore translations of About and Debug buttons
Fixes #2030
2022-07-29 10:14:00 +02:00
demmm
42386c520d [calamares] fix for https://github.com/calamares/calamares/issues/2030
adjust CalamaresWindow.cpp so About & Debug buttons pick needd translation for widget sidebar
2022-07-28 17:50:05 +02:00
Adriaan de Groot
fd56b5bdc4 [locale] Approach matching from a different angle
- add struct that splits a locale name into parts
- add tests that the splitting and joining works
2022-07-26 22:10:46 +02:00
Adriaan de Groot
be54cd24de [partition] Factor out visibility of encryption widget
- Put this in a method of its own even though it's used
  only once, so we can put a good name on it.
- If there are no FS choices (e.g. the sample settings file)
  then there is no combo-box, and the check was crashing.

FIXES #2029
2022-07-26 17:33:39 +02:00
Adriaan de Groot
ba96f7ddc2 CMake: build libcalamares with an internal name for KPMcore 2022-07-23 23:48:21 +02:00
Adriaan de Groot
8a43ed99ed CMake: provide calamares::kpmcore only when kpmcore was found
This works around older CMakes that refuse to set arbitrary
properties on a target. Instead, use calamares::kpmcore
as the specific indicator that kpmcore was found.

Breaks build of libcalamares, since that needs **something**
regardless of whether KPMcore was found.
2022-07-23 23:45:32 +02:00
Adriaan de Groot
84c0da2186 [locale] Test KDE neon and FreeBSD separately, same data
- wrangle the test framework so it hands the same data to
  two different collections of tests; do KDE neon and FreeBSD
  separately so it's clearer which lookups are being done
  (and a failure in one doesn't prevent the test of the other).
2022-07-19 18:56:50 +02:00
Adriaan de Groot
d52d1bfeee [locale] Add FreeBSD test data for locale-mapping 2022-07-19 18:48:32 +02:00
Adriaan de Groot
73628b13ea [locale] Add test for language-mapping
Adds specific data from KDE neon and expected mappings.
The test fails right now because the mapping is incorrect.
2022-07-19 18:19:19 +02:00
Adriaan de Groot
8cefb59efb [packagechooser] Repair namespace-changed build error
FIXES #2021
2022-07-19 12:00:05 +02:00
Adriaan de Groot
908928b41c CMake: repair broken logic around finding KPMcore
- the alias libraries calapmcore and calamares::kpmcore
  are always created; if there is no KPMcore, they handle
  definitions to signal that.
- upstream kpmcore target is the one we should be testing
  to see if KPMcore itself is there (or, use KPMcore_FOUND).
2022-07-19 11:54:26 +02:00
Adriaan de Groot
97cbebc0f7 [libcalamares] Move KPMcore-dependencies
- FileSystem.h depends on KPMcore and only compiles when
  KPMcore is present; it can use KPMcore identifiers.
- Global.h doesn't.
- Move the few functions introduced into Global.h that need
  KPMcore, to FileSystem.h instead.
2022-07-19 11:46:57 +02:00
Adriaan de Groot
04e93f513c [libcalamares] Always use the calamares::kpmcore library
When KPMcore is present, the calamares::kpmcore wraps that
and provides suitable API detection. If KPMcore is not
present, the same interface library provides -DWITHOUT_KPMcore.
2022-07-19 11:41:01 +02:00
Adriaan de Groot
eef3bb19d3 Merge pull request #2011 from calamares/improve-kpmcore
Fix kpmcore detection and compilation on Debian-11
2022-07-18 23:23:32 +02:00
Adriaan de Groot
64eed3a40c CI: remove nonsense CMake flags 2022-07-18 23:17:08 +02:00
Adriaan de Groot
10da2c257d Merge pull request #2009 from calamares/issue-1940
[libcalamares] Remove translation-languages define
2022-07-18 23:03:22 +02:00
Adriaan de Groot
c49d520d3d Merge pull request #2020 from dalto8/zfsfix3
[partition] Fix encryption being shown when not available
2022-07-17 23:08:26 +02:00
Adriaan de Groot
650bddae63 Merge pull request #2007 from calamares/issue-1438
Use `${}` everywhere instead of `@@`
2022-07-17 23:01:25 +02:00
dalto
250678627a [partition] Apply format 2022-07-17 14:53:11 -05:00
dalto
56e37d0abb [partition] Fix encryption being shown when not available 2022-07-17 14:16:42 -05:00
Adriaan de Groot
bb0a2d3bd4 Changes: stray space in the 3.2 changelog 2022-07-14 10:15:28 +02:00
Adriaan de Groot
eccfdbd986 [libcalamares] Mark a TODO that is causing build failures 2022-07-10 13:38:48 +02:00
Adriaan de Groot
3360ad612e [libcalamares] Use Calamares interface-library to kpmcore 2022-07-10 13:38:48 +02:00
Adriaan de Groot
fb620464d7 CMake: create an alias for KPMcore that fixes its interface
- kpmcore (when used as target "kpmcore") has an interface
  include directory that does not contain the "kpmcore/"
  subdirectory. But the headers it has installed, assume it
  is there (e.g. kpmcore internals use #include <fs/filesystem.h>).
- add an alias at Calamares level that sticks in some more
  includes, adds the relevant WITHOUT_kpmcore when it's
  not there, etc.
2022-07-10 13:38:48 +02:00
Adriaan de Groot
ab813b607f CMake: move kpmcore support into the helper-CMake-module
- find the dependencies just once
- fix the interface for kpmcore so it can find its own
  includes (this is mostly relevant for Debian)
2022-07-10 13:38:48 +02:00
Adriaan de Groot
0e6d70c395 [services-systemd] Ungroup systemd units 2022-07-10 12:52:40 +02:00
shivanandvp
27c187084b fix: Check for name key based on comments on PR 2022-07-06 20:01:50 -05:00
shivanandvp
781ced1a59 feat: feat: Ungroup systemd units in services-systemd module 2022-07-05 23:08:43 -05:00
Adriaan de Groot
8f3ac6e00b Merge pull request #2010 from calamares/accept-esperanto
Remove special case for Esperanto
2022-07-03 12:34:53 +02:00
Adriaan de Groot
24652abe8a CI: another stab at PR notifications 2022-07-03 00:28:38 +02:00
Adriaan de Groot
6e950cf49c CI: update translation-fetching to remove Esperanto special case 2022-07-03 00:15:56 +02:00
Adriaan de Groot
4935da8fe4 CMake: support Esperanto
Since the minimum Qt version is 5.15.0, we always have a version
that can support Esperanto in QLocale, so drop the checks.
2022-07-03 00:14:35 +02:00
Adriaan de Groot
170a5a8697 [libcalamares] Factor out the list of translations
The list of translation codes lives in one place, make it accessible
through a function in Calamares::Locale.
2022-07-03 00:05:40 +02:00
Adriaan de Groot
18a3092aa1 [libcalamares] Use namespace Calamares
The distinction CalamaresUtils and Calamares is old-fashioned,
since we can use nested namespaces (and already do) for a lot
of things; make libcalamares/locale/ a bit more consistent
by using namespace Calamares::Locale for everything.
2022-07-02 23:19:44 +02:00
Adriaan de Groot
d7e35d2ad2 [libcalamares] Use newly-generated table of language names 2022-07-02 23:19:44 +02:00
Adriaan de Groot
f53f83be56 CMake: create header with available languages 2022-07-02 23:19:44 +02:00
Adriaan de Groot
42f4cdd40c CMake: remove redundant comments (they're at top-level too) 2022-07-02 22:37:52 +02:00
Adriaan de Groot
f5891e1c8c CI: try to get useful notification from pull request change 2022-07-02 22:33:22 +02:00
Adriaan de Groot
2322f12b59 [libcalamares] Remove translation-languages define
This doesn't compile, since it doesn't provide any replacement
for the translations define.
2022-07-02 17:42:02 +02:00
Adriaan de Groot
c03850a302 CI: notify on pull-requests 2022-07-02 17:19:11 +02:00
Adriaan de Groot
66002f375c [bootloader] Don't use @@ replacements
SEE #1438
2022-07-02 16:49:19 +02:00
Adriaan de Groot
3d901637d1 [preservefiles] Use ${} expansion instead of @@
SEE #1438
2022-07-02 16:49:05 +02:00
Adriaan de Groot
a7b3ccf198 [oemid] Use consistent ${} substitution
SEE #1438
2022-07-02 16:08:48 +02:00
Adriaan de Groot
f8a845d996 [users] Use DictionaryExpander instead of raw KMacroExpander 2022-07-02 15:56:59 +02:00
Adriaan de Groot
273941f451 [libcalamares] Add convenience for building macro-expanders 2022-07-02 15:56:21 +02:00
demmm
010ab08384 Merge pull request #2004 from demmm/calamares
[webview] remove broken & unused module
2022-07-01 18:39:37 +02:00
demmm
2d9d65f33c [webview] remove broken & unused module
adjust settings.conf to replace webview example & entries
this fixes https://github.com/calamares/calamares/issues/2003
2022-07-01 18:00:21 +02:00
Adriaan de Groot
b4c23b8b70 [users] In tests, adjust failure expectations
Some distro's let the user change the hostname at will;
others don't, and yet others don't have systemd to change
the hostname with at all. Check if we **can** change the
hostname (as a non-root user), before setting expectations.
2022-06-28 23:50:56 +02:00
Adriaan de Groot
6a9d9700d4 [grubcfg] Avoid crashes in tests
- remove "bogus" key when it's not needed
- check for existence of "branding" key in GS before
  subscripting it (this happens in tests, where no
  GS contents are loaded, but not in regular use,
  where startup loads the branding data into GS)
2022-06-28 23:41:17 +02:00
Adriaan de Groot
0688c7f4e7 CMake: target kpmcore doesn't exist elsewhere, so check was failing
Consumers of calapmcode couldn't tell if KPMcore was found.
Pass it around as a property of calapmcore, rather than
anything else.

FIXES #2026
2022-06-28 00:12:33 +02:00
Adriaan de Groot
f42f2514cb CMake: simplify the KPMcore helper 2022-07-21 13:19:19 +02:00
Adriaan de Groot
09ed07b0c8 [luksopenswaphookcfg] Merge pull request #2025 from demmm/calamares
Duplicate key ends up in the configuration file.

FIXES #1659
2022-07-21 01:08:51 +02:00
demmm
f30d568f10 [luksopenswaphookcfg] fix for https://github.com/calamares/calamares/issues/1659 2022-07-20 20:22:04 +02:00
Adriaan de Groot
0c79418393 Changes: mention the -alpha1 release 2022-06-27 23:54:12 +02:00
Adriaan de Groot
b0f86d9fb6 Changes: DBus activation was a mistake, now reverted 2022-06-27 23:53:04 +02:00
Adriaan de Groot
3b08ace966 Changes: mention more module-config changes 2022-06-27 23:52:13 +02:00
Adriaan de Groot
ee848e2367 [libcalamares] About box should show extended version if available 2022-06-27 23:48:03 +02:00
Adriaan de Groot
9d593a2a90 [services-systemd] Repair schema
No # in IDs (see *netinstall* schema for explanation).
2022-06-27 23:19:26 +02:00
Adriaan de Groot
208e7736e6 [welcome] Repair example config file
Needs quotes for boolean values that are really names.
2022-06-27 23:19:07 +02:00
Adriaan de Groot
bb05deca33 [netinstall] Repair schema IDs
The schema is considered invalid by **some** versions of
configvalidator (or rather, the underlying jsonschema):

```
128: '#definitions/groups' does not match '^[^#]*#?$'
128:
128: Failed validating 'pattern' in metaschema['properties']['definitions']['additionalProperties']['$dynamicRef']['allOf'][0]['properties']['$id']:
128:     {'$comment': 'Non-empty fragments not allowed.',
128:      '$ref': '#/$defs/uriReferenceString',
128:      'pattern': '^[^#]*#?$'}
```

Remove the `#` from the IDs.
2022-06-27 23:12:31 +02:00
Adriaan de Groot
cdbc7fffca [mount] Repair test-config files against schema
- can't use *bogus* as a key unless that's allowed by
  the schema -- and it is not.
- can't supply empty config if there is supposed to be
  an object there.

This makes it a little difficult to allow a config-file
that is actually no-configuration-at-all (or only-defaults).
Put in values for *btrfsSwapSubvol* since it isn't a fragile
setting.
2022-06-27 23:04:12 +02:00
Adriaan de Groot
d797aea311 [grubcfg] Repair typo in schema key 2022-06-27 23:00:13 +02:00
Adriaan de Groot
873d5e3522 [fstab] Remove schema-entry for mountOptions
These were removed from the module in commit
	03f2e45605
but later restored by a botched merge.
2022-06-27 22:57:14 +02:00
Adriaan de Groot
ef4980448a [bootloader] Repair schema file
Looks like clang-format was applied to this JSON schema
file in 5a14c3c76f, which is
completely borked. Restore from earlier revision, now
with just `machineid` removed.
2022-06-27 22:50:37 +02:00
Adriaan de Groot
1c7c0b9af8 CI: apply coding style (clang-format 13) 2022-06-27 00:37:15 +02:00
Adriaan de Groot
5a14c3c76f [bootloader] Fix schema file for config
A stray "machineid" was added, without a type definition,
so the config file -- which doesn't mention machineid at all
-- was considered invalid. Drop it because the key isn't mentioned
anywhere else.
2022-06-27 00:36:20 +02:00
Adriaan de Groot
c826e8e78a CI: replace 'prepare' step with a script in the Calamares repo
This applies to the Debian nightly builds; having to go through
external actions doubles the effort to debug these kinds of
scripts, so just slap the actual commands into the workflow.
This also makes it easier to migrate to a different hosting.
2022-06-26 23:53:36 +02:00
Adriaan de Groot
96fb97d53a Changes: pre-release housekeeping
- this would be the first 3.3 release, scripts still needed
  cleanup to handle all the changes in 3.3
- support "-alpha1" kinds of designation
- support more versioning information in the headers
2022-06-26 23:49:14 +02:00
Adriaan de Groot
20d96f9ea3 [libcalamaresui] More constness 2022-06-26 23:24:32 +02:00
Adriaan de Groot
36df20eb0e Merge branch 're-import-kdsag' into calamares
FIXES #1997
2022-06-26 23:10:16 +02:00
Adriaan de Groot
86d3932a16 [calamares] Hook up to KDSAG again (instead of DBus activation) 2022-06-26 23:06:31 +02:00
Adriaan de Groot
784f591dee 3rdparty: build only the part of KDSAG we need 2022-06-26 22:03:06 +02:00
Adriaan de Groot
e80764a01e 3rdparty: import KDSingleApplication
This was removed (in favor of DBus activation) but DBus activation
does not work; re-import the latest version, now under the MIT
license. Pull in only src/ and the license file, though.

https://github.com/KDAB/KDSingleApplication
9dc8b2f61638aa1c4dbf49d38f8b97178974409f
2022-06-26 21:59:53 +02:00
Adriaan de Groot
3b9aa272f7 Desktop: mark as single-main-window
Desktop environments that understand this (relatively new)
.desktop key won't offer multi-window-related functionality.
2022-06-26 21:53:24 +02:00
demmm
1d1aff5622 Merge pull request #1996 from Sunderland93/calamares
greetd: remove autologin copied from the Live ISO
2022-06-22 14:18:14 +02:00
Sunderland93
464a9ac503 greetd: fix typo in gtkgreet path 2022-06-22 11:52:14 +04:00
Sunderland93
136ec3df58 greetd: remove autologin copied from the Live ISO (fixes #1995) 2022-06-22 11:49:21 +04:00
Adriaan de Groot
d9b4562076 Style: remove trailing ; after namespace 2022-06-20 21:48:22 +02:00
Adriaan de Groot
3a0b75a006 Merge branch '3.2.x-stable' into calamares 2022-06-19 16:05:17 +02:00
Adriaan de Groot
6dbf9de06e Changes: post-release housekeeping 2022-06-19 16:01:34 +02:00
Adriaan de Groot
795256cba5 Changes: release-related housekeeping 2022-06-19 16:00:41 +02:00
Adriaan de Groot
b11ee3abc5 [libcalamares] Add alternatives ca@valencia and ca_ES@valencia 2022-06-19 15:34:20 +02:00
Adriaan de Groot
82b19a6314 [locale] Fix up handling of regional variants, country-specifics
- expand tests to include Serbian variants
- massage detection code to do better filtering based on
  country-selection (so "American English" doesn't later
  pick "English" with Antigua and Barbados for locale)
2022-06-19 15:25:23 +02:00
Adriaan de Groot
18626901d3 [locale] Improve regional variant lookup 2022-06-19 14:49:46 +02:00
Adriaan de Groot
40d8e1e0f6 [locale] Expand tests for matching-valencia locales 2022-06-19 14:39:12 +02:00
Adriaan de Groot
b8b7b10bfd [locale] Be more chatty when loading locales 2022-06-19 14:17:12 +02:00
Adriaan de Groot
ed5149c17f CI: on 3.2 branch, check for 3.2 branch 2022-06-19 12:43:12 +02:00
Adriaan de Groot
f4fb495488 CI: replace 'prepare' step with a script in the Calamares repo 2022-06-19 12:34:12 +02:00
Adriaan de Groot
b7dcf55d4c [locale] Add debug while mapping language+country 2022-06-19 11:51:38 +02:00
Adriaan de Groot
7f7e4aa1ae [locale] Expand tests to language-matching 2022-06-18 12:33:02 +02:00
Adriaan de Groot
79db04dc2e [locale] Defer to the locale-service idea of LANG
- Using QLocale().name() loses some special locales that
  Calamares understands but Qt does not (e.g. sr@latn, ca@valencia)
  so do it in two steps.
2022-06-18 11:48:50 +02:00
Adriaan de Groot
2478570deb [libcalamares, keyboard] Use convenience for getting current locale 2022-06-18 00:40:26 +02:00
Adriaan de Groot
d80661211c [libcalamares] Introduce convenience for reading Locale map 2022-06-18 00:23:21 +02:00
Adriaan de Groot
4420120b55 i18n: update language lists, welcome back Uzbek 2022-06-17 23:29:55 +02:00
Calamares CI
1f237cd373 i18n: [python] Automatic merge of Transifex translations 2022-06-17 22:20:17 +02:00
Calamares CI
214522f42a i18n: [calamares] Automatic merge of Transifex translations 2022-06-17 22:20:17 +02:00
demmm
0257c9d31e [welcomeq] set needed Text id 2022-06-15 19:52:27 +02:00
demmm
e4729b8dc3 [welcomeq] adjust Requirements.qml
starting with 217e4ab4f7
the messages have expanded, no longer fitting in the used ListView model
set the text blocks to expand with text size, add a scrollbar
reduce top spacing so underlying image won't show
set the full requirements listing as default
2022-06-15 18:26:35 +02:00
Calamares CI
5f55f14f9d i18n: [python] Automatic merge of Transifex translations 2022-06-14 13:32:17 +02:00
Calamares CI
0809dc65ec i18n: [calamares] Automatic merge of Transifex translations 2022-06-14 13:32:16 +02:00
Adriaan de Groot
2696bd5b44 CI: update action references to pull in the right packages for nightly build 2022-06-14 11:33:59 +02:00
dalto8
9cfbb4106b Merge pull request #1991 from demmm/calamares
[bootloader] bootLoader GS is always empty for EFI
2022-06-13 14:44:21 +00:00
demmm
8461571fbd [bootloader] bootLoader GS is always empty for EFI
with e15e57600e (diff-91818b0ce02fc61c3ff4b136101ee5f632a3a1febc46632dcd1dc4dc4ddc8594L801) the bootloader module will never run for EFI systems. Option to select to install or not install a bootloader is only visible on BIOS systems at this point.
Go back to only using bootLoader value for BIOS systems. This fixes https://github.com/calamares/calamares/issues/1990
2022-06-13 11:04:00 +02:00
Adriaan de Groot
700f2a6af3 [fstab] Warn when the mount options end up weird
Cherry-picked from 3.3, but only half of it applies.
2022-06-12 14:50:51 +02:00
Adriaan de Groot
2f3fb4a387 [fstab, mount] Warn when the mount options end up weird 2022-06-11 00:30:32 +02:00
Adriaan de Groot
57d978b82d Merge pull request #1977 from calamares/issue-1974
[welcome] Show welcome-image when all requirements are satisfied
2022-06-11 00:17:01 +02:00
Adriaan de Groot
7ccd7aa4e5 i18n: fix plurals in English while waiting for requirements-checker 2022-06-10 01:33:57 +02:00
Adriaan de Groot
42f9f07a07 [libcalamares] The spinner doesn't support rich text 2022-06-10 01:27:37 +02:00
Adriaan de Groot
9f91b50553 [libcalamares] Use Q_EMIT instead of 'emit' 2022-06-10 01:04:43 +02:00
Adriaan de Groot
f8dd3ea133 [welcome] Extend schema to allow the debugging checks 2022-06-10 01:00:40 +02:00
Adriaan de Groot
0fd0e9a1af [welcome] Add debugging checks slow-false and slow-true 2022-06-10 01:00:27 +02:00
Adriaan de Groot
26751f2acd [welcome] After creating ResultsListWidget, update it to current model state 2022-06-10 00:52:45 +02:00
Adriaan de Groot
849b831ca4 Merge pull request #1986 from ptr1337/initcpio_fix
fix initcpio issue from 3.3 merge
2022-06-09 09:18:04 +02:00
Adriaan de Groot
4d10629acf Merge pull request #1979 from abalfoort/issue-1963
FIXES #1963 : label encrypted partitions
2022-06-09 09:17:22 +02:00
Peter Jung
341fecd3ff fix initcpio issue from 3.3 merge
Signed-off-by: Peter Jung <admin@ptr1337.dev>
2022-06-09 04:00:18 +02:00
dalto8
056a5c29cb Merge pull request #1981 from monetaryabyss/issue-1980
[fstab] Remove ssd_extra_mount_options from fstab module.
2022-06-08 19:35:19 +00:00
demmm
a20ab6f0c6 [keyboardq] missed keyboardq.qrc merge
fixes https://github.com/calamares/calamares/issues/1985
2022-06-08 20:26:09 +02:00
Dan Simmons
70b83f5ca6 [fstab] Remove ssd_extra_mount_options from fstab module.
This looks to be a remnant from moving this to the mount module
which left an undefined variable. The mount options are now part
of the globalstorage and consumed here as mount_options_list.

FIXES #1980
2022-06-07 22:40:13 -04:00
abalfoort
9ca763127d Fix issue 1963: label encrypted partitions 2022-06-07 17:20:56 +02:00
Adriaan de Groot
9fdae8c76f Merge pull request #1976 from calamares/fix-color-names
[libcalamaresui] Fix color names
2022-06-07 16:06:08 +02:00
Adriaan de Groot
8b44eef002 [calamares] Make naming consistent between 'special' buttons 2022-06-07 16:02:29 +02:00
Adriaan de Groot
e6960ceec1 [calamares] Restore text on debug- and about-buttons 2022-06-07 16:02:29 +02:00
Adriaan de Groot
0141e681df Merge pull request #1973 from calamares/issue-1967
[calamares] Improve "about" and "debug" buttons
2022-06-07 16:01:14 +02:00
Adriaan de Groot
f5c58c8065 CI: use latest checkout action, to help support PRs 2022-06-07 12:45:06 +02:00
Adriaan de Groot
3645f99259 CI: update branch names where push-CI happens 2022-06-07 12:33:02 +02:00
Adriaan de Groot
105159a285 CI: update openSUSE and Debian versions 2022-06-07 12:31:02 +02:00
Adriaan de Groot
f958a3c2f7 [welcome] Update the results-list when a round of checks completes
When the checks were done, the widget showing the countdown-timer
and results was not being informed, so it didn't update the
display of the countdown timer or hide the list of problems
(when there are none) so that the welcome image is shown.

FIXES #1974
2022-06-07 12:12:54 +02:00
Adriaan de Groot
d4a776e759 [libcalamaresui] Adjust description of countdown spinner 2022-06-07 11:55:03 +02:00
Adriaan de Groot
1ae79fe58c [calamares] Make naming consistent between 'special' buttons 2022-06-03 12:08:41 +02:00
Adriaan de Groot
687d44859f [calamares] Restore text on debug- and about-buttons 2022-06-03 12:08:09 +02:00
Adriaan de Groot
2c07463ac6 [libcalamaresui] Check for typo's in branding keys 2022-06-03 11:53:02 +02:00
Adriaan de Groot
7356961f52 [libcalamares] Use the enum names as keys
- this uses the Qt internals to map enum values to names, making
  the separate translation table unnecessary. Adjust default branding
  to use the new names.

This makes code (using enum identifiers) and configuration (using
string keys) consistent in naming.
2022-06-03 11:40:10 +02:00
Adriaan de Groot
e6d72cb23b [calamares] Correct enum-names in QML Sidebar
- previous commits did not fix up all the enum names; this means
  you get errors -- because Branding.SidebarTextSelect is not a known
  name in the enum Branding::StyleEntry -- and the colors are messed up.
2022-06-03 11:27:39 +02:00
Adriaan de Groot
dc699db5f5 [libcalamaresui] Document style-string mapping
- while here, the static array of names doesn't need to be
  a class member, it is entirely internal.
- document how names are mapped to branding keys.
2022-06-03 11:20:59 +02:00
Adriaan de Groot
c9be4c744f [partition] Use the chosen replace-filesystem type 2022-06-03 10:44:39 +02:00
Adriaan de Groot
916b87e62e [partition] (unrelated) remove compatibility code for older Qt 2022-06-02 18:36:26 +02:00
Adriaan de Groot
425901fb98 [partition] Fix up combo-box handling for replace-fs choice 2022-06-02 18:32:54 +02:00
Adriaan de Groot
3b55b65a34 [partition] Implement config-side of a replace-filesystem choice 2022-06-02 18:30:35 +02:00
Adriaan de Groot
b763087e11 [partition] Partial implementation of Config-side for storing replace-FS 2022-06-02 14:58:28 +02:00
Adriaan de Groot
e27c57f8a6 [partition] Add FS-choice box when replacing (re-use the erase-fs configuration) 2022-06-02 14:58:11 +02:00
Adriaan de Groot
821a62ffbb [libcalamares] Add missing <memory> for std::unique_ptr
SEE #1972
2022-06-02 14:38:44 +02:00
Adriaan de Groot
72240d0d59 Merge branch 'work-3.3' into calamares 2022-05-29 17:22:36 +02:00
Adriaan de Groot
13153df484 Changes: post-release housekeeping 2022-05-29 17:13:02 +02:00
Adriaan de Groot
fb910d7c41 [fstab] Fix schema for new tmpOptions settings 2022-05-29 17:04:24 +02:00
Adriaan de Groot
55f1df9563 [users] Just don't test restore-to-previous, too flaky 2022-05-29 17:00:37 +02:00
Adriaan de Groot
b2f1a28504 Changes: pre-release housekeeping (3) 2022-05-29 16:21:07 +02:00
Adriaan de Groot
aca48bc027 i18n: update english 2022-05-29 16:17:53 +02:00
Calamares CI
753ba765eb i18n: [python] Automatic merge of Transifex translations 2022-05-29 16:16:15 +02:00
Calamares CI
34d8d90688 i18n: [calamares] Automatic merge of Transifex translations 2022-05-29 16:16:14 +02:00
Adriaan de Groot
729c31dd7a Changes: document About-button
FIXES #1922
2022-05-29 16:14:34 +02:00
Adriaan de Groot
1b2d12b9a1 [calamares] Give QML-progress-panel an about-button 2022-05-29 16:12:10 +02:00
Adriaan de Groot
ce74d2fdfc [calamares] Fix QML progress highlights 2022-05-29 15:56:21 +02:00
Adriaan de Groot
d34f593562 [calamares] Migrate the about-dialog to the debug (meta) window manager
- DebugWindowManager already manages not-really-Calamares windows
  like the Debug window, add About-Dialog to its responsibilities.
- Make about() accessible to the QML progress panel.
2022-05-29 15:54:03 +02:00
Adriaan de Groot
00898b18d6 [welcomeq] Remove about-calamares button from default QML 2022-05-29 15:38:06 +02:00
Adriaan de Groot
84186babab [welcome] Remove the about-calamares button from the (widgets) UI 2022-05-29 15:34:19 +02:00
Adriaan de Groot
18363ca183 [welcome] Move about-calamares box to Calamares (main) 2022-05-29 15:31:25 +02:00
Adriaan de Groot
006c3f99e6 [calamares] Add 'about calamares' button alongside the debug-button 2022-05-29 15:22:02 +02:00
Adriaan de Groot
04121892cf Changes: pre-release housekeeping (2) 2022-05-29 14:00:22 +02:00
Adriaan de Groot
3e72635204 [libcalamares] Fix path-search for loading branding-translation
- log which path is actually being used
- there are two overloads for QTranslator::load(); the intention
  was to call `QTranslator::load(const QLocale&, ...)`, but the
  types of the arguments were wrong, leading to the other
  overload being called, and interpreting the locale-name
  (e.g. "nl") as a full filename.

Improve logging, call the "other" overload with the right parameters
and drop the not-needed ones.

FIXES #1961
2022-05-29 00:55:35 +02:00
Adriaan de Groot
7dc450edb4 Changes: update the AUTHORS list (probably still incomplete) 2022-05-29 00:28:49 +02:00
Adriaan de Groot
6e8d820737 [partition] Missing space 2022-05-28 13:43:45 +02:00
Adriaan de Groot
135fce77c1 i18n: update english 2022-05-27 12:39:58 +02:00
Adriaan de Groot
b5c5eecdbd Changes: pre-release housekeeping 2022-05-27 11:18:25 +02:00
Adriaan de Groot
af813ac95b [fstab] Don't import (unused) subprocess 2022-05-24 16:51:36 +02:00
Adriaan de Groot
bb395db9f4 Merge branch 'release-3.2.58.2' into calamares 2022-05-24 16:48:05 +02:00
Adriaan de Groot
ff7ceb2e2b [fstab] Replace two-step attribute-setting with one step 2022-05-24 15:56:34 +02:00
Adriaan de Groot
cada0f2547 Changes: pre-release housekeeping 2022-05-24 15:25:31 +02:00
Adriaan de Groot
f4e5e08aa8 [fstab] Be more careful in setting up btrfs swap
- do not use subprocess module in Python bits,
- do +C (no-CoW) after turning compression off
2022-05-24 15:18:50 +02:00
Adriaan de Groot
5526cdc03c Changes: credits for fstab improvements
FIXES #1958 (PR)
2022-05-24 13:30:26 +02:00
abalfoort
63ee982d36 [fstab] Configure tmp on tmpfs
Adds a new option / configuration keys to `fstab.conf` to
configure how /tmp is created. The example shows how /tmp
is made *tmpfs* on an SSD, or on not-SSD, is just-a-directory.

FIXES #1818
2022-05-24 13:26:07 +02:00
abalfoort
4e5078c950 [fstab] Fix unencrypted root check
There are more ways (than not having a keyfile) for the root
partition to be unencrypted. Check it based on the settings
in the partition data.
2022-05-24 13:25:28 +02:00
Adriaan de Groot
61c67f8c22 Changes: document LUKS fix
FIXES #1957 (PR)
2022-05-24 13:15:45 +02:00
abalfoort
badb1d4706 [luksbootkeyfile] Handle key-slots-are-full 2022-05-24 13:07:17 +02:00
Adriaan de Groot
dfffbc62bc Changes: credits for recent work
FIXES #1955 (PR)
2022-05-24 12:58:02 +02:00
Adriaan de Groot
fd53c090f4 [partition] Massage coding style
- some long-missing (unrelated to recent PR) braces
- remove some redundant comments
2022-05-24 12:58:02 +02:00
Adriaan de Groot
6de880c95d [partition] No need for temporary variable 2022-05-24 12:58:02 +02:00
Adriaan de Groot
de03a92a8f [partition] Move LUKS helpers code-documentation 2022-05-24 12:58:02 +02:00
abalfoort
2a7cbd2520 [partition] update LuksDevice to savePassphrase and enum 2022-05-24 12:58:02 +02:00
Adriaan de Groot
4edad4d8c4 Changes: post-release housekeeping 2022-05-24 12:58:02 +02:00
Adriaan de Groot
7e4fc3e4c7 [welcome] Use about-message from Config
- for QML, this is the easiest way to factor out the message
  (no convenient access to free functions, unless I bung the
  message into e.g. Branding where I don't think it fits
  very well).
2022-05-23 17:11:45 +02:00
Adriaan de Groot
f9f18e5d3b [welcome] Use welcome message from Config object 2022-05-23 17:00:56 +02:00
Adriaan de Groot
4a852facb3 [welcome] Use generated about string 2022-05-23 16:57:51 +02:00
Adriaan de Groot
09255a1d9c [libcalamares] Add a more extensible About message
- make the years easier to update without annoying translators
- make the maintainers extensible.
2022-05-23 16:45:23 +02:00
Adriaan de Groot
f8345a09a2 [netinstall] Add disambiguation to labels 2022-05-23 15:41:45 +02:00
Adriaan de Groot
2a42084af4 [partition, users] Fix merge artifacts 2022-05-18 15:16:30 +02:00
Adriaan de Groot
66682b3e84 Merge branch 'calamares' into work-3.3 2022-05-18 15:13:21 +02:00
Adriaan de Groot
0d3e5e1c26 CMake: find boost_python as well
On FreeBSD, at least, `find_package(Boost COMPONENTS python)`
doesn't work well, while `find_package(boost_python)` does the job.

Be somewhat more flexible: look for boost_python first, assuming
it pulls in the rest of the Boost bits it needs.
2022-05-10 11:16:24 +02:00
Adriaan de Groot
52e2c8c262 [libcalamares] Use stronger type, rather than comment 2022-05-10 00:30:35 +02:00
Adriaan de Groot
a9df841770 CMake: fix Python3-executable uses 2022-05-10 00:07:41 +02:00
Adriaan de Groot
7096ee760e [libcalamaresui] Remove unused image-transformation function 2022-05-10 00:07:41 +02:00
Adriaan de Groot
880c367d64 [libcalamaresui] Remove under-used function 2022-05-10 00:07:41 +02:00
Adriaan de Groot
704e250664 [libcalamaresui] Remove under-used function
- there was one consumer of this function, and it was over-engineered
  for what was needed (removing a list of widgets). Just drop it.
2022-05-10 00:07:41 +02:00
Adriaan de Groot
928b46f18e [libcalamaresui] Use namespace Calamares::Widgets 2022-05-10 00:07:41 +02:00
Adriaan de Groot
f42924a9ca CI: accept clang-format 12-14 2022-05-10 00:07:41 +02:00
Adriaan de Groot
9196f696ea [users] Ensure the basic forbidden-names are always forbidden by the constructor 2022-05-09 15:25:14 +02:00
Adriaan de Groot
824d706a20 [users] Fix tests
- in 3.3, the legacy values are ignored, so all the old-style
  tests behave as if nothing is set at all.
- Some tests used old-style settings, adapt to newer ones.
2022-05-09 15:24:43 +02:00
Adriaan de Groot
f4e9b3689d [users] Remove legacy settings 2022-05-09 15:06:21 +02:00
Adriaan de Groot
bbeba5c9ab Merge branch 'calamares' into work-3.3 2022-05-09 15:03:41 +02:00
Adriaan de Groot
0678957def Merge pull request #1946 from dalto8/mount-schema
[mount] Update schema to use arrays
2022-05-09 15:02:27 +02:00
dalto
85c67113b7 [mount] Update schema to use arrays 2022-05-09 06:50:33 -05:00
Adriaan de Groot
21aa608ce2 Merge branch 'calamares' into work-3.3 2022-05-05 23:35:53 +02:00
Adriaan de Groot
ed9155bfd8 CMake: fix reversed logic
RC (in the 3.2 branch) and RELEASE_MODE are inverted, logically,
but the change to the CMake check wasn't properly inverted.
This only matters if you try to build Calamares in the src-dir,
which is something I never do anyway.
2022-05-04 12:01:36 +02:00
Adriaan de Groot
4713f0be42 Merge branch 'calamares' into work-3.3 2022-05-04 11:59:46 +02:00
Adriaan de Groot
8407d39109 [welcome] Remove superfluous moc include (automoc handles this) 2022-05-04 11:39:58 +02:00
Adriaan de Groot
1f7b2a3d2d [libcalamares] Remove CommandList destructor
The destructor was just the default one, but declaring it
blocks the default copy constructor.
2022-05-04 11:38:42 +02:00
Adriaan de Groot
a7cf1b18ce [webview] reduce #defines 2022-05-04 11:31:25 +02:00
Adriaan de Groot
f26ff07046 [webview] Fix build
Some QPainter enum values were deprecated in 5.14, and since we
require 5.15 now, we hit some old code paths with now-deprecated
values; this only shows up when actually enforcing deprecations.
2022-05-04 11:25:05 +02:00
Adriaan de Groot
1c3817ad65 [welcome] Fix displayed (user-visible) copyright years 2022-05-04 00:54:01 +02:00
Adriaan de Groot
a7d3630e42 [libcalamaresui] Improve naming, resolve TODO 2022-05-04 00:51:50 +02:00
Adriaan de Groot
992d2d3be0 [displaymanager] kdm is no longer relevant 2022-05-04 00:24:43 +02:00
Adriaan de Groot
ee1232b10a Merge branch 'calamares' into work-3.3 2022-05-04 00:18:44 +02:00
Adriaan de Groot
f302bd8854 Merge branch 'calamares' into work-3.3 2022-04-27 10:44:42 +02:00
Adriaan de Groot
eefe65ad0e CMake: chase changed linking in libcalamares 2022-04-25 15:34:39 +02:00
Adriaan de Groot
d7459e2bfe CMake: modernize optional parts of libcalamares 2022-04-25 15:23:27 +02:00
Adriaan de Groot
53926b8bbe i18n: make language-updater more resilient 2022-04-25 15:00:52 +02:00
Adriaan de Groot
5e80dddc82 CMake: resolve another TODO
- update translations
- apply gersemi formatting
- move HOMEPAGE_URL
2022-04-25 14:53:26 +02:00
Adriaan de Groot
585d06494e CMake: fix linking with modern Python and Boost 2022-04-25 14:47:18 +02:00
Adriaan de Groot
62de4eb8bf CMake: use modern FindPython and FindBoost 2022-04-25 14:36:16 +02:00
Adriaan de Groot
ab0a33ceae Changes: credits for faux-merged PR 2022-04-25 14:01:02 +02:00
Adriaan de Groot
e15e57600e Merge branch 'pr-1632' into work-3.3
- merge in recent *calamares* branch

FIXES #1632 (PR from Anubhav)
FIXES #1886
FIXES #1456
FIXES #517
2022-04-25 13:50:42 +02:00
Adriaan de Groot
d02afa20b8 [partition] Factor out creating-bootloader-panel
- this makes createBootloaderComboBox obsolete, since that was
  an implementation detail for creating the panel.
- add the panel also when doing an alongside install.
- credits to Anubhav, whose PR started this code.
2022-04-25 12:17:10 +02:00
Adriaan de Groot
d70d1ebfcd [partition] Always offer a 'no bootloader' item
- this branch is importing parts of a PR from Anubhav, so add
  relevant SPDX tag as well.
2022-04-25 12:17:10 +02:00
Adriaan de Groot
eb5be9cd34 [bootloader] Allow skipping an EFI bootloader, too
- while here, remove C-style if()
2022-04-25 11:11:40 +02:00
Adriaan de Groot
a3bd0d8091 Docs: update GS key overviews 2022-04-22 12:46:19 +02:00
Adriaan de Groot
03f755d168 Merge branch 'calamares' into work-3.3 2022-04-22 11:17:59 +02:00
Adriaan de Groot
47016765b3 [welcome] Fill backgrounds of failed requirements 2022-04-20 17:04:24 +02:00
Adriaan de Groot
217e4ab4f7 [welcome] Start improving the tooltips for missing requirements 2022-04-20 16:36:18 +02:00
Adriaan de Groot
b129cb0786 [libcalamares] Match roles from model to Qt standard roles 2022-04-20 16:25:28 +02:00
Adriaan de Groot
e102e2630e [welcome] Rip out the "details" dialog for requirements
- The dialog gave very little extra information
- The text descriptions from the dialog are already available
  as tooltips in the existing list view.
2022-04-20 16:19:34 +02:00
Adriaan de Groot
7650795f48 [welcome] Give the result-display somre more space 2022-04-20 16:16:20 +02:00
Adriaan de Groot
e5036da084 [welcome] Draw an icon for requirement-status 2022-04-20 16:03:42 +02:00
Adriaan de Groot
07f4ec529b [libcalamares] Clean up requirements model API
- don't need friends
- made modify-the-model API public where it makes sense
- improve naming
2022-04-20 15:39:53 +02:00
Adriaan de Groot
0b2af86ec9 [welcome] Remove compensating-for-model-reset code
The model was emptied-and-refilled when re-checked, which
meant we needed to have some special handling when messages
changed to avoid re-creating widgets. Since we use a model
view now, we don't need the extra machinery.
2022-04-20 15:15:06 +02:00
Adriaan de Groot
8b917ace4d [welcome] Replace widgets in dialog with model+listview
While here, remove unused vars and functions, tidy code.
2022-04-20 15:09:54 +02:00
Adriaan de Groot
ab1c78ca23 [welcome] Allow delegate to pick the text role to display 2022-04-20 13:29:19 +02:00
Adriaan de Groot
3679bb45f0 [welcome] Give the countdown a tooltip 2022-04-20 13:16:10 +02:00
Adriaan de Groot
1101b0dc82 CMake: hand off RC-or-not to the version header again (for welcome-checks) 2022-04-20 13:12:02 +02:00
Adriaan de Groot
15b4660d3e [welcome] Rip out rest of ResultWidget
- this breaks the dialog showing details, but we'll switch
  that to the delegate as well.
2022-04-20 13:12:02 +02:00
Adriaan de Groot
e457d099d8 [welcome] Replace manual widgets-creation by a listview with model 2022-04-20 12:00:21 +02:00
Adriaan de Groot
7686b89cd6 [welcome] Very basic model delegate for results / requirements 2022-04-20 12:00:21 +02:00
Adriaan de Groot
e757639669 [calamares] A progresstree isn't a tree 2022-04-20 12:00:21 +02:00
Adriaan de Groot
7b22546b14 [calamares] Don't need a method for painting, reduce API 2022-04-20 12:00:21 +02:00
Adriaan de Groot
7db14cb5cf [libcalamaresui] Fix build for ::ceil 2022-04-20 12:00:21 +02:00
Adriaan de Groot
87ff7ae0da [libcalamaresui] Use Qt max, min, bound 2022-04-16 12:51:11 +02:00
Adriaan de Groot
58306de28a [libcalamaresui] Private static methods can be hidden 2022-04-16 12:48:12 +02:00
Adriaan de Groot
56c27c4255 [libcalamaresui] Warnings-- 2022-04-16 12:45:58 +02:00
Adriaan de Groot
9084d746af Git: add a blame-ignore file for large-scale reformatting 2022-04-16 12:42:29 +02:00
Adriaan de Groot
18fef8dfe5 [libcalamaresui] Apply coding style 2022-04-16 12:39:21 +02:00
Adriaan de Groot
7e5df42fc0 Merge branch 'issue-1924' into work-3.3
This is a rather clunky implementation of re-check requirements.

"Clunky" because the UI parts are re-created each time, rather
than fishing from a model of checked (or unchecked) requirements.
The Widgets parts should be updated to use a full model, rather
than the recreate-list-of-Widgets implementation they have now.

Unrelated changes pull in a bunch of improvements to the
waiting spinner widget.
2022-04-16 12:34:40 +02:00
Adriaan de Groot
e11a0ee448 [libcalamaresui] Use delegating-constructor, drop initialize() 2022-04-16 12:25:28 +02:00
Adriaan de Groot
18f8633dd9 [libcalamaresui] Also modern-style initialize center and disable flags
- All constructors explicitly initialize these, so there's no
  real change here.
2022-04-16 12:20:02 +02:00
Adriaan de Groot
497422e72c [libcalamaresui] Don't disable parent while waiting 2022-04-16 12:18:49 +02:00
Adriaan de Groot
78a8993f38 [libcalamaresui] Move to more modern-style initializations 2022-04-16 12:11:52 +02:00
Adriaan de Groot
1f7dd2fcd5 [libcalamaresui] Convenience API 2022-04-16 12:02:56 +02:00
Adriaan de Groot
2ccd59e90b [libcalamaresui] Move waitingspinnerwidget.* into calamaresui
Although this is 3rd-party code, it now diverges -- by merging the
stale PR from upstream, and from adding features of our own --
enough that we should not pretend that it is the original 3rdparty
code.

Chase a couple of include paths that called this from 3rdparty/
2022-04-16 11:59:31 +02:00
Adriaan de Groot
3bd610a838 [libcalamaresui] Port Countdown to spinner widget alone 2022-04-16 11:53:03 +02:00
Adriaan de Groot
5060a66d4e [locale] Remove unused include 2022-04-16 11:29:49 +02:00
Adriaan de Groot
3c5ac535f1 [libcalamaresui] The waiting spinner now supports text, no need for extra label 2022-04-16 11:28:10 +02:00
Adriaan de Groot
82d721f455 [libcalamaresui] Display countdown 2022-04-16 00:05:01 +02:00
Adriaan de Groot
bef6b2fffd [3rdparty] Introduce alignment flag for text 2022-04-16 00:04:32 +02:00
Adriaan de Groot
fac8662387 [3rdparty] Tidy up access and API dox 2022-04-15 23:08:58 +02:00
Adriaan de Groot
15dc47555a [3rdparty] Constness for waitingspinner
The accessors can be (should be!) const.
2022-04-15 22:05:37 +02:00
Adriaan de Groot
171a597355 [3rdparty] Add SPDX tags for setText() support
The setText() support was submitted upstream at
	https://github.com/snowwlex/QtWaitingSpinner/pull/14
by `huxingyi <huxingyi@msn.com>`, but not merged. The
commits from that PR were merged into Calamares' copy
of the waitingspinnerwidget files. Add relevant tags
(which aren't in the PR, but Calamares does chase SPDX)
2022-04-15 22:05:37 +02:00
huxingyi
022f04355a Change default text color to black. 2022-04-15 21:54:13 +02:00
huxingyi
9786614917 Add text support.
Implement the setText function. The text will be displayed under the spinner image.
2022-04-15 21:54:13 +02:00
Adriaan de Groot
e351b1dafa [libcalamaresui] Drop the countdown label 2022-04-15 12:50:18 +02:00
Adriaan de Groot
075185547a [welcome] Display a countdown while (re)checking requirements 2022-04-15 12:47:12 +02:00
Adriaan de Groot
514b728449 [libcalamaresui] Tweak widget display for countdown 2022-04-15 12:41:29 +02:00
Adriaan de Groot
9a3d9feb30 [libcalamaresui] Add a countdown widget for limited waiting. 2022-04-15 12:13:16 +02:00
Adriaan de Groot
fcb893cd12 [welcome] Avoid growing more spacers
Insert spacers only once; avoid crashing when all the requirements
are satisfied immediately.
2022-04-14 22:06:36 +02:00
Adriaan de Groot
e79f29dc0e [welcome] Update the explanation only when all the results are in. 2022-04-14 21:51:43 +02:00
Adriaan de Groot
11d7870d68 [welcome] Factor out check for a filled requirements-model 2022-04-14 21:48:55 +02:00
Adriaan de Groot
fc653adcc0 [welcome] Don't duplicate result widgets 2022-04-13 18:15:21 +02:00
Adriaan de Groot
ee925492d4 [welcome] Don't duplicate widgets 2022-04-13 17:12:25 +02:00
Adriaan de Groot
6348309936 [libcalamaresui] If requirements are not satisfied, recheck in 5 seconds 2022-04-13 17:09:43 +02:00
Adriaan de Groot
a9e098b0b4 [libcalamares] Allow resetting the requirements model
- When a requirements checker starts, it can reset the model
  to clear it of previous entries.
2022-04-13 17:08:17 +02:00
Adriaan de Groot
8f5c3fa302 [welcome] Improve messages a little for bogus-checks.
Follow the guidelines for checker-messages, even though these
should never be displayed to real users.
2022-04-13 16:51:21 +02:00
Adriaan de Groot
cbd4bd9bbe [welcome] Factor out is-this-check-required
While here, make it possible for the "screen" (screen-size) check
to be mandatory; there's no reason it shouldn't follow the same
logic as all the others (although denying users an install because
they have a VGA monitor seems a bit weak).
2022-04-13 16:47:54 +02:00
Adriaan de Groot
f4117881cd [welcome] Add some more development-only checks 2022-04-13 16:45:32 +02:00
Adriaan de Groot
f6b65b3b93 [shellprocess] CommandLine now quotes properly in variable expansion 2022-04-13 14:16:57 +02:00
Adriaan de Groot
bbea67ecb4 [libcalamares] Add an expand() to command lines and lists
- While this is primarily convenient for testing (e.g. checking
  that a command is expanded the way we expect), it simplifies
  some of the code because it's now clear that run() uses an
  expanded copy of the command-list to do the actual work.
2022-04-13 14:08:21 +02:00
Adriaan de Groot
d76dd2f8e0 [libcalamares] Use new expander in CommandList
- This switches @@ROOT@@ for ${ROOT} and uses standard macro-
  expansion mechanisms for the commands; undefined variables
  will be logged as well.
2022-04-12 16:06:42 +02:00
Adriaan de Groot
334b7fc219 SPDX: tag gersemi configuration 2022-04-12 15:30:35 +02:00
Adriaan de Groot
f923dedc3f [libcalamares] Add a word-expander
This is a variant on KMacroExpander, which allows for
reporting of errors after expansion.
2022-04-12 15:28:07 +02:00
Adriaan de Groot
576f244d2d *: Chase new namespace Calamares::String 2022-04-12 14:15:52 +02:00
Adriaan de Groot
d03a8acc9d [libcalamares] Create namespace Calamares::String
This is a step towards getting rid of CalamaresUtils and
using more structured namespaces overall, e.g. Calamares::String
for things related to string-handling.
2022-04-12 14:14:02 +02:00
Adriaan de Groot
2c0d9396e2 [users] Link to CoreAddons for KMacroExpander in config 2022-04-12 14:10:12 +02:00
Adriaan de Groot
bb278c7ba9 [shellprocess] Migrate towards 'standard' variable substitutions 2022-04-12 13:13:01 +02:00
Adriaan de Groot
3bf0a93b86 CMake: fix missed merge failure
- Don't format the language-lists with gersemi
2022-04-12 12:52:19 +02:00
Adriaan de Groot
82b5ca8bfc Merge branch 'calamares' into work-3.3 2022-04-12 12:44:39 +02:00
Adriaan de Groot
f64938cb3f [partition] Remove unnecessary methods
- _find and _each Doesn't need to be part of the class API
- Rename to *Transform() because that's more in-line with what it
  does, applying an operation to the tree.
2022-03-22 18:47:27 +01:00
Adriaan de Groot
9b0ef5fce5 [partition] Use unsigned sizes
Reduce warnings by using unsigned consistently; this fights
the KPMCore API (which uses signed sizes for, e.g. sectorSize)
a little, but states more clearly that a disk cannot have a
negative size.
2022-03-22 15:23:24 +01:00
Adriaan de Groot
8ce92d450c [partition] Warnings-- for int / double / size_t confusions 2022-03-22 15:23:24 +01:00
Adriaan de Groot
982f9c8458 [partition] Hide implementation function 2022-03-22 15:23:24 +01:00
Adriaan de Groot
f888cb87d1 [libcalamares] Start deprecating signed sizes 2022-03-22 15:23:24 +01:00
Adriaan de Groot
97031ea3e6 [libcalamares] The amount of memory in the system cannot be negative 2022-03-22 15:23:24 +01:00
Adriaan de Groot
a303efb174 [users] Warnings--
Remove unreachable code.
2022-03-22 13:12:23 +01:00
Adriaan de Groot
029bb3efdd [calamares] Warnings--
The widget name is used (by moc) to inform the name of the
member variable storing the widget; having a :: in the name
yields a member variable with __ in it. Two _ is reserverd
to the implementation.
2022-03-22 13:08:07 +01:00
Adriaan de Groot
4545470f2d Changes: document new bits 2022-03-22 12:57:46 +01:00
Adriaan de Groot
99b19b9539 [libcalamares] Always log to file, sometimes to terminal 2022-03-22 12:54:54 +01:00
Adriaan de Groot
aedb55ea36 [partition] Require modern KPMCore 2022-03-21 23:44:20 +01:00
Adriaan de Groot
49c56add7d Merge branch 'calamares' into work-3.3 2022-03-21 23:21:54 +01:00
Adriaan de Groot
827d06df85 Merge pull request #1895 from loongarch64/la64/dev-work-3.3
[bootloader] Add loongarch64 support for bootloader
2022-03-03 22:14:30 +01:00
Huang Jia Wen
107afcff27 Merge pull request #2 from loongarch64/dev-work-3.3
[bootloader] Add loongarch64 support for bootloader
2022-03-03 16:58:32 +08:00
Huang Jia Wen
1793c627cd [bootloader] Add loongarch64 support for bootloader 2022-03-03 14:11:32 +08:00
Adriaan de Groot
03291fb726 [partition] Don't set empty labels 2022-02-08 19:01:41 +01:00
Adriaan de Groot
0be88f1453 [partition] Use signed sizes 2022-02-08 16:42:31 +01:00
Adriaan de Groot
a59c45d869 [users] Rename macro to avoid reserved-to-the-implementation names 2022-02-08 16:35:50 +01:00
Adriaan de Groot
7f14aa6bf1 [libcalamares] Avoid warnings about KPMCore headers 2022-02-08 16:35:23 +01:00
Adriaan de Groot
c7cc599a19 [umount] Remove/mark unused parameters 2022-02-08 16:35:04 +01:00
Adriaan de Groot
3b55c2805a Changes: document formatting-tools 2022-02-08 16:21:43 +01:00
Adriaan de Groot
cf097850de CMake: apply gersemi styling 2022-02-08 16:18:47 +01:00
Adriaan de Groot
b167d8da03 [libcalamares,ui] Make KF5::CoreAddons explicit
- libcalamares doesn't need it anymore, because it ported away
  from KPluginLoader,
- libcalamaresui does need it, because of KMacroExpander.
2022-02-08 16:13:40 +01:00
Adriaan de Groot
e507a23795 Modules: make use of KF5::CoreAddons explicit 2022-02-08 16:12:25 +01:00
Adriaan de Groot
5160fdc26a [libcalamares] Port away from KPluginFactory 2022-02-08 15:50:17 +01:00
Adriaan de Groot
8f769006d6 Merge branch 'calamares' into work-3.3 2022-02-08 13:28:20 +01:00
Adriaan de Groot
d98027ad2f Merge pull request #1865 from dalto8/mount-mount
Changes to mount module for 3.3
2022-02-02 16:24:34 +01:00
Adriaan de Groot
2bf43ffbf2 [unpackfs] Fix test validation (and document what the test is for) 2022-02-02 16:19:51 +01:00
Adriaan de Groot
0c7f06137a CMake: validate all the test-configurations as well 2022-02-02 15:57:49 +01:00
Adriaan de Groot
a352bd946e [grubcfg] snake-case one configuration key
This makes all the keys in grubcfg consistently
snake-case (rather than one being a camel).
2022-02-02 15:02:58 +01:00
Adriaan de Groot
d1e4740e70 Merge branch 'calamares' into work-3.3 2022-02-02 14:41:58 +01:00
dalto
5b483ab26f [mount] Fix typo in mount.conf comments 2021-12-30 10:01:03 -06:00
dalto
3e1bc6cb22 [partition] Revert change to partition.conf 2021-12-30 09:36:54 -06:00
dalto
bb1d3022e0 [mount] Add additional documentation in mount.conf and main.py 2021-12-30 09:07:51 -06:00
dalto
a50ffa74e1 [mount,fstab] Fix bugs in moving mount options to the mount module 2021-12-30 09:07:51 -06:00
dalto
03f2e45605 [mount,fstab] Move mounting logic to the mount module 2021-12-30 09:07:51 -06:00
Adriaan de Groot
24a881ad75 Merge branch 'calamares' into work-3.3 2021-12-24 17:01:08 +01:00
Adriaan de Groot
e4a3b66024 CI: add abi-consistency-checking 2021-11-30 13:23:15 +01:00
Adriaan de Groot
1667d75a70 CMake: WITH_KF5Crash -> BUILD_KF5Crash
ABI-changing flags are WITH_*, features and dependencies are BUILD_*
2021-11-30 11:49:43 +01:00
Adriaan de Groot
ce23efae99 Merge branch 'calamares' into work-3.3 2021-11-30 11:39:30 +01:00
Adriaan de Groot
bd4bed1438 Merge branch 'calamares' into work-3.3 2021-11-09 15:31:37 +01:00
Adriaan de Groot
23f6b25cfc Merge branch 'calamares' into work-3.3 2021-10-30 15:02:53 +02:00
Adriaan de Groot
8e959105c6 Changes: avoid constant merge-conflicts by separating 3.2 and 3.3 2021-10-30 15:02:03 +02:00
Adriaan de Groot
dde55471ba Merge branch 'calamares' into work-3.3 2021-10-30 15:00:54 +02:00
Adriaan de Groot
97eea9bde2 Merge pull request #1645 from dalto8/non-EOS
[bootloader] kernel-install changes to bootloader module
2021-10-20 11:45:10 +02:00
dalto
b5f8e30093 Change additionalInitrdFiles to an array 2021-10-13 15:09:27 -05:00
dalto
9d9cd44617 Changes from review comments 2021-10-13 12:12:16 -05:00
dalto
c1f7a2c855 Fix issue with absolute paths 2021-10-13 12:12:16 -05:00
dalto
e0f40cb4a4 Remove EOS-specific changes 2021-10-13 12:12:16 -05:00
dalto
04e927e67f EndeavourOS customizations 2021-10-13 12:12:16 -05:00
Adriaan de Groot
605ad788d0 [partition] Fix build against Qt deprecations
setMargin() has been deprecated for a long time, and
Calamares has a utility function for it anyway.
2021-09-30 00:02:43 +02:00
Adriaan de Groot
bcde8b87b1 [partition] Remove unreachable break statements 2021-09-29 23:55:40 +02:00
Adriaan de Groot
cb3b2422a9 Changes: update requirements / dependencies documentation 2021-09-28 23:59:45 +02:00
Adriaan de Groot
60cc8696e3 Remove PythonQt support -- C++ bits 2021-09-28 23:56:52 +02:00
Adriaan de Groot
ca4dbabf70 Remove PythonQt support
Nothing beyond the example module was ever built with the
PythonQt bindings, as far as I can tell. They have been
deprecated, defaulting OFF for over two years now.

QML modules fill the gap with customizable, run-time
interpreted UI and stronger support from the C++ side
of Calamares.
2021-09-28 23:49:08 +02:00
Adriaan de Groot
c1e1e6c3a4 Merge branch 'calamares' into work-3.3 2021-09-28 23:37:38 +02:00
Adriaan de Groot
cf6c930df5 Merge remote-tracking branch 'origin/calamares' into work-3.3 2021-09-22 11:51:14 +02:00
Adriaan de Groot
e1df2a2450 Changes: document Python work and other deps-updates 2021-09-16 14:15:12 +02:00
Vitor Lopes
bd3f89fb57 [grubcfg] tidy code + pep8 2021-09-16 14:11:46 +02:00
Vitor Lopes
f9dc932f62 [initcpiocfg] fix english in human-visible string 2021-09-16 14:11:29 +02:00
Vitor Lopes
4b08aebe7f [initcpiocfg] Use F strings, python3.6 only 2021-09-16 14:11:29 +02:00
Vitor Lopes
1fe27effe5 [initcpiocfg] rework swap_uuid statement and filesystem hook 2021-09-16 14:11:21 +02:00
Vitor Lopes
453e760709 [initcpiocfg] use format instead of % 2021-09-16 14:11:11 +02:00
Vitor Lopes
0ad9242ab7 [initcpiocfg] mkinitcpio.conf might not understand single quotes 2021-09-16 14:11:01 +02:00
Vitor Lopes
5da736466c [initcpiocfg] rework is_intel_cpu 2021-09-16 14:10:56 +02:00
Vitor Lopes
df256b608a [initcpiocfg] code tidy up 2021-09-16 14:10:45 +02:00
Adriaan de Groot
1f5bdef96e CMake: bump Python requirements
- Python 3.6 for f-string support
- Boost 1.67 because it has consistent library naming and some CMake support
2021-09-16 13:50:51 +02:00
Adriaan de Groot
261c3587a5 [calamares] Use DBus activation instead of KDSAG 2021-09-16 13:48:56 +02:00
Adriaan de Groot
a6ba3dfce0 [license] Adjust to Qt 5.15 deprecations 2021-09-16 12:08:14 +02:00
Adriaan de Groot
1bd5628256 [libcalamaresui] Redundant call, not available in Qt 5.15 anyway 2021-09-16 12:04:50 +02:00
Adriaan de Groot
714605ebaa [libcalamaresui] Missing header, needed in Qt 5.15 2021-09-16 12:04:29 +02:00
Adriaan de Groot
5975ff9e42 CMake: drop NAME option from add_test
- drop the unused "NAME" option for calamares_add_test
- while here reformat the module with the CMake style tool
2021-09-16 11:52:01 +02:00
Adriaan de Groot
a27b72e893 CMake: introduce consistent CMake style
The tool "gersemi" [1] formats CMake code. It is an opinionated
and slightly simplistic "just work" formatter. Let's see how
it does on Calamares CMake code.

[1] https://github.com/BlankSpruce/gersemi
2021-09-16 11:52:01 +02:00
Adriaan de Groot
396746acc1 [libcalamares] Warnings-- for renamed enum value
Remove the before-Qt 5.15 ifdeffery and just keep the current
flags for NetworkManager.
2021-09-16 11:12:57 +02:00
Adriaan de Groot
adc3af0345 CMake: explicitly suppress old API 2021-09-16 11:11:27 +02:00
Adriaan de Groot
5a82c8123b CMake: require Qt 5.15 (the LTS, all current distro's have it) 2021-09-16 11:11:27 +02:00
Adriaan de Groot
8ab1a4fb30 CMake: require 3.16
This is just prep-work: from here, we can re-work FindBoost usage
and the FindPython things as well.
2021-09-16 11:09:24 +02:00
Adriaan de Groot
72701aae21 CMake: pick a build type (if none given explicitly) 2021-09-16 11:04:38 +02:00
Adriaan de Groot
419be4df25 3.3: start a new changelog 2021-09-16 11:01:30 +02:00
907 changed files with 205086 additions and 120505 deletions

View File

@@ -22,6 +22,7 @@ Cpp11BracedListStyle: "false"
FixNamespaceComments: "true"
IncludeBlocks: Preserve
IndentWidth: "4"
InsertBraces: "true"
MaxEmptyLinesToKeep: "2"
NamespaceIndentation: None
PointerAlignment: Left

10
.gersemirc Normal file
View 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

View File

@@ -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@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: "OPENED ${{ github.event.issue.html_url }} by ${{ github.actor }} ${{ github.event.issue.title }}"
- name: "notify: closed"
if: github.event.issue.state != 'open'
uses: calamares/actions/matrix-notify@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: "CLOSED ${{ github.event.issue.html_url }} by ${{ github.actor }} ${{ github.event.issue.title }}"
- name: "remove in-progress label"
if: github.event.issue.state != 'open'
run: |

View File

@@ -1,4 +1,4 @@
name: nightly-debian-10
name: nightly-debian-11
on:
schedule:
@@ -9,38 +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@v4
- name: "prepare git"
shell: bash
run: |
apt-get update
apt-get -y install git-core jq curl
- name: "prepare source"
uses: calamares/actions/generic-checkout@v4
uses: calamares/actions/generic-checkout@v5
- name: "install dependencies"
shell: bash
run: ./ci/deps-debian11.sh
- name: "build"
id: build
uses: calamares/actions/generic-build@v4
- name: "notify: ok"
if: ${{ success() && github.repository == 'calamares/calamares' }}
uses: calamares/actions/matrix-notify@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: |
OK ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
- name: "notify: fail"
if: ${{ failure() && github.repository == 'calamares/calamares' }}
uses: calamares/actions/matrix-notify@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: |
FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
shell: bash
run: ./ci/build.sh

View 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

View 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

View File

@@ -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,21 @@ jobs:
image: docker://kdeneon/plasma:user
options: --tmpfs /build:rw --user 0:0
steps:
- name: "prepare env"
uses: calamares/actions/prepare-neon@v4
- name: "prepare source"
uses: calamares/actions/generic-checkout@v4
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@v4
- name: "notify: ok"
if: ${{ success() && github.repository == 'calamares/calamares' }}
uses: calamares/actions/matrix-notify@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: |
OK ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
- name: "notify: fail"
if: ${{ failure() && github.repository == 'calamares/calamares' }}
uses: calamares/actions/matrix-notify@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: |
FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
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

View 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

View File

@@ -9,38 +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@v4
- name: "prepare git"
shell: bash
run: zypper --non-interactive in git-core jq curl
- name: "prepare source"
uses: calamares/actions/generic-checkout@v4
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@v4
- name: "notify: ok"
if: ${{ success() && github.repository == 'calamares/calamares' }}
uses: calamares/actions/matrix-notify@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: |
OK ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
- name: "notify: fail"
if: ${{ failure() && github.repository == 'calamares/calamares' }}
uses: calamares/actions/matrix-notify@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: |
FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.build.outputs.git-summary }}
shell: bash
run: ./ci/build.sh

View File

@@ -4,7 +4,6 @@ on:
push:
branches:
- calamares
- work-3.3
pull_request:
types:
- opened
@@ -18,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:
@@ -28,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@v4
- name: "prepare source"
uses: calamares/actions/generic-checkout@v4
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@v4
- name: "notify: ok"
if: ${{ success() && github.repository == 'calamares/calamares' }}
uses: calamares/actions/matrix-notify@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: |
OK ${{ github.workflow }} in ${{ github.repository }} by ${{ github.actor }} on ${{ github.event.ref }}
.. ${{ steps.build.outputs.git-summary }}
- name: "notify: fail"
if: ${{ failure() && github.repository == 'calamares/calamares' }}
uses: calamares/actions/matrix-notify@v4
with:
token: ${{ secrets.MATRIX_TOKEN }}
room: ${{ secrets.MATRIX_ROOM }}
message: |
FAIL ${{ github.workflow }} in ${{ github.repository }} by ${{ github.actor }} on ${{ github.event.ref }}
.. ${{ steps.build.outputs.git-summary }}
.. ${{ github.event.compare }}
shell: bash
run: ./ci/build.sh

View File

@@ -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

View File

@@ -2,23 +2,23 @@
# 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
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
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
type = PO
type = PO

View 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)

View 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.

View 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;

View 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

View 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

View 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);
}

View 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
View 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

View File

@@ -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!

View File

@@ -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 )

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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

View File

@@ -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
View 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
View 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
View 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
View 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
View 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.

View 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)

View 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

File diff suppressed because it is too large Load Diff

View 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)

View 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'."

View 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)

View 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 &registered_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)

File diff suppressed because it is too large Load Diff

View 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)

View 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)

View 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)

File diff suppressed because it is too large Load Diff

View 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)

View 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"

View 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."

View 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)

View 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)

View 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)

View 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)

View 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
View 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)

View 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

File diff suppressed because it is too large Load Diff

View 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)

View 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)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

447
3rdparty/pybind11/include/pybind11/stl.h vendored Normal file
View 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)

View 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)

View 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 &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 &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 &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)

View 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)

View File

@@ -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;
}

View File

@@ -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
View File

@@ -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.

View File

@@ -1,4 +1,3 @@
<!-- SPDX-FileCopyrightText: no
SPDX-License-Identifier: CC0-1.0
-->
@@ -8,6 +7,104 @@ 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

290
CHANGES-3.3 Normal file
View File

@@ -0,0 +1,290 @@
<!-- 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):
- Nobody yet!
## Core ##
- No changes of note.
## Modules ##
- No changes of note.
# 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 `@@`.

View File

@@ -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.58.1
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
@@ -77,7 +101,6 @@ option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON )
# - DEBUG_PARTITION_UNSAFE (see partition/CMakeLists.txt)
# - DEBUG_PARTITION_BAIL_OUT (see partition/CMakeLists.txt)
### USE_*
#
# By convention, when there are multiple modules that implement similar
@@ -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,7 +142,7 @@ 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
@@ -128,47 +150,69 @@ set( CALAMARES_DESCRIPTION_SUMMARY
# (sr@latin in particular) or location (ca@valencia) need special
# handling in libcalamares/locale/Translation.h .
#
# NOTE: move eo (Esperanto) to _ok once Qt can actually create a
# locale for it. (Qt 5.12.2 can, see Translation Status section).
# NOTE: move ie (Interlingue) to _ok once Qt supports it.
# NOTE: update these lines by running `txstats.py`, or for full automation
# `txstats.py -e`. See also
#
# Total 74 languages
set( _tx_complete az az_AZ ca es fi_FI he hi hr ja lt pt_BR pt_PT
sq sv uk zh_TW )
set( _tx_good as be ca@valencia cs_CZ da de fa fr fur it_IT ko ml
nl ru si sk tg tr_TR vi zh_CN )
set( _tx_ok ar ast bg bn el en_GB es_MX et eu gl hu id is mr nb oc
pl ro sl sr sr@latin th )
set( _tx_incomplete eo es_PR gu ie ja-Hira kk kn lo lv mk ne_NP
ta_IN te 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"
@@ -176,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
@@ -221,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 ( PYTHONLIBS_FOUND )
# TODO:3.3: Require Boost + CMake; sort out Boost::Python
# Since Boost provides CMake config files (starting with Boost 1.70.
# or so) the mess that is the Calamares find code picks the wrong
# bits. Suppress those CMake config files, as suggested by @jmrcpn
set(Boost_NO_BOOST_CMAKE ON)
include( BoostPython3 )
find_boost_python3( ${BOOSTPYTHON_VERSION} ${PYTHONLIBS_VERSION_STRING} CALAMARES_BOOST_PYTHON3_FOUND )
set_package_properties(
Boost PROPERTIES
PURPOSE "Boost.Python is used for Python job modules."
)
# TODO:3.3: Remove PythonQt support
find_package( PythonQt )
set_package_properties( PythonQt PROPERTIES
DESCRIPTION "A Python embedding solution for Qt applications."
URL "http://pythonqt.sourceforge.net"
PURPOSE "PythonQt is used for Python view modules."
)
if(NOT Python_Development_FOUND)
message(STATUS "Disabling Python modules")
set(WITH_PYTHON OFF)
set(WITH_PYBIND11 OFF)
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 )
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
)
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
#
@@ -462,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(
@@ -488,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(
@@ -603,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:"
@@ -682,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)

View File

@@ -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()

View File

@@ -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/

View File

@@ -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})

View File

@@ -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

View File

@@ -104,10 +104,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]" )
@@ -210,16 +209,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 )

View File

@@ -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()

View File

@@ -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()

View File

@@ -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} )

View File

@@ -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()

View File

@@ -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()

View File

@@ -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.
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org)
* [![Chat on IRC](https://img.shields.io/badge/IRC-Libera.Chat%20%23calamares-green)](https://kiwiirc.com/client/irc.libera.chat/#calamares)
## General Guidelines
@@ -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)

View File

@@ -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@)

View File

@@ -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!

View File

@@ -7,26 +7,26 @@
[![Current issue](https://img.shields.io/badge/issue-in_progress-FE9B48)](https://github.com/calamares/calamares/labels/hacking%3A%20in-progress)
[![GitHub release](https://img.shields.io/github/release/calamares/calamares.svg)](https://github.com/calamares/calamares/releases)
[![GitHub Build Status](https://img.shields.io/github/workflow/status/calamares/calamares/ci?label=GH%20build)](https://github.com/calamares/calamares/actions?query=workflow%3Aci)
[![GitHub license](https://img.shields.io/github/license/calamares/calamares.svg)](https://github.com/calamares/calamares/blob/calamares/LICENSES/GPL-3.0-or-later.txt)
[![GitHub Build Status](https://img.shields.io/github/actions/workflow/status/calamares/calamares/push.yml)](https://github.com/calamares/calamares/actions?query=workflow%3Aci)
[![GitHub license](https://img.shields.io/badge/license-Multiple-green)](https://github.com/calamares/calamares/tree/calamares/LICENSES)
| [Report a Bug](https://github.com/calamares/calamares/issues/new) | [Translate](https://www.transifex.com/projects/p/calamares/) | [Contribute](CONTRIBUTING.md) | [Matrix: #calamares:kde.org](https://webchat.kde.org/#/room/%23calamares:kde.org) | [IRC: Libera.Chat #calamares](https://kiwiirc.com/client/irc.libera.chat/#calamares) | [Wiki](https://github.com/calamares/calamares/wiki) |
|:--:|:--:|:--:|:--:|:--:|:--:|
| [Report a Bug](https://github.com/calamares/calamares/issues/new) | [Translate](https://app.transifex.com/calamares/calamares/) | [Contribute](CONTRIBUTING.md) | [Chat on Matrix: #calamares:kde.org](https://webchat.kde.org/#/room/%23calamares:kde.org) | [Wiki](https://github.com/calamares/calamares/wiki) |
|:--:|:--:|:--:|:--:|:--:|
> Calamares is a distribution-independent system installer, with an advanced partitioning
> 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.
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org) (needs a Matrix account)
* [![Chat on IRC](https://img.shields.io/badge/IRC-Libera.Chat%20%23calamares-green)](https://kiwiirc.com/client/irc.libera.chat/#calamares) (IRC supports guest accounts)

View File

@@ -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

View File

@@ -86,6 +86,16 @@ KEY_ID="328D742D8807A435"
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
#
#
@@ -124,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,

74
ci/abicheck.sh Executable file
View 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

View File

@@ -9,7 +9,7 @@ indent=spaces=4
# Brackets
style=break
add-brackets
add-braces
# Spaces
pad-paren-in

20
ci/build.sh Executable file
View 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 "::"

View File

@@ -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.
@@ -21,10 +20,8 @@ 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" || { echo "! No .clang-format support files in $TOPDIR" ; exit 1 ; }
AS=$( which astyle )
# Allow specifying CF_VERSIONS outside already
CF_VERSIONS="$CF_VERSIONS clang-format13 clang-format-13 clang-format-13.0.1 clang-format12 clang-format-12 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,27 +29,30 @@ 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 12 handles lambdas nicely, so use that.
# Version 13 is also ok.
# 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
12|13 )
15|16|17 )
:
;;
* )
echo "! Clang-format version '$format_version' unsupported, versions 12 or 13 are ok."
echo "! Clang-format version '$format_version' unsupported, versions 15-17 are ok."
exit 1
;;
esac
@@ -72,7 +72,6 @@ done
style_some()
{
if test -n "$*" ; then
$AS --options=$BASEDIR/astylerc --quiet "$@"
$CF -i -style=file "$@"
fi
}

View File

@@ -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
View 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

11
ci/deps-endeavouros.sh Executable file
View File

@@ -0,0 +1,11 @@
#! /bin/sh
#
# Install dependencies for building on EndeavourOS
#
# There is no docker image for EndeavoudOS, and the live ISO
# for Cassini Nova is KF5 / Qt5 based, but we can build there.
# It even has most of the build-deps already installed.
pacman -Syu --noconfirm git cmake ninja jq
pacman -S --noconfirm gcc yaml-cpp icu
pacman -S --noconfigm extra-cmake-modules

17
ci/deps-fedora-qt6.sh Executable file
View File

@@ -0,0 +1,17 @@
#! /bin/sh
#
# Install dependencies for the nightly-fedora-qt6 build
#
yum install -y bison flex git make cmake gcc-c++ ninja-build
yum install -y yaml-cpp-devel libpwquality-devel parted-devel python-devel gettext gettext-devel
yum install -y libicu-devel libatasmart-devel
# Qt6/KF6 dependencies
yum install -y qt6-qtbase-devel qt6-linguist qt6-qtbase-private-devel qt6-qtdeclarative-devel qt6-qtsvg-devel qt6-qttools-devel
yum install -y extra-cmake-modules kf6-kcoreaddons-devel kf6-kdbusaddons-devel kf6-kcrash-devel
yum install -y kf6-kconfig-devel kf6-ki18n-devel kf6-kwidgetsaddons-devel kf6-kservice-devel
yum install -y polkit-qt6-1-devel appstream-qt-devel
# Runtime dependencies for QML modules
yum install -y kf6-kirigami2-devel || true
yum install -y qt6-qt5compat-devel || true
true

25
ci/deps-kaos.sh Executable file
View File

@@ -0,0 +1,25 @@
#! /bin/sh
#
# Install dependencies for building on KaOS
#
# There is no docker image for KaOS, and the live ISO comes
# with many useful things already installed, so the list
# here is short. Use pacman -Syu once to update the whole
# system to get latest libraries.
#
pacman -Syu --noconfirm git cmake ninja # No jq available
pacman -S --noconfirm \
"gcc" \
"boost" \
"qt5-tools" \
"yaml-cpp" \
"kpmcore" \
"icu"
pacman -S --noconfirm \
"extra-cmake-modules" \
"kiconthemes" \
"kservice" \
"kio" \
"kparts" \
"qtwebengine"
true

36
ci/deps-neon.sh Executable file
View File

@@ -0,0 +1,36 @@
#! /bin/sh
#
# Install dependencies for the nightly-neon build
#
apt-get update
apt-get -y install git-core jq ninja
apt-get -y install \
build-essential \
cmake \
extra-cmake-modules \
gettext \
kio-dev \
libatasmart-dev \
libboost-python-dev \
libkf5config-dev \
libkf5coreaddons-dev \
libkf5i18n-dev \
libkf5iconthemes-dev \
libkf5parts-dev \
libkf5service-dev \
libkf5solid-dev \
libkpmcore-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
true

Some files were not shown because too many files have changed in this diff Show More