tokev commited on
Commit
27167d9
·
verified ·
1 Parent(s): 4d03ebc

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. third_party/CityFlow/extern/pybind11/.git.bak/hooks/applypatch-msg.sample +15 -15
  2. third_party/CityFlow/extern/pybind11/.git.bak/hooks/commit-msg.sample +24 -24
  3. third_party/CityFlow/extern/pybind11/.git.bak/hooks/fsmonitor-watchman.sample +174 -174
  4. third_party/CityFlow/extern/pybind11/.git.bak/hooks/post-update.sample +8 -8
  5. third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-applypatch.sample +14 -14
  6. third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-commit.sample +49 -49
  7. third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-merge-commit.sample +13 -13
  8. third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-push.sample +53 -53
  9. third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-rebase.sample +169 -169
  10. third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-receive.sample +24 -24
  11. third_party/CityFlow/extern/pybind11/.git.bak/hooks/prepare-commit-msg.sample +42 -42
  12. third_party/CityFlow/extern/pybind11/.git.bak/hooks/push-to-checkout.sample +78 -78
  13. third_party/CityFlow/extern/pybind11/tests/test_async.py +24 -24
  14. third_party/CityFlow/extern/pybind11/tests/test_buffers.cpp +259 -259
  15. third_party/CityFlow/extern/pybind11/tests/test_buffers.py +228 -228
  16. third_party/CityFlow/extern/pybind11/tests/test_builtin_casters.cpp +392 -392
  17. third_party/CityFlow/extern/pybind11/tests/test_builtin_casters.py +528 -528
  18. third_party/CityFlow/extern/pybind11/tests/test_call_policies.cpp +115 -115
  19. third_party/CityFlow/extern/pybind11/tests/test_call_policies.py +247 -247
  20. third_party/CityFlow/extern/pybind11/tests/test_callbacks.cpp +280 -280
  21. third_party/CityFlow/extern/pybind11/tests/test_callbacks.py +225 -225
  22. third_party/CityFlow/extern/pybind11/tests/test_chrono.cpp +81 -81
  23. third_party/CityFlow/extern/pybind11/tests/test_chrono.py +205 -205
  24. third_party/CityFlow/extern/pybind11/tests/test_class.cpp +657 -657
  25. third_party/CityFlow/extern/pybind11/tests/test_class.py +499 -499
  26. third_party/CityFlow/extern/pybind11/tests/test_const_name.cpp +55 -55
  27. third_party/CityFlow/extern/pybind11/tests/test_const_name.py +29 -29
  28. third_party/CityFlow/extern/pybind11/tests/test_constants_and_functions.cpp +158 -158
  29. third_party/CityFlow/extern/pybind11/tests/test_constants_and_functions.py +56 -56
  30. third_party/CityFlow/extern/pybind11/tests/test_copy_move.cpp +533 -533
  31. third_party/CityFlow/extern/pybind11/tests/test_copy_move.py +132 -132
  32. third_party/CityFlow/extern/pybind11/tests/test_custom_type_casters.cpp +221 -221
  33. third_party/CityFlow/extern/pybind11/tests/test_custom_type_casters.py +122 -122
  34. third_party/CityFlow/extern/pybind11/tests/test_custom_type_setup.cpp +41 -41
  35. third_party/CityFlow/extern/pybind11/tests/test_custom_type_setup.py +48 -48
  36. third_party/CityFlow/extern/pybind11/tests/test_docstring_options.cpp +141 -141
  37. third_party/CityFlow/extern/pybind11/tests/test_docstring_options.py +64 -64
  38. third_party/CityFlow/extern/pybind11/tests/test_eigen_matrix.cpp +445 -445
  39. third_party/CityFlow/extern/pybind11/tests/test_eigen_matrix.py +814 -814
  40. third_party/CityFlow/extern/pybind11/tests/test_eigen_tensor.cpp +18 -18
  41. third_party/CityFlow/extern/pybind11/tests/test_eigen_tensor.inl +333 -333
  42. third_party/CityFlow/extern/pybind11/tests/test_eigen_tensor.py +288 -288
  43. third_party/CityFlow/extern/pybind11/tests/test_enum.cpp +133 -133
  44. third_party/CityFlow/extern/pybind11/tests/test_enum.py +269 -269
  45. third_party/CityFlow/extern/pybind11/tests/test_eval.cpp +118 -118
  46. third_party/CityFlow/extern/pybind11/tests/test_eval.py +50 -50
  47. third_party/CityFlow/extern/pybind11/tests/test_eval_call.py +4 -4
  48. third_party/CityFlow/extern/pybind11/tests/test_exceptions.cpp +388 -388
  49. third_party/CityFlow/extern/pybind11/tests/test_exceptions.h +13 -13
  50. third_party/CityFlow/extern/pybind11/tests/test_exceptions.py +432 -432
third_party/CityFlow/extern/pybind11/.git.bak/hooks/applypatch-msg.sample CHANGED
@@ -1,15 +1,15 @@
1
- #!/bin/sh
2
- #
3
- # An example hook script to check the commit log message taken by
4
- # applypatch from an e-mail message.
5
- #
6
- # The hook should exit with non-zero status after issuing an
7
- # appropriate message if it wants to stop the commit. The hook is
8
- # allowed to edit the commit message file.
9
- #
10
- # To enable this hook, rename this file to "applypatch-msg".
11
-
12
- . git-sh-setup
13
- commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
14
- test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
15
- :
 
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to check the commit log message taken by
4
+ # applypatch from an e-mail message.
5
+ #
6
+ # The hook should exit with non-zero status after issuing an
7
+ # appropriate message if it wants to stop the commit. The hook is
8
+ # allowed to edit the commit message file.
9
+ #
10
+ # To enable this hook, rename this file to "applypatch-msg".
11
+
12
+ . git-sh-setup
13
+ commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
14
+ test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
15
+ :
third_party/CityFlow/extern/pybind11/.git.bak/hooks/commit-msg.sample CHANGED
@@ -1,24 +1,24 @@
1
- #!/bin/sh
2
- #
3
- # An example hook script to check the commit log message.
4
- # Called by "git commit" with one argument, the name of the file
5
- # that has the commit message. The hook should exit with non-zero
6
- # status after issuing an appropriate message if it wants to stop the
7
- # commit. The hook is allowed to edit the commit message file.
8
- #
9
- # To enable this hook, rename this file to "commit-msg".
10
-
11
- # Uncomment the below to add a Signed-off-by line to the message.
12
- # Doing this in a hook is a bad idea in general, but the prepare-commit-msg
13
- # hook is more suited to it.
14
- #
15
- # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
16
- # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
17
-
18
- # This example catches duplicate Signed-off-by lines.
19
-
20
- test "" = "$(grep '^Signed-off-by: ' "$1" |
21
- sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
22
- echo >&2 Duplicate Signed-off-by lines.
23
- exit 1
24
- }
 
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to check the commit log message.
4
+ # Called by "git commit" with one argument, the name of the file
5
+ # that has the commit message. The hook should exit with non-zero
6
+ # status after issuing an appropriate message if it wants to stop the
7
+ # commit. The hook is allowed to edit the commit message file.
8
+ #
9
+ # To enable this hook, rename this file to "commit-msg".
10
+
11
+ # Uncomment the below to add a Signed-off-by line to the message.
12
+ # Doing this in a hook is a bad idea in general, but the prepare-commit-msg
13
+ # hook is more suited to it.
14
+ #
15
+ # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
16
+ # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
17
+
18
+ # This example catches duplicate Signed-off-by lines.
19
+
20
+ test "" = "$(grep '^Signed-off-by: ' "$1" |
21
+ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
22
+ echo >&2 Duplicate Signed-off-by lines.
23
+ exit 1
24
+ }
third_party/CityFlow/extern/pybind11/.git.bak/hooks/fsmonitor-watchman.sample CHANGED
@@ -1,174 +1,174 @@
1
- #!/usr/bin/perl
2
-
3
- use strict;
4
- use warnings;
5
- use IPC::Open2;
6
-
7
- # An example hook script to integrate Watchman
8
- # (https://facebook.github.io/watchman/) with git to speed up detecting
9
- # new and modified files.
10
- #
11
- # The hook is passed a version (currently 2) and last update token
12
- # formatted as a string and outputs to stdout a new update token and
13
- # all files that have been modified since the update token. Paths must
14
- # be relative to the root of the working tree and separated by a single NUL.
15
- #
16
- # To enable this hook, rename this file to "query-watchman" and set
17
- # 'git config core.fsmonitor .git/hooks/query-watchman'
18
- #
19
- my ($version, $last_update_token) = @ARGV;
20
-
21
- # Uncomment for debugging
22
- # print STDERR "$0 $version $last_update_token\n";
23
-
24
- # Check the hook interface version
25
- if ($version ne 2) {
26
- die "Unsupported query-fsmonitor hook version '$version'.\n" .
27
- "Falling back to scanning...\n";
28
- }
29
-
30
- my $git_work_tree = get_working_dir();
31
-
32
- my $retry = 1;
33
-
34
- my $json_pkg;
35
- eval {
36
- require JSON::XS;
37
- $json_pkg = "JSON::XS";
38
- 1;
39
- } or do {
40
- require JSON::PP;
41
- $json_pkg = "JSON::PP";
42
- };
43
-
44
- launch_watchman();
45
-
46
- sub launch_watchman {
47
- my $o = watchman_query();
48
- if (is_work_tree_watched($o)) {
49
- output_result($o->{clock}, @{$o->{files}});
50
- }
51
- }
52
-
53
- sub output_result {
54
- my ($clockid, @files) = @_;
55
-
56
- # Uncomment for debugging watchman output
57
- # open (my $fh, ">", ".git/watchman-output.out");
58
- # binmode $fh, ":utf8";
59
- # print $fh "$clockid\n@files\n";
60
- # close $fh;
61
-
62
- binmode STDOUT, ":utf8";
63
- print $clockid;
64
- print "\0";
65
- local $, = "\0";
66
- print @files;
67
- }
68
-
69
- sub watchman_clock {
70
- my $response = qx/watchman clock "$git_work_tree"/;
71
- die "Failed to get clock id on '$git_work_tree'.\n" .
72
- "Falling back to scanning...\n" if $? != 0;
73
-
74
- return $json_pkg->new->utf8->decode($response);
75
- }
76
-
77
- sub watchman_query {
78
- my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
79
- or die "open2() failed: $!\n" .
80
- "Falling back to scanning...\n";
81
-
82
- # In the query expression below we're asking for names of files that
83
- # changed since $last_update_token but not from the .git folder.
84
- #
85
- # To accomplish this, we're using the "since" generator to use the
86
- # recency index to select candidate nodes and "fields" to limit the
87
- # output to file names only. Then we're using the "expression" term to
88
- # further constrain the results.
89
- my $last_update_line = "";
90
- if (substr($last_update_token, 0, 1) eq "c") {
91
- $last_update_token = "\"$last_update_token\"";
92
- $last_update_line = qq[\n"since": $last_update_token,];
93
- }
94
- my $query = <<" END";
95
- ["query", "$git_work_tree", {$last_update_line
96
- "fields": ["name"],
97
- "expression": ["not", ["dirname", ".git"]]
98
- }]
99
- END
100
-
101
- # Uncomment for debugging the watchman query
102
- # open (my $fh, ">", ".git/watchman-query.json");
103
- # print $fh $query;
104
- # close $fh;
105
-
106
- print CHLD_IN $query;
107
- close CHLD_IN;
108
- my $response = do {local $/; <CHLD_OUT>};
109
-
110
- # Uncomment for debugging the watch response
111
- # open ($fh, ">", ".git/watchman-response.json");
112
- # print $fh $response;
113
- # close $fh;
114
-
115
- die "Watchman: command returned no output.\n" .
116
- "Falling back to scanning...\n" if $response eq "";
117
- die "Watchman: command returned invalid output: $response\n" .
118
- "Falling back to scanning...\n" unless $response =~ /^\{/;
119
-
120
- return $json_pkg->new->utf8->decode($response);
121
- }
122
-
123
- sub is_work_tree_watched {
124
- my ($output) = @_;
125
- my $error = $output->{error};
126
- if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
127
- $retry--;
128
- my $response = qx/watchman watch "$git_work_tree"/;
129
- die "Failed to make watchman watch '$git_work_tree'.\n" .
130
- "Falling back to scanning...\n" if $? != 0;
131
- $output = $json_pkg->new->utf8->decode($response);
132
- $error = $output->{error};
133
- die "Watchman: $error.\n" .
134
- "Falling back to scanning...\n" if $error;
135
-
136
- # Uncomment for debugging watchman output
137
- # open (my $fh, ">", ".git/watchman-output.out");
138
- # close $fh;
139
-
140
- # Watchman will always return all files on the first query so
141
- # return the fast "everything is dirty" flag to git and do the
142
- # Watchman query just to get it over with now so we won't pay
143
- # the cost in git to look up each individual file.
144
- my $o = watchman_clock();
145
- $error = $output->{error};
146
-
147
- die "Watchman: $error.\n" .
148
- "Falling back to scanning...\n" if $error;
149
-
150
- output_result($o->{clock}, ("/"));
151
- $last_update_token = $o->{clock};
152
-
153
- eval { launch_watchman() };
154
- return 0;
155
- }
156
-
157
- die "Watchman: $error.\n" .
158
- "Falling back to scanning...\n" if $error;
159
-
160
- return 1;
161
- }
162
-
163
- sub get_working_dir {
164
- my $working_dir;
165
- if ($^O =~ 'msys' || $^O =~ 'cygwin') {
166
- $working_dir = Win32::GetCwd();
167
- $working_dir =~ tr/\\/\//;
168
- } else {
169
- require Cwd;
170
- $working_dir = Cwd::cwd();
171
- }
172
-
173
- return $working_dir;
174
- }
 
1
+ #!/usr/bin/perl
2
+
3
+ use strict;
4
+ use warnings;
5
+ use IPC::Open2;
6
+
7
+ # An example hook script to integrate Watchman
8
+ # (https://facebook.github.io/watchman/) with git to speed up detecting
9
+ # new and modified files.
10
+ #
11
+ # The hook is passed a version (currently 2) and last update token
12
+ # formatted as a string and outputs to stdout a new update token and
13
+ # all files that have been modified since the update token. Paths must
14
+ # be relative to the root of the working tree and separated by a single NUL.
15
+ #
16
+ # To enable this hook, rename this file to "query-watchman" and set
17
+ # 'git config core.fsmonitor .git/hooks/query-watchman'
18
+ #
19
+ my ($version, $last_update_token) = @ARGV;
20
+
21
+ # Uncomment for debugging
22
+ # print STDERR "$0 $version $last_update_token\n";
23
+
24
+ # Check the hook interface version
25
+ if ($version ne 2) {
26
+ die "Unsupported query-fsmonitor hook version '$version'.\n" .
27
+ "Falling back to scanning...\n";
28
+ }
29
+
30
+ my $git_work_tree = get_working_dir();
31
+
32
+ my $retry = 1;
33
+
34
+ my $json_pkg;
35
+ eval {
36
+ require JSON::XS;
37
+ $json_pkg = "JSON::XS";
38
+ 1;
39
+ } or do {
40
+ require JSON::PP;
41
+ $json_pkg = "JSON::PP";
42
+ };
43
+
44
+ launch_watchman();
45
+
46
+ sub launch_watchman {
47
+ my $o = watchman_query();
48
+ if (is_work_tree_watched($o)) {
49
+ output_result($o->{clock}, @{$o->{files}});
50
+ }
51
+ }
52
+
53
+ sub output_result {
54
+ my ($clockid, @files) = @_;
55
+
56
+ # Uncomment for debugging watchman output
57
+ # open (my $fh, ">", ".git/watchman-output.out");
58
+ # binmode $fh, ":utf8";
59
+ # print $fh "$clockid\n@files\n";
60
+ # close $fh;
61
+
62
+ binmode STDOUT, ":utf8";
63
+ print $clockid;
64
+ print "\0";
65
+ local $, = "\0";
66
+ print @files;
67
+ }
68
+
69
+ sub watchman_clock {
70
+ my $response = qx/watchman clock "$git_work_tree"/;
71
+ die "Failed to get clock id on '$git_work_tree'.\n" .
72
+ "Falling back to scanning...\n" if $? != 0;
73
+
74
+ return $json_pkg->new->utf8->decode($response);
75
+ }
76
+
77
+ sub watchman_query {
78
+ my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
79
+ or die "open2() failed: $!\n" .
80
+ "Falling back to scanning...\n";
81
+
82
+ # In the query expression below we're asking for names of files that
83
+ # changed since $last_update_token but not from the .git folder.
84
+ #
85
+ # To accomplish this, we're using the "since" generator to use the
86
+ # recency index to select candidate nodes and "fields" to limit the
87
+ # output to file names only. Then we're using the "expression" term to
88
+ # further constrain the results.
89
+ my $last_update_line = "";
90
+ if (substr($last_update_token, 0, 1) eq "c") {
91
+ $last_update_token = "\"$last_update_token\"";
92
+ $last_update_line = qq[\n"since": $last_update_token,];
93
+ }
94
+ my $query = <<" END";
95
+ ["query", "$git_work_tree", {$last_update_line
96
+ "fields": ["name"],
97
+ "expression": ["not", ["dirname", ".git"]]
98
+ }]
99
+ END
100
+
101
+ # Uncomment for debugging the watchman query
102
+ # open (my $fh, ">", ".git/watchman-query.json");
103
+ # print $fh $query;
104
+ # close $fh;
105
+
106
+ print CHLD_IN $query;
107
+ close CHLD_IN;
108
+ my $response = do {local $/; <CHLD_OUT>};
109
+
110
+ # Uncomment for debugging the watch response
111
+ # open ($fh, ">", ".git/watchman-response.json");
112
+ # print $fh $response;
113
+ # close $fh;
114
+
115
+ die "Watchman: command returned no output.\n" .
116
+ "Falling back to scanning...\n" if $response eq "";
117
+ die "Watchman: command returned invalid output: $response\n" .
118
+ "Falling back to scanning...\n" unless $response =~ /^\{/;
119
+
120
+ return $json_pkg->new->utf8->decode($response);
121
+ }
122
+
123
+ sub is_work_tree_watched {
124
+ my ($output) = @_;
125
+ my $error = $output->{error};
126
+ if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
127
+ $retry--;
128
+ my $response = qx/watchman watch "$git_work_tree"/;
129
+ die "Failed to make watchman watch '$git_work_tree'.\n" .
130
+ "Falling back to scanning...\n" if $? != 0;
131
+ $output = $json_pkg->new->utf8->decode($response);
132
+ $error = $output->{error};
133
+ die "Watchman: $error.\n" .
134
+ "Falling back to scanning...\n" if $error;
135
+
136
+ # Uncomment for debugging watchman output
137
+ # open (my $fh, ">", ".git/watchman-output.out");
138
+ # close $fh;
139
+
140
+ # Watchman will always return all files on the first query so
141
+ # return the fast "everything is dirty" flag to git and do the
142
+ # Watchman query just to get it over with now so we won't pay
143
+ # the cost in git to look up each individual file.
144
+ my $o = watchman_clock();
145
+ $error = $output->{error};
146
+
147
+ die "Watchman: $error.\n" .
148
+ "Falling back to scanning...\n" if $error;
149
+
150
+ output_result($o->{clock}, ("/"));
151
+ $last_update_token = $o->{clock};
152
+
153
+ eval { launch_watchman() };
154
+ return 0;
155
+ }
156
+
157
+ die "Watchman: $error.\n" .
158
+ "Falling back to scanning...\n" if $error;
159
+
160
+ return 1;
161
+ }
162
+
163
+ sub get_working_dir {
164
+ my $working_dir;
165
+ if ($^O =~ 'msys' || $^O =~ 'cygwin') {
166
+ $working_dir = Win32::GetCwd();
167
+ $working_dir =~ tr/\\/\//;
168
+ } else {
169
+ require Cwd;
170
+ $working_dir = Cwd::cwd();
171
+ }
172
+
173
+ return $working_dir;
174
+ }
third_party/CityFlow/extern/pybind11/.git.bak/hooks/post-update.sample CHANGED
@@ -1,8 +1,8 @@
1
- #!/bin/sh
2
- #
3
- # An example hook script to prepare a packed repository for use over
4
- # dumb transports.
5
- #
6
- # To enable this hook, rename this file to "post-update".
7
-
8
- exec git update-server-info
 
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to prepare a packed repository for use over
4
+ # dumb transports.
5
+ #
6
+ # To enable this hook, rename this file to "post-update".
7
+
8
+ exec git update-server-info
third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-applypatch.sample CHANGED
@@ -1,14 +1,14 @@
1
- #!/bin/sh
2
- #
3
- # An example hook script to verify what is about to be committed
4
- # by applypatch from an e-mail message.
5
- #
6
- # The hook should exit with non-zero status after issuing an
7
- # appropriate message if it wants to stop the commit.
8
- #
9
- # To enable this hook, rename this file to "pre-applypatch".
10
-
11
- . git-sh-setup
12
- precommit="$(git rev-parse --git-path hooks/pre-commit)"
13
- test -x "$precommit" && exec "$precommit" ${1+"$@"}
14
- :
 
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to verify what is about to be committed
4
+ # by applypatch from an e-mail message.
5
+ #
6
+ # The hook should exit with non-zero status after issuing an
7
+ # appropriate message if it wants to stop the commit.
8
+ #
9
+ # To enable this hook, rename this file to "pre-applypatch".
10
+
11
+ . git-sh-setup
12
+ precommit="$(git rev-parse --git-path hooks/pre-commit)"
13
+ test -x "$precommit" && exec "$precommit" ${1+"$@"}
14
+ :
third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-commit.sample CHANGED
@@ -1,49 +1,49 @@
1
- #!/bin/sh
2
- #
3
- # An example hook script to verify what is about to be committed.
4
- # Called by "git commit" with no arguments. The hook should
5
- # exit with non-zero status after issuing an appropriate message if
6
- # it wants to stop the commit.
7
- #
8
- # To enable this hook, rename this file to "pre-commit".
9
-
10
- if git rev-parse --verify HEAD >/dev/null 2>&1
11
- then
12
- against=HEAD
13
- else
14
- # Initial commit: diff against an empty tree object
15
- against=$(git hash-object -t tree /dev/null)
16
- fi
17
-
18
- # If you want to allow non-ASCII filenames set this variable to true.
19
- allownonascii=$(git config --type=bool hooks.allownonascii)
20
-
21
- # Redirect output to stderr.
22
- exec 1>&2
23
-
24
- # Cross platform projects tend to avoid non-ASCII filenames; prevent
25
- # them from being added to the repository. We exploit the fact that the
26
- # printable range starts at the space character and ends with tilde.
27
- if [ "$allownonascii" != "true" ] &&
28
- # Note that the use of brackets around a tr range is ok here, (it's
29
- # even required, for portability to Solaris 10's /usr/bin/tr), since
30
- # the square bracket bytes happen to fall in the designated range.
31
- test $(git diff-index --cached --name-only --diff-filter=A -z $against |
32
- LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
33
- then
34
- cat <<\EOF
35
- Error: Attempt to add a non-ASCII file name.
36
-
37
- This can cause problems if you want to work with people on other platforms.
38
-
39
- To be portable it is advisable to rename the file.
40
-
41
- If you know what you are doing you can disable this check using:
42
-
43
- git config hooks.allownonascii true
44
- EOF
45
- exit 1
46
- fi
47
-
48
- # If there are whitespace errors, print the offending file names and fail.
49
- exec git diff-index --check --cached $against --
 
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to verify what is about to be committed.
4
+ # Called by "git commit" with no arguments. The hook should
5
+ # exit with non-zero status after issuing an appropriate message if
6
+ # it wants to stop the commit.
7
+ #
8
+ # To enable this hook, rename this file to "pre-commit".
9
+
10
+ if git rev-parse --verify HEAD >/dev/null 2>&1
11
+ then
12
+ against=HEAD
13
+ else
14
+ # Initial commit: diff against an empty tree object
15
+ against=$(git hash-object -t tree /dev/null)
16
+ fi
17
+
18
+ # If you want to allow non-ASCII filenames set this variable to true.
19
+ allownonascii=$(git config --type=bool hooks.allownonascii)
20
+
21
+ # Redirect output to stderr.
22
+ exec 1>&2
23
+
24
+ # Cross platform projects tend to avoid non-ASCII filenames; prevent
25
+ # them from being added to the repository. We exploit the fact that the
26
+ # printable range starts at the space character and ends with tilde.
27
+ if [ "$allownonascii" != "true" ] &&
28
+ # Note that the use of brackets around a tr range is ok here, (it's
29
+ # even required, for portability to Solaris 10's /usr/bin/tr), since
30
+ # the square bracket bytes happen to fall in the designated range.
31
+ test $(git diff-index --cached --name-only --diff-filter=A -z $against |
32
+ LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
33
+ then
34
+ cat <<\EOF
35
+ Error: Attempt to add a non-ASCII file name.
36
+
37
+ This can cause problems if you want to work with people on other platforms.
38
+
39
+ To be portable it is advisable to rename the file.
40
+
41
+ If you know what you are doing you can disable this check using:
42
+
43
+ git config hooks.allownonascii true
44
+ EOF
45
+ exit 1
46
+ fi
47
+
48
+ # If there are whitespace errors, print the offending file names and fail.
49
+ exec git diff-index --check --cached $against --
third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-merge-commit.sample CHANGED
@@ -1,13 +1,13 @@
1
- #!/bin/sh
2
- #
3
- # An example hook script to verify what is about to be committed.
4
- # Called by "git merge" with no arguments. The hook should
5
- # exit with non-zero status after issuing an appropriate message to
6
- # stderr if it wants to stop the merge commit.
7
- #
8
- # To enable this hook, rename this file to "pre-merge-commit".
9
-
10
- . git-sh-setup
11
- test -x "$GIT_DIR/hooks/pre-commit" &&
12
- exec "$GIT_DIR/hooks/pre-commit"
13
- :
 
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to verify what is about to be committed.
4
+ # Called by "git merge" with no arguments. The hook should
5
+ # exit with non-zero status after issuing an appropriate message to
6
+ # stderr if it wants to stop the merge commit.
7
+ #
8
+ # To enable this hook, rename this file to "pre-merge-commit".
9
+
10
+ . git-sh-setup
11
+ test -x "$GIT_DIR/hooks/pre-commit" &&
12
+ exec "$GIT_DIR/hooks/pre-commit"
13
+ :
third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-push.sample CHANGED
@@ -1,53 +1,53 @@
1
- #!/bin/sh
2
-
3
- # An example hook script to verify what is about to be pushed. Called by "git
4
- # push" after it has checked the remote status, but before anything has been
5
- # pushed. If this script exits with a non-zero status nothing will be pushed.
6
- #
7
- # This hook is called with the following parameters:
8
- #
9
- # $1 -- Name of the remote to which the push is being done
10
- # $2 -- URL to which the push is being done
11
- #
12
- # If pushing without using a named remote those arguments will be equal.
13
- #
14
- # Information about the commits which are being pushed is supplied as lines to
15
- # the standard input in the form:
16
- #
17
- # <local ref> <local oid> <remote ref> <remote oid>
18
- #
19
- # This sample shows how to prevent push of commits where the log message starts
20
- # with "WIP" (work in progress).
21
-
22
- remote="$1"
23
- url="$2"
24
-
25
- zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
26
-
27
- while read local_ref local_oid remote_ref remote_oid
28
- do
29
- if test "$local_oid" = "$zero"
30
- then
31
- # Handle delete
32
- :
33
- else
34
- if test "$remote_oid" = "$zero"
35
- then
36
- # New branch, examine all commits
37
- range="$local_oid"
38
- else
39
- # Update to existing branch, examine new commits
40
- range="$remote_oid..$local_oid"
41
- fi
42
-
43
- # Check for WIP commit
44
- commit=$(git rev-list -n 1 --grep '^WIP' "$range")
45
- if test -n "$commit"
46
- then
47
- echo >&2 "Found WIP commit in $local_ref, not pushing"
48
- exit 1
49
- fi
50
- fi
51
- done
52
-
53
- exit 0
 
1
+ #!/bin/sh
2
+
3
+ # An example hook script to verify what is about to be pushed. Called by "git
4
+ # push" after it has checked the remote status, but before anything has been
5
+ # pushed. If this script exits with a non-zero status nothing will be pushed.
6
+ #
7
+ # This hook is called with the following parameters:
8
+ #
9
+ # $1 -- Name of the remote to which the push is being done
10
+ # $2 -- URL to which the push is being done
11
+ #
12
+ # If pushing without using a named remote those arguments will be equal.
13
+ #
14
+ # Information about the commits which are being pushed is supplied as lines to
15
+ # the standard input in the form:
16
+ #
17
+ # <local ref> <local oid> <remote ref> <remote oid>
18
+ #
19
+ # This sample shows how to prevent push of commits where the log message starts
20
+ # with "WIP" (work in progress).
21
+
22
+ remote="$1"
23
+ url="$2"
24
+
25
+ zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
26
+
27
+ while read local_ref local_oid remote_ref remote_oid
28
+ do
29
+ if test "$local_oid" = "$zero"
30
+ then
31
+ # Handle delete
32
+ :
33
+ else
34
+ if test "$remote_oid" = "$zero"
35
+ then
36
+ # New branch, examine all commits
37
+ range="$local_oid"
38
+ else
39
+ # Update to existing branch, examine new commits
40
+ range="$remote_oid..$local_oid"
41
+ fi
42
+
43
+ # Check for WIP commit
44
+ commit=$(git rev-list -n 1 --grep '^WIP' "$range")
45
+ if test -n "$commit"
46
+ then
47
+ echo >&2 "Found WIP commit in $local_ref, not pushing"
48
+ exit 1
49
+ fi
50
+ fi
51
+ done
52
+
53
+ exit 0
third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-rebase.sample CHANGED
@@ -1,169 +1,169 @@
1
- #!/bin/sh
2
- #
3
- # Copyright (c) 2006, 2008 Junio C Hamano
4
- #
5
- # The "pre-rebase" hook is run just before "git rebase" starts doing
6
- # its job, and can prevent the command from running by exiting with
7
- # non-zero status.
8
- #
9
- # The hook is called with the following parameters:
10
- #
11
- # $1 -- the upstream the series was forked from.
12
- # $2 -- the branch being rebased (or empty when rebasing the current branch).
13
- #
14
- # This sample shows how to prevent topic branches that are already
15
- # merged to 'next' branch from getting rebased, because allowing it
16
- # would result in rebasing already published history.
17
-
18
- publish=next
19
- basebranch="$1"
20
- if test "$#" = 2
21
- then
22
- topic="refs/heads/$2"
23
- else
24
- topic=`git symbolic-ref HEAD` ||
25
- exit 0 ;# we do not interrupt rebasing detached HEAD
26
- fi
27
-
28
- case "$topic" in
29
- refs/heads/??/*)
30
- ;;
31
- *)
32
- exit 0 ;# we do not interrupt others.
33
- ;;
34
- esac
35
-
36
- # Now we are dealing with a topic branch being rebased
37
- # on top of master. Is it OK to rebase it?
38
-
39
- # Does the topic really exist?
40
- git show-ref -q "$topic" || {
41
- echo >&2 "No such branch $topic"
42
- exit 1
43
- }
44
-
45
- # Is topic fully merged to master?
46
- not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
47
- if test -z "$not_in_master"
48
- then
49
- echo >&2 "$topic is fully merged to master; better remove it."
50
- exit 1 ;# we could allow it, but there is no point.
51
- fi
52
-
53
- # Is topic ever merged to next? If so you should not be rebasing it.
54
- only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
55
- only_next_2=`git rev-list ^master ${publish} | sort`
56
- if test "$only_next_1" = "$only_next_2"
57
- then
58
- not_in_topic=`git rev-list "^$topic" master`
59
- if test -z "$not_in_topic"
60
- then
61
- echo >&2 "$topic is already up to date with master"
62
- exit 1 ;# we could allow it, but there is no point.
63
- else
64
- exit 0
65
- fi
66
- else
67
- not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
68
- /usr/bin/perl -e '
69
- my $topic = $ARGV[0];
70
- my $msg = "* $topic has commits already merged to public branch:\n";
71
- my (%not_in_next) = map {
72
- /^([0-9a-f]+) /;
73
- ($1 => 1);
74
- } split(/\n/, $ARGV[1]);
75
- for my $elem (map {
76
- /^([0-9a-f]+) (.*)$/;
77
- [$1 => $2];
78
- } split(/\n/, $ARGV[2])) {
79
- if (!exists $not_in_next{$elem->[0]}) {
80
- if ($msg) {
81
- print STDERR $msg;
82
- undef $msg;
83
- }
84
- print STDERR " $elem->[1]\n";
85
- }
86
- }
87
- ' "$topic" "$not_in_next" "$not_in_master"
88
- exit 1
89
- fi
90
-
91
- <<\DOC_END
92
-
93
- This sample hook safeguards topic branches that have been
94
- published from being rewound.
95
-
96
- The workflow assumed here is:
97
-
98
- * Once a topic branch forks from "master", "master" is never
99
- merged into it again (either directly or indirectly).
100
-
101
- * Once a topic branch is fully cooked and merged into "master",
102
- it is deleted. If you need to build on top of it to correct
103
- earlier mistakes, a new topic branch is created by forking at
104
- the tip of the "master". This is not strictly necessary, but
105
- it makes it easier to keep your history simple.
106
-
107
- * Whenever you need to test or publish your changes to topic
108
- branches, merge them into "next" branch.
109
-
110
- The script, being an example, hardcodes the publish branch name
111
- to be "next", but it is trivial to make it configurable via
112
- $GIT_DIR/config mechanism.
113
-
114
- With this workflow, you would want to know:
115
-
116
- (1) ... if a topic branch has ever been merged to "next". Young
117
- topic branches can have stupid mistakes you would rather
118
- clean up before publishing, and things that have not been
119
- merged into other branches can be easily rebased without
120
- affecting other people. But once it is published, you would
121
- not want to rewind it.
122
-
123
- (2) ... if a topic branch has been fully merged to "master".
124
- Then you can delete it. More importantly, you should not
125
- build on top of it -- other people may already want to
126
- change things related to the topic as patches against your
127
- "master", so if you need further changes, it is better to
128
- fork the topic (perhaps with the same name) afresh from the
129
- tip of "master".
130
-
131
- Let's look at this example:
132
-
133
- o---o---o---o---o---o---o---o---o---o "next"
134
- / / / /
135
- / a---a---b A / /
136
- / / / /
137
- / / c---c---c---c B /
138
- / / / \ /
139
- / / / b---b C \ /
140
- / / / / \ /
141
- ---o---o---o---o---o---o---o---o---o---o---o "master"
142
-
143
-
144
- A, B and C are topic branches.
145
-
146
- * A has one fix since it was merged up to "next".
147
-
148
- * B has finished. It has been fully merged up to "master" and "next",
149
- and is ready to be deleted.
150
-
151
- * C has not merged to "next" at all.
152
-
153
- We would want to allow C to be rebased, refuse A, and encourage
154
- B to be deleted.
155
-
156
- To compute (1):
157
-
158
- git rev-list ^master ^topic next
159
- git rev-list ^master next
160
-
161
- if these match, topic has not merged in next at all.
162
-
163
- To compute (2):
164
-
165
- git rev-list master..topic
166
-
167
- if this is empty, it is fully merged to "master".
168
-
169
- DOC_END
 
1
+ #!/bin/sh
2
+ #
3
+ # Copyright (c) 2006, 2008 Junio C Hamano
4
+ #
5
+ # The "pre-rebase" hook is run just before "git rebase" starts doing
6
+ # its job, and can prevent the command from running by exiting with
7
+ # non-zero status.
8
+ #
9
+ # The hook is called with the following parameters:
10
+ #
11
+ # $1 -- the upstream the series was forked from.
12
+ # $2 -- the branch being rebased (or empty when rebasing the current branch).
13
+ #
14
+ # This sample shows how to prevent topic branches that are already
15
+ # merged to 'next' branch from getting rebased, because allowing it
16
+ # would result in rebasing already published history.
17
+
18
+ publish=next
19
+ basebranch="$1"
20
+ if test "$#" = 2
21
+ then
22
+ topic="refs/heads/$2"
23
+ else
24
+ topic=`git symbolic-ref HEAD` ||
25
+ exit 0 ;# we do not interrupt rebasing detached HEAD
26
+ fi
27
+
28
+ case "$topic" in
29
+ refs/heads/??/*)
30
+ ;;
31
+ *)
32
+ exit 0 ;# we do not interrupt others.
33
+ ;;
34
+ esac
35
+
36
+ # Now we are dealing with a topic branch being rebased
37
+ # on top of master. Is it OK to rebase it?
38
+
39
+ # Does the topic really exist?
40
+ git show-ref -q "$topic" || {
41
+ echo >&2 "No such branch $topic"
42
+ exit 1
43
+ }
44
+
45
+ # Is topic fully merged to master?
46
+ not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
47
+ if test -z "$not_in_master"
48
+ then
49
+ echo >&2 "$topic is fully merged to master; better remove it."
50
+ exit 1 ;# we could allow it, but there is no point.
51
+ fi
52
+
53
+ # Is topic ever merged to next? If so you should not be rebasing it.
54
+ only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
55
+ only_next_2=`git rev-list ^master ${publish} | sort`
56
+ if test "$only_next_1" = "$only_next_2"
57
+ then
58
+ not_in_topic=`git rev-list "^$topic" master`
59
+ if test -z "$not_in_topic"
60
+ then
61
+ echo >&2 "$topic is already up to date with master"
62
+ exit 1 ;# we could allow it, but there is no point.
63
+ else
64
+ exit 0
65
+ fi
66
+ else
67
+ not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
68
+ /usr/bin/perl -e '
69
+ my $topic = $ARGV[0];
70
+ my $msg = "* $topic has commits already merged to public branch:\n";
71
+ my (%not_in_next) = map {
72
+ /^([0-9a-f]+) /;
73
+ ($1 => 1);
74
+ } split(/\n/, $ARGV[1]);
75
+ for my $elem (map {
76
+ /^([0-9a-f]+) (.*)$/;
77
+ [$1 => $2];
78
+ } split(/\n/, $ARGV[2])) {
79
+ if (!exists $not_in_next{$elem->[0]}) {
80
+ if ($msg) {
81
+ print STDERR $msg;
82
+ undef $msg;
83
+ }
84
+ print STDERR " $elem->[1]\n";
85
+ }
86
+ }
87
+ ' "$topic" "$not_in_next" "$not_in_master"
88
+ exit 1
89
+ fi
90
+
91
+ <<\DOC_END
92
+
93
+ This sample hook safeguards topic branches that have been
94
+ published from being rewound.
95
+
96
+ The workflow assumed here is:
97
+
98
+ * Once a topic branch forks from "master", "master" is never
99
+ merged into it again (either directly or indirectly).
100
+
101
+ * Once a topic branch is fully cooked and merged into "master",
102
+ it is deleted. If you need to build on top of it to correct
103
+ earlier mistakes, a new topic branch is created by forking at
104
+ the tip of the "master". This is not strictly necessary, but
105
+ it makes it easier to keep your history simple.
106
+
107
+ * Whenever you need to test or publish your changes to topic
108
+ branches, merge them into "next" branch.
109
+
110
+ The script, being an example, hardcodes the publish branch name
111
+ to be "next", but it is trivial to make it configurable via
112
+ $GIT_DIR/config mechanism.
113
+
114
+ With this workflow, you would want to know:
115
+
116
+ (1) ... if a topic branch has ever been merged to "next". Young
117
+ topic branches can have stupid mistakes you would rather
118
+ clean up before publishing, and things that have not been
119
+ merged into other branches can be easily rebased without
120
+ affecting other people. But once it is published, you would
121
+ not want to rewind it.
122
+
123
+ (2) ... if a topic branch has been fully merged to "master".
124
+ Then you can delete it. More importantly, you should not
125
+ build on top of it -- other people may already want to
126
+ change things related to the topic as patches against your
127
+ "master", so if you need further changes, it is better to
128
+ fork the topic (perhaps with the same name) afresh from the
129
+ tip of "master".
130
+
131
+ Let's look at this example:
132
+
133
+ o---o---o---o---o---o---o---o---o---o "next"
134
+ / / / /
135
+ / a---a---b A / /
136
+ / / / /
137
+ / / c---c---c---c B /
138
+ / / / \ /
139
+ / / / b---b C \ /
140
+ / / / / \ /
141
+ ---o---o---o---o---o---o---o---o---o---o---o "master"
142
+
143
+
144
+ A, B and C are topic branches.
145
+
146
+ * A has one fix since it was merged up to "next".
147
+
148
+ * B has finished. It has been fully merged up to "master" and "next",
149
+ and is ready to be deleted.
150
+
151
+ * C has not merged to "next" at all.
152
+
153
+ We would want to allow C to be rebased, refuse A, and encourage
154
+ B to be deleted.
155
+
156
+ To compute (1):
157
+
158
+ git rev-list ^master ^topic next
159
+ git rev-list ^master next
160
+
161
+ if these match, topic has not merged in next at all.
162
+
163
+ To compute (2):
164
+
165
+ git rev-list master..topic
166
+
167
+ if this is empty, it is fully merged to "master".
168
+
169
+ DOC_END
third_party/CityFlow/extern/pybind11/.git.bak/hooks/pre-receive.sample CHANGED
@@ -1,24 +1,24 @@
1
- #!/bin/sh
2
- #
3
- # An example hook script to make use of push options.
4
- # The example simply echoes all push options that start with 'echoback='
5
- # and rejects all pushes when the "reject" push option is used.
6
- #
7
- # To enable this hook, rename this file to "pre-receive".
8
-
9
- if test -n "$GIT_PUSH_OPTION_COUNT"
10
- then
11
- i=0
12
- while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
13
- do
14
- eval "value=\$GIT_PUSH_OPTION_$i"
15
- case "$value" in
16
- echoback=*)
17
- echo "echo from the pre-receive-hook: ${value#*=}" >&2
18
- ;;
19
- reject)
20
- exit 1
21
- esac
22
- i=$((i + 1))
23
- done
24
- fi
 
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to make use of push options.
4
+ # The example simply echoes all push options that start with 'echoback='
5
+ # and rejects all pushes when the "reject" push option is used.
6
+ #
7
+ # To enable this hook, rename this file to "pre-receive".
8
+
9
+ if test -n "$GIT_PUSH_OPTION_COUNT"
10
+ then
11
+ i=0
12
+ while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
13
+ do
14
+ eval "value=\$GIT_PUSH_OPTION_$i"
15
+ case "$value" in
16
+ echoback=*)
17
+ echo "echo from the pre-receive-hook: ${value#*=}" >&2
18
+ ;;
19
+ reject)
20
+ exit 1
21
+ esac
22
+ i=$((i + 1))
23
+ done
24
+ fi
third_party/CityFlow/extern/pybind11/.git.bak/hooks/prepare-commit-msg.sample CHANGED
@@ -1,42 +1,42 @@
1
- #!/bin/sh
2
- #
3
- # An example hook script to prepare the commit log message.
4
- # Called by "git commit" with the name of the file that has the
5
- # commit message, followed by the description of the commit
6
- # message's source. The hook's purpose is to edit the commit
7
- # message file. If the hook fails with a non-zero status,
8
- # the commit is aborted.
9
- #
10
- # To enable this hook, rename this file to "prepare-commit-msg".
11
-
12
- # This hook includes three examples. The first one removes the
13
- # "# Please enter the commit message..." help message.
14
- #
15
- # The second includes the output of "git diff --name-status -r"
16
- # into the message, just before the "git status" output. It is
17
- # commented because it doesn't cope with --amend or with squashed
18
- # commits.
19
- #
20
- # The third example adds a Signed-off-by line to the message, that can
21
- # still be edited. This is rarely a good idea.
22
-
23
- COMMIT_MSG_FILE=$1
24
- COMMIT_SOURCE=$2
25
- SHA1=$3
26
-
27
- /usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
28
-
29
- # case "$COMMIT_SOURCE,$SHA1" in
30
- # ,|template,)
31
- # /usr/bin/perl -i.bak -pe '
32
- # print "\n" . `git diff --cached --name-status -r`
33
- # if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
34
- # *) ;;
35
- # esac
36
-
37
- # SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
38
- # git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
39
- # if test -z "$COMMIT_SOURCE"
40
- # then
41
- # /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
42
- # fi
 
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to prepare the commit log message.
4
+ # Called by "git commit" with the name of the file that has the
5
+ # commit message, followed by the description of the commit
6
+ # message's source. The hook's purpose is to edit the commit
7
+ # message file. If the hook fails with a non-zero status,
8
+ # the commit is aborted.
9
+ #
10
+ # To enable this hook, rename this file to "prepare-commit-msg".
11
+
12
+ # This hook includes three examples. The first one removes the
13
+ # "# Please enter the commit message..." help message.
14
+ #
15
+ # The second includes the output of "git diff --name-status -r"
16
+ # into the message, just before the "git status" output. It is
17
+ # commented because it doesn't cope with --amend or with squashed
18
+ # commits.
19
+ #
20
+ # The third example adds a Signed-off-by line to the message, that can
21
+ # still be edited. This is rarely a good idea.
22
+
23
+ COMMIT_MSG_FILE=$1
24
+ COMMIT_SOURCE=$2
25
+ SHA1=$3
26
+
27
+ /usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
28
+
29
+ # case "$COMMIT_SOURCE,$SHA1" in
30
+ # ,|template,)
31
+ # /usr/bin/perl -i.bak -pe '
32
+ # print "\n" . `git diff --cached --name-status -r`
33
+ # if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
34
+ # *) ;;
35
+ # esac
36
+
37
+ # SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
38
+ # git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
39
+ # if test -z "$COMMIT_SOURCE"
40
+ # then
41
+ # /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
42
+ # fi
third_party/CityFlow/extern/pybind11/.git.bak/hooks/push-to-checkout.sample CHANGED
@@ -1,78 +1,78 @@
1
- #!/bin/sh
2
-
3
- # An example hook script to update a checked-out tree on a git push.
4
- #
5
- # This hook is invoked by git-receive-pack(1) when it reacts to git
6
- # push and updates reference(s) in its repository, and when the push
7
- # tries to update the branch that is currently checked out and the
8
- # receive.denyCurrentBranch configuration variable is set to
9
- # updateInstead.
10
- #
11
- # By default, such a push is refused if the working tree and the index
12
- # of the remote repository has any difference from the currently
13
- # checked out commit; when both the working tree and the index match
14
- # the current commit, they are updated to match the newly pushed tip
15
- # of the branch. This hook is to be used to override the default
16
- # behaviour; however the code below reimplements the default behaviour
17
- # as a starting point for convenient modification.
18
- #
19
- # The hook receives the commit with which the tip of the current
20
- # branch is going to be updated:
21
- commit=$1
22
-
23
- # It can exit with a non-zero status to refuse the push (when it does
24
- # so, it must not modify the index or the working tree).
25
- die () {
26
- echo >&2 "$*"
27
- exit 1
28
- }
29
-
30
- # Or it can make any necessary changes to the working tree and to the
31
- # index to bring them to the desired state when the tip of the current
32
- # branch is updated to the new commit, and exit with a zero status.
33
- #
34
- # For example, the hook can simply run git read-tree -u -m HEAD "$1"
35
- # in order to emulate git fetch that is run in the reverse direction
36
- # with git push, as the two-tree form of git read-tree -u -m is
37
- # essentially the same as git switch or git checkout that switches
38
- # branches while keeping the local changes in the working tree that do
39
- # not interfere with the difference between the branches.
40
-
41
- # The below is a more-or-less exact translation to shell of the C code
42
- # for the default behaviour for git's push-to-checkout hook defined in
43
- # the push_to_deploy() function in builtin/receive-pack.c.
44
- #
45
- # Note that the hook will be executed from the repository directory,
46
- # not from the working tree, so if you want to perform operations on
47
- # the working tree, you will have to adapt your code accordingly, e.g.
48
- # by adding "cd .." or using relative paths.
49
-
50
- if ! git update-index -q --ignore-submodules --refresh
51
- then
52
- die "Up-to-date check failed"
53
- fi
54
-
55
- if ! git diff-files --quiet --ignore-submodules --
56
- then
57
- die "Working directory has unstaged changes"
58
- fi
59
-
60
- # This is a rough translation of:
61
- #
62
- # head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
63
- if git cat-file -e HEAD 2>/dev/null
64
- then
65
- head=HEAD
66
- else
67
- head=$(git hash-object -t tree --stdin </dev/null)
68
- fi
69
-
70
- if ! git diff-index --quiet --cached --ignore-submodules $head --
71
- then
72
- die "Working directory has staged changes"
73
- fi
74
-
75
- if ! git read-tree -u -m "$commit"
76
- then
77
- die "Could not update working tree to new HEAD"
78
- fi
 
1
+ #!/bin/sh
2
+
3
+ # An example hook script to update a checked-out tree on a git push.
4
+ #
5
+ # This hook is invoked by git-receive-pack(1) when it reacts to git
6
+ # push and updates reference(s) in its repository, and when the push
7
+ # tries to update the branch that is currently checked out and the
8
+ # receive.denyCurrentBranch configuration variable is set to
9
+ # updateInstead.
10
+ #
11
+ # By default, such a push is refused if the working tree and the index
12
+ # of the remote repository has any difference from the currently
13
+ # checked out commit; when both the working tree and the index match
14
+ # the current commit, they are updated to match the newly pushed tip
15
+ # of the branch. This hook is to be used to override the default
16
+ # behaviour; however the code below reimplements the default behaviour
17
+ # as a starting point for convenient modification.
18
+ #
19
+ # The hook receives the commit with which the tip of the current
20
+ # branch is going to be updated:
21
+ commit=$1
22
+
23
+ # It can exit with a non-zero status to refuse the push (when it does
24
+ # so, it must not modify the index or the working tree).
25
+ die () {
26
+ echo >&2 "$*"
27
+ exit 1
28
+ }
29
+
30
+ # Or it can make any necessary changes to the working tree and to the
31
+ # index to bring them to the desired state when the tip of the current
32
+ # branch is updated to the new commit, and exit with a zero status.
33
+ #
34
+ # For example, the hook can simply run git read-tree -u -m HEAD "$1"
35
+ # in order to emulate git fetch that is run in the reverse direction
36
+ # with git push, as the two-tree form of git read-tree -u -m is
37
+ # essentially the same as git switch or git checkout that switches
38
+ # branches while keeping the local changes in the working tree that do
39
+ # not interfere with the difference between the branches.
40
+
41
+ # The below is a more-or-less exact translation to shell of the C code
42
+ # for the default behaviour for git's push-to-checkout hook defined in
43
+ # the push_to_deploy() function in builtin/receive-pack.c.
44
+ #
45
+ # Note that the hook will be executed from the repository directory,
46
+ # not from the working tree, so if you want to perform operations on
47
+ # the working tree, you will have to adapt your code accordingly, e.g.
48
+ # by adding "cd .." or using relative paths.
49
+
50
+ if ! git update-index -q --ignore-submodules --refresh
51
+ then
52
+ die "Up-to-date check failed"
53
+ fi
54
+
55
+ if ! git diff-files --quiet --ignore-submodules --
56
+ then
57
+ die "Working directory has unstaged changes"
58
+ fi
59
+
60
+ # This is a rough translation of:
61
+ #
62
+ # head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
63
+ if git cat-file -e HEAD 2>/dev/null
64
+ then
65
+ head=HEAD
66
+ else
67
+ head=$(git hash-object -t tree --stdin </dev/null)
68
+ fi
69
+
70
+ if ! git diff-index --quiet --cached --ignore-submodules $head --
71
+ then
72
+ die "Working directory has staged changes"
73
+ fi
74
+
75
+ if ! git read-tree -u -m "$commit"
76
+ then
77
+ die "Could not update working tree to new HEAD"
78
+ fi
third_party/CityFlow/extern/pybind11/tests/test_async.py CHANGED
@@ -1,24 +1,24 @@
1
- import pytest
2
-
3
- asyncio = pytest.importorskip("asyncio")
4
- m = pytest.importorskip("pybind11_tests.async_module")
5
-
6
-
7
- @pytest.fixture()
8
- def event_loop():
9
- loop = asyncio.new_event_loop()
10
- yield loop
11
- loop.close()
12
-
13
-
14
- async def get_await_result(x):
15
- return await x
16
-
17
-
18
- def test_await(event_loop):
19
- assert event_loop.run_until_complete(get_await_result(m.SupportsAsync())) == 5
20
-
21
-
22
- def test_await_missing(event_loop):
23
- with pytest.raises(TypeError):
24
- event_loop.run_until_complete(get_await_result(m.DoesNotSupportAsync()))
 
1
+ import pytest
2
+
3
+ asyncio = pytest.importorskip("asyncio")
4
+ m = pytest.importorskip("pybind11_tests.async_module")
5
+
6
+
7
+ @pytest.fixture()
8
+ def event_loop():
9
+ loop = asyncio.new_event_loop()
10
+ yield loop
11
+ loop.close()
12
+
13
+
14
+ async def get_await_result(x):
15
+ return await x
16
+
17
+
18
+ def test_await(event_loop):
19
+ assert event_loop.run_until_complete(get_await_result(m.SupportsAsync())) == 5
20
+
21
+
22
+ def test_await_missing(event_loop):
23
+ with pytest.raises(TypeError):
24
+ event_loop.run_until_complete(get_await_result(m.DoesNotSupportAsync()))
third_party/CityFlow/extern/pybind11/tests/test_buffers.cpp CHANGED
@@ -1,259 +1,259 @@
1
- /*
2
- tests/test_buffers.cpp -- supporting Pythons' buffer protocol
3
-
4
- Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include <pybind11/complex.h>
11
- #include <pybind11/stl.h>
12
-
13
- #include "constructor_stats.h"
14
- #include "pybind11_tests.h"
15
-
16
- TEST_SUBMODULE(buffers, m) {
17
- m.attr("long_double_and_double_have_same_size") = (sizeof(long double) == sizeof(double));
18
-
19
- m.def("format_descriptor_format_buffer_info_equiv",
20
- [](const std::string &cpp_name, const py::buffer &buffer) {
21
- // https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
22
- static auto *format_table = new std::map<std::string, std::string>;
23
- static auto *equiv_table
24
- = new std::map<std::string, bool (py::buffer_info::*)() const>;
25
- if (format_table->empty()) {
26
- #define PYBIND11_ASSIGN_HELPER(...) \
27
- (*format_table)[#__VA_ARGS__] = py::format_descriptor<__VA_ARGS__>::format(); \
28
- (*equiv_table)[#__VA_ARGS__] = &py::buffer_info::item_type_is_equivalent_to<__VA_ARGS__>;
29
- PYBIND11_ASSIGN_HELPER(PyObject *)
30
- PYBIND11_ASSIGN_HELPER(bool)
31
- PYBIND11_ASSIGN_HELPER(std::int8_t)
32
- PYBIND11_ASSIGN_HELPER(std::uint8_t)
33
- PYBIND11_ASSIGN_HELPER(std::int16_t)
34
- PYBIND11_ASSIGN_HELPER(std::uint16_t)
35
- PYBIND11_ASSIGN_HELPER(std::int32_t)
36
- PYBIND11_ASSIGN_HELPER(std::uint32_t)
37
- PYBIND11_ASSIGN_HELPER(std::int64_t)
38
- PYBIND11_ASSIGN_HELPER(std::uint64_t)
39
- PYBIND11_ASSIGN_HELPER(float)
40
- PYBIND11_ASSIGN_HELPER(double)
41
- PYBIND11_ASSIGN_HELPER(long double)
42
- PYBIND11_ASSIGN_HELPER(std::complex<float>)
43
- PYBIND11_ASSIGN_HELPER(std::complex<double>)
44
- PYBIND11_ASSIGN_HELPER(std::complex<long double>)
45
- #undef PYBIND11_ASSIGN_HELPER
46
- }
47
- return std::pair<std::string, bool>(
48
- (*format_table)[cpp_name], (buffer.request().*((*equiv_table)[cpp_name]))());
49
- });
50
-
51
- // test_from_python / test_to_python:
52
- class Matrix {
53
- public:
54
- Matrix(py::ssize_t rows, py::ssize_t cols) : m_rows(rows), m_cols(cols) {
55
- print_created(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
56
- // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
57
- m_data = new float[(size_t) (rows * cols)];
58
- memset(m_data, 0, sizeof(float) * (size_t) (rows * cols));
59
- }
60
-
61
- Matrix(const Matrix &s) : m_rows(s.m_rows), m_cols(s.m_cols) {
62
- print_copy_created(this,
63
- std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
64
- // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
65
- m_data = new float[(size_t) (m_rows * m_cols)];
66
- memcpy(m_data, s.m_data, sizeof(float) * (size_t) (m_rows * m_cols));
67
- }
68
-
69
- Matrix(Matrix &&s) noexcept : m_rows(s.m_rows), m_cols(s.m_cols), m_data(s.m_data) {
70
- print_move_created(this);
71
- s.m_rows = 0;
72
- s.m_cols = 0;
73
- s.m_data = nullptr;
74
- }
75
-
76
- ~Matrix() {
77
- print_destroyed(this,
78
- std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
79
- delete[] m_data;
80
- }
81
-
82
- Matrix &operator=(const Matrix &s) {
83
- if (this == &s) {
84
- return *this;
85
- }
86
- print_copy_assigned(this,
87
- std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
88
- delete[] m_data;
89
- m_rows = s.m_rows;
90
- m_cols = s.m_cols;
91
- m_data = new float[(size_t) (m_rows * m_cols)];
92
- memcpy(m_data, s.m_data, sizeof(float) * (size_t) (m_rows * m_cols));
93
- return *this;
94
- }
95
-
96
- Matrix &operator=(Matrix &&s) noexcept {
97
- print_move_assigned(this,
98
- std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
99
- if (&s != this) {
100
- delete[] m_data;
101
- m_rows = s.m_rows;
102
- m_cols = s.m_cols;
103
- m_data = s.m_data;
104
- s.m_rows = 0;
105
- s.m_cols = 0;
106
- s.m_data = nullptr;
107
- }
108
- return *this;
109
- }
110
-
111
- float operator()(py::ssize_t i, py::ssize_t j) const {
112
- return m_data[(size_t) (i * m_cols + j)];
113
- }
114
-
115
- float &operator()(py::ssize_t i, py::ssize_t j) {
116
- return m_data[(size_t) (i * m_cols + j)];
117
- }
118
-
119
- float *data() { return m_data; }
120
-
121
- py::ssize_t rows() const { return m_rows; }
122
- py::ssize_t cols() const { return m_cols; }
123
-
124
- private:
125
- py::ssize_t m_rows;
126
- py::ssize_t m_cols;
127
- float *m_data;
128
- };
129
- py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
130
- .def(py::init<py::ssize_t, py::ssize_t>())
131
- /// Construct from a buffer
132
- .def(py::init([](const py::buffer &b) {
133
- py::buffer_info info = b.request();
134
- if (info.format != py::format_descriptor<float>::format() || info.ndim != 2) {
135
- throw std::runtime_error("Incompatible buffer format!");
136
- }
137
-
138
- auto *v = new Matrix(info.shape[0], info.shape[1]);
139
- memcpy(v->data(), info.ptr, sizeof(float) * (size_t) (v->rows() * v->cols()));
140
- return v;
141
- }))
142
-
143
- .def("rows", &Matrix::rows)
144
- .def("cols", &Matrix::cols)
145
-
146
- /// Bare bones interface
147
- .def("__getitem__",
148
- [](const Matrix &m, std::pair<py::ssize_t, py::ssize_t> i) {
149
- if (i.first >= m.rows() || i.second >= m.cols()) {
150
- throw py::index_error();
151
- }
152
- return m(i.first, i.second);
153
- })
154
- .def("__setitem__",
155
- [](Matrix &m, std::pair<py::ssize_t, py::ssize_t> i, float v) {
156
- if (i.first >= m.rows() || i.second >= m.cols()) {
157
- throw py::index_error();
158
- }
159
- m(i.first, i.second) = v;
160
- })
161
- /// Provide buffer access
162
- .def_buffer([](Matrix &m) -> py::buffer_info {
163
- return py::buffer_info(
164
- m.data(), /* Pointer to buffer */
165
- {m.rows(), m.cols()}, /* Buffer dimensions */
166
- {sizeof(float) * size_t(m.cols()), /* Strides (in bytes) for each index */
167
- sizeof(float)});
168
- });
169
-
170
- // test_inherited_protocol
171
- class SquareMatrix : public Matrix {
172
- public:
173
- explicit SquareMatrix(py::ssize_t n) : Matrix(n, n) {}
174
- };
175
- // Derived classes inherit the buffer protocol and the buffer access function
176
- py::class_<SquareMatrix, Matrix>(m, "SquareMatrix").def(py::init<py::ssize_t>());
177
-
178
- // test_pointer_to_member_fn
179
- // Tests that passing a pointer to member to the base class works in
180
- // the derived class.
181
- struct Buffer {
182
- int32_t value = 0;
183
-
184
- py::buffer_info get_buffer_info() {
185
- return py::buffer_info(
186
- &value, sizeof(value), py::format_descriptor<int32_t>::format(), 1);
187
- }
188
- };
189
- py::class_<Buffer>(m, "Buffer", py::buffer_protocol())
190
- .def(py::init<>())
191
- .def_readwrite("value", &Buffer::value)
192
- .def_buffer(&Buffer::get_buffer_info);
193
-
194
- class ConstBuffer {
195
- std::unique_ptr<int32_t> value;
196
-
197
- public:
198
- int32_t get_value() const { return *value; }
199
- void set_value(int32_t v) { *value = v; }
200
-
201
- py::buffer_info get_buffer_info() const {
202
- return py::buffer_info(
203
- value.get(), sizeof(*value), py::format_descriptor<int32_t>::format(), 1);
204
- }
205
-
206
- ConstBuffer() : value(new int32_t{0}) {}
207
- };
208
- py::class_<ConstBuffer>(m, "ConstBuffer", py::buffer_protocol())
209
- .def(py::init<>())
210
- .def_property("value", &ConstBuffer::get_value, &ConstBuffer::set_value)
211
- .def_buffer(&ConstBuffer::get_buffer_info);
212
-
213
- struct DerivedBuffer : public Buffer {};
214
- py::class_<DerivedBuffer>(m, "DerivedBuffer", py::buffer_protocol())
215
- .def(py::init<>())
216
- .def_readwrite("value", (int32_t DerivedBuffer::*) &DerivedBuffer::value)
217
- .def_buffer(&DerivedBuffer::get_buffer_info);
218
-
219
- struct BufferReadOnly {
220
- const uint8_t value = 0;
221
- explicit BufferReadOnly(uint8_t value) : value(value) {}
222
-
223
- py::buffer_info get_buffer_info() { return py::buffer_info(&value, 1); }
224
- };
225
- py::class_<BufferReadOnly>(m, "BufferReadOnly", py::buffer_protocol())
226
- .def(py::init<uint8_t>())
227
- .def_buffer(&BufferReadOnly::get_buffer_info);
228
-
229
- struct BufferReadOnlySelect {
230
- uint8_t value = 0;
231
- bool readonly = false;
232
-
233
- py::buffer_info get_buffer_info() { return py::buffer_info(&value, 1, readonly); }
234
- };
235
- py::class_<BufferReadOnlySelect>(m, "BufferReadOnlySelect", py::buffer_protocol())
236
- .def(py::init<>())
237
- .def_readwrite("value", &BufferReadOnlySelect::value)
238
- .def_readwrite("readonly", &BufferReadOnlySelect::readonly)
239
- .def_buffer(&BufferReadOnlySelect::get_buffer_info);
240
-
241
- // Expose buffer_info for testing.
242
- py::class_<py::buffer_info>(m, "buffer_info")
243
- .def(py::init<>())
244
- .def_readonly("itemsize", &py::buffer_info::itemsize)
245
- .def_readonly("size", &py::buffer_info::size)
246
- .def_readonly("format", &py::buffer_info::format)
247
- .def_readonly("ndim", &py::buffer_info::ndim)
248
- .def_readonly("shape", &py::buffer_info::shape)
249
- .def_readonly("strides", &py::buffer_info::strides)
250
- .def_readonly("readonly", &py::buffer_info::readonly)
251
- .def("__repr__", [](py::handle self) {
252
- return py::str("itemsize={0.itemsize!r}, size={0.size!r}, format={0.format!r}, "
253
- "ndim={0.ndim!r}, shape={0.shape!r}, strides={0.strides!r}, "
254
- "readonly={0.readonly!r}")
255
- .format(self);
256
- });
257
-
258
- m.def("get_buffer_info", [](const py::buffer &buffer) { return buffer.request(); });
259
- }
 
1
+ /*
2
+ tests/test_buffers.cpp -- supporting Pythons' buffer protocol
3
+
4
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include <pybind11/complex.h>
11
+ #include <pybind11/stl.h>
12
+
13
+ #include "constructor_stats.h"
14
+ #include "pybind11_tests.h"
15
+
16
+ TEST_SUBMODULE(buffers, m) {
17
+ m.attr("long_double_and_double_have_same_size") = (sizeof(long double) == sizeof(double));
18
+
19
+ m.def("format_descriptor_format_buffer_info_equiv",
20
+ [](const std::string &cpp_name, const py::buffer &buffer) {
21
+ // https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
22
+ static auto *format_table = new std::map<std::string, std::string>;
23
+ static auto *equiv_table
24
+ = new std::map<std::string, bool (py::buffer_info::*)() const>;
25
+ if (format_table->empty()) {
26
+ #define PYBIND11_ASSIGN_HELPER(...) \
27
+ (*format_table)[#__VA_ARGS__] = py::format_descriptor<__VA_ARGS__>::format(); \
28
+ (*equiv_table)[#__VA_ARGS__] = &py::buffer_info::item_type_is_equivalent_to<__VA_ARGS__>;
29
+ PYBIND11_ASSIGN_HELPER(PyObject *)
30
+ PYBIND11_ASSIGN_HELPER(bool)
31
+ PYBIND11_ASSIGN_HELPER(std::int8_t)
32
+ PYBIND11_ASSIGN_HELPER(std::uint8_t)
33
+ PYBIND11_ASSIGN_HELPER(std::int16_t)
34
+ PYBIND11_ASSIGN_HELPER(std::uint16_t)
35
+ PYBIND11_ASSIGN_HELPER(std::int32_t)
36
+ PYBIND11_ASSIGN_HELPER(std::uint32_t)
37
+ PYBIND11_ASSIGN_HELPER(std::int64_t)
38
+ PYBIND11_ASSIGN_HELPER(std::uint64_t)
39
+ PYBIND11_ASSIGN_HELPER(float)
40
+ PYBIND11_ASSIGN_HELPER(double)
41
+ PYBIND11_ASSIGN_HELPER(long double)
42
+ PYBIND11_ASSIGN_HELPER(std::complex<float>)
43
+ PYBIND11_ASSIGN_HELPER(std::complex<double>)
44
+ PYBIND11_ASSIGN_HELPER(std::complex<long double>)
45
+ #undef PYBIND11_ASSIGN_HELPER
46
+ }
47
+ return std::pair<std::string, bool>(
48
+ (*format_table)[cpp_name], (buffer.request().*((*equiv_table)[cpp_name]))());
49
+ });
50
+
51
+ // test_from_python / test_to_python:
52
+ class Matrix {
53
+ public:
54
+ Matrix(py::ssize_t rows, py::ssize_t cols) : m_rows(rows), m_cols(cols) {
55
+ print_created(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
56
+ // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
57
+ m_data = new float[(size_t) (rows * cols)];
58
+ memset(m_data, 0, sizeof(float) * (size_t) (rows * cols));
59
+ }
60
+
61
+ Matrix(const Matrix &s) : m_rows(s.m_rows), m_cols(s.m_cols) {
62
+ print_copy_created(this,
63
+ std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
64
+ // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
65
+ m_data = new float[(size_t) (m_rows * m_cols)];
66
+ memcpy(m_data, s.m_data, sizeof(float) * (size_t) (m_rows * m_cols));
67
+ }
68
+
69
+ Matrix(Matrix &&s) noexcept : m_rows(s.m_rows), m_cols(s.m_cols), m_data(s.m_data) {
70
+ print_move_created(this);
71
+ s.m_rows = 0;
72
+ s.m_cols = 0;
73
+ s.m_data = nullptr;
74
+ }
75
+
76
+ ~Matrix() {
77
+ print_destroyed(this,
78
+ std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
79
+ delete[] m_data;
80
+ }
81
+
82
+ Matrix &operator=(const Matrix &s) {
83
+ if (this == &s) {
84
+ return *this;
85
+ }
86
+ print_copy_assigned(this,
87
+ std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
88
+ delete[] m_data;
89
+ m_rows = s.m_rows;
90
+ m_cols = s.m_cols;
91
+ m_data = new float[(size_t) (m_rows * m_cols)];
92
+ memcpy(m_data, s.m_data, sizeof(float) * (size_t) (m_rows * m_cols));
93
+ return *this;
94
+ }
95
+
96
+ Matrix &operator=(Matrix &&s) noexcept {
97
+ print_move_assigned(this,
98
+ std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
99
+ if (&s != this) {
100
+ delete[] m_data;
101
+ m_rows = s.m_rows;
102
+ m_cols = s.m_cols;
103
+ m_data = s.m_data;
104
+ s.m_rows = 0;
105
+ s.m_cols = 0;
106
+ s.m_data = nullptr;
107
+ }
108
+ return *this;
109
+ }
110
+
111
+ float operator()(py::ssize_t i, py::ssize_t j) const {
112
+ return m_data[(size_t) (i * m_cols + j)];
113
+ }
114
+
115
+ float &operator()(py::ssize_t i, py::ssize_t j) {
116
+ return m_data[(size_t) (i * m_cols + j)];
117
+ }
118
+
119
+ float *data() { return m_data; }
120
+
121
+ py::ssize_t rows() const { return m_rows; }
122
+ py::ssize_t cols() const { return m_cols; }
123
+
124
+ private:
125
+ py::ssize_t m_rows;
126
+ py::ssize_t m_cols;
127
+ float *m_data;
128
+ };
129
+ py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
130
+ .def(py::init<py::ssize_t, py::ssize_t>())
131
+ /// Construct from a buffer
132
+ .def(py::init([](const py::buffer &b) {
133
+ py::buffer_info info = b.request();
134
+ if (info.format != py::format_descriptor<float>::format() || info.ndim != 2) {
135
+ throw std::runtime_error("Incompatible buffer format!");
136
+ }
137
+
138
+ auto *v = new Matrix(info.shape[0], info.shape[1]);
139
+ memcpy(v->data(), info.ptr, sizeof(float) * (size_t) (v->rows() * v->cols()));
140
+ return v;
141
+ }))
142
+
143
+ .def("rows", &Matrix::rows)
144
+ .def("cols", &Matrix::cols)
145
+
146
+ /// Bare bones interface
147
+ .def("__getitem__",
148
+ [](const Matrix &m, std::pair<py::ssize_t, py::ssize_t> i) {
149
+ if (i.first >= m.rows() || i.second >= m.cols()) {
150
+ throw py::index_error();
151
+ }
152
+ return m(i.first, i.second);
153
+ })
154
+ .def("__setitem__",
155
+ [](Matrix &m, std::pair<py::ssize_t, py::ssize_t> i, float v) {
156
+ if (i.first >= m.rows() || i.second >= m.cols()) {
157
+ throw py::index_error();
158
+ }
159
+ m(i.first, i.second) = v;
160
+ })
161
+ /// Provide buffer access
162
+ .def_buffer([](Matrix &m) -> py::buffer_info {
163
+ return py::buffer_info(
164
+ m.data(), /* Pointer to buffer */
165
+ {m.rows(), m.cols()}, /* Buffer dimensions */
166
+ {sizeof(float) * size_t(m.cols()), /* Strides (in bytes) for each index */
167
+ sizeof(float)});
168
+ });
169
+
170
+ // test_inherited_protocol
171
+ class SquareMatrix : public Matrix {
172
+ public:
173
+ explicit SquareMatrix(py::ssize_t n) : Matrix(n, n) {}
174
+ };
175
+ // Derived classes inherit the buffer protocol and the buffer access function
176
+ py::class_<SquareMatrix, Matrix>(m, "SquareMatrix").def(py::init<py::ssize_t>());
177
+
178
+ // test_pointer_to_member_fn
179
+ // Tests that passing a pointer to member to the base class works in
180
+ // the derived class.
181
+ struct Buffer {
182
+ int32_t value = 0;
183
+
184
+ py::buffer_info get_buffer_info() {
185
+ return py::buffer_info(
186
+ &value, sizeof(value), py::format_descriptor<int32_t>::format(), 1);
187
+ }
188
+ };
189
+ py::class_<Buffer>(m, "Buffer", py::buffer_protocol())
190
+ .def(py::init<>())
191
+ .def_readwrite("value", &Buffer::value)
192
+ .def_buffer(&Buffer::get_buffer_info);
193
+
194
+ class ConstBuffer {
195
+ std::unique_ptr<int32_t> value;
196
+
197
+ public:
198
+ int32_t get_value() const { return *value; }
199
+ void set_value(int32_t v) { *value = v; }
200
+
201
+ py::buffer_info get_buffer_info() const {
202
+ return py::buffer_info(
203
+ value.get(), sizeof(*value), py::format_descriptor<int32_t>::format(), 1);
204
+ }
205
+
206
+ ConstBuffer() : value(new int32_t{0}) {}
207
+ };
208
+ py::class_<ConstBuffer>(m, "ConstBuffer", py::buffer_protocol())
209
+ .def(py::init<>())
210
+ .def_property("value", &ConstBuffer::get_value, &ConstBuffer::set_value)
211
+ .def_buffer(&ConstBuffer::get_buffer_info);
212
+
213
+ struct DerivedBuffer : public Buffer {};
214
+ py::class_<DerivedBuffer>(m, "DerivedBuffer", py::buffer_protocol())
215
+ .def(py::init<>())
216
+ .def_readwrite("value", (int32_t DerivedBuffer::*) &DerivedBuffer::value)
217
+ .def_buffer(&DerivedBuffer::get_buffer_info);
218
+
219
+ struct BufferReadOnly {
220
+ const uint8_t value = 0;
221
+ explicit BufferReadOnly(uint8_t value) : value(value) {}
222
+
223
+ py::buffer_info get_buffer_info() { return py::buffer_info(&value, 1); }
224
+ };
225
+ py::class_<BufferReadOnly>(m, "BufferReadOnly", py::buffer_protocol())
226
+ .def(py::init<uint8_t>())
227
+ .def_buffer(&BufferReadOnly::get_buffer_info);
228
+
229
+ struct BufferReadOnlySelect {
230
+ uint8_t value = 0;
231
+ bool readonly = false;
232
+
233
+ py::buffer_info get_buffer_info() { return py::buffer_info(&value, 1, readonly); }
234
+ };
235
+ py::class_<BufferReadOnlySelect>(m, "BufferReadOnlySelect", py::buffer_protocol())
236
+ .def(py::init<>())
237
+ .def_readwrite("value", &BufferReadOnlySelect::value)
238
+ .def_readwrite("readonly", &BufferReadOnlySelect::readonly)
239
+ .def_buffer(&BufferReadOnlySelect::get_buffer_info);
240
+
241
+ // Expose buffer_info for testing.
242
+ py::class_<py::buffer_info>(m, "buffer_info")
243
+ .def(py::init<>())
244
+ .def_readonly("itemsize", &py::buffer_info::itemsize)
245
+ .def_readonly("size", &py::buffer_info::size)
246
+ .def_readonly("format", &py::buffer_info::format)
247
+ .def_readonly("ndim", &py::buffer_info::ndim)
248
+ .def_readonly("shape", &py::buffer_info::shape)
249
+ .def_readonly("strides", &py::buffer_info::strides)
250
+ .def_readonly("readonly", &py::buffer_info::readonly)
251
+ .def("__repr__", [](py::handle self) {
252
+ return py::str("itemsize={0.itemsize!r}, size={0.size!r}, format={0.format!r}, "
253
+ "ndim={0.ndim!r}, shape={0.shape!r}, strides={0.strides!r}, "
254
+ "readonly={0.readonly!r}")
255
+ .format(self);
256
+ });
257
+
258
+ m.def("get_buffer_info", [](const py::buffer &buffer) { return buffer.request(); });
259
+ }
third_party/CityFlow/extern/pybind11/tests/test_buffers.py CHANGED
@@ -1,228 +1,228 @@
1
- import ctypes
2
- import io
3
- import struct
4
-
5
- import pytest
6
-
7
- import env
8
- from pybind11_tests import ConstructorStats
9
- from pybind11_tests import buffers as m
10
-
11
- np = pytest.importorskip("numpy")
12
-
13
- if m.long_double_and_double_have_same_size:
14
- # Determined by the compiler used to build the pybind11 tests
15
- # (e.g. MSVC gets here, but MinGW might not).
16
- np_float128 = None
17
- np_complex256 = None
18
- else:
19
- # Determined by the compiler used to build numpy (e.g. MinGW).
20
- np_float128 = getattr(np, *["float128"] * 2)
21
- np_complex256 = getattr(np, *["complex256"] * 2)
22
-
23
- CPP_NAME_FORMAT_NP_DTYPE_TABLE = [
24
- ("PyObject *", "O", object),
25
- ("bool", "?", np.bool_),
26
- ("std::int8_t", "b", np.int8),
27
- ("std::uint8_t", "B", np.uint8),
28
- ("std::int16_t", "h", np.int16),
29
- ("std::uint16_t", "H", np.uint16),
30
- ("std::int32_t", "i", np.int32),
31
- ("std::uint32_t", "I", np.uint32),
32
- ("std::int64_t", "q", np.int64),
33
- ("std::uint64_t", "Q", np.uint64),
34
- ("float", "f", np.float32),
35
- ("double", "d", np.float64),
36
- ("long double", "g", np_float128),
37
- ("std::complex<float>", "Zf", np.complex64),
38
- ("std::complex<double>", "Zd", np.complex128),
39
- ("std::complex<long double>", "Zg", np_complex256),
40
- ]
41
- CPP_NAME_FORMAT_TABLE = [
42
- (cpp_name, format)
43
- for cpp_name, format, np_dtype in CPP_NAME_FORMAT_NP_DTYPE_TABLE
44
- if np_dtype is not None
45
- ]
46
- CPP_NAME_NP_DTYPE_TABLE = [
47
- (cpp_name, np_dtype) for cpp_name, _, np_dtype in CPP_NAME_FORMAT_NP_DTYPE_TABLE
48
- ]
49
-
50
-
51
- @pytest.mark.parametrize(("cpp_name", "np_dtype"), CPP_NAME_NP_DTYPE_TABLE)
52
- def test_format_descriptor_format_buffer_info_equiv(cpp_name, np_dtype):
53
- if np_dtype is None:
54
- pytest.skip(
55
- f"cpp_name=`{cpp_name}`: `long double` and `double` have same size."
56
- )
57
- if isinstance(np_dtype, str):
58
- pytest.skip(f"np.{np_dtype} does not exist.")
59
- np_array = np.array([], dtype=np_dtype)
60
- for other_cpp_name, expected_format in CPP_NAME_FORMAT_TABLE:
61
- format, np_array_is_matching = m.format_descriptor_format_buffer_info_equiv(
62
- other_cpp_name, np_array
63
- )
64
- assert format == expected_format
65
- if other_cpp_name == cpp_name:
66
- assert np_array_is_matching
67
- else:
68
- assert not np_array_is_matching
69
-
70
-
71
- def test_from_python():
72
- with pytest.raises(RuntimeError) as excinfo:
73
- m.Matrix(np.array([1, 2, 3])) # trying to assign a 1D array
74
- assert str(excinfo.value) == "Incompatible buffer format!"
75
-
76
- m3 = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
77
- m4 = m.Matrix(m3)
78
-
79
- for i in range(m4.rows()):
80
- for j in range(m4.cols()):
81
- assert m3[i, j] == m4[i, j]
82
-
83
- cstats = ConstructorStats.get(m.Matrix)
84
- assert cstats.alive() == 1
85
- del m3, m4
86
- assert cstats.alive() == 0
87
- assert cstats.values() == ["2x3 matrix"]
88
- assert cstats.copy_constructions == 0
89
- # assert cstats.move_constructions >= 0 # Don't invoke any
90
- assert cstats.copy_assignments == 0
91
- assert cstats.move_assignments == 0
92
-
93
-
94
- # https://foss.heptapod.net/pypy/pypy/-/issues/2444
95
- # TODO: fix on recent PyPy
96
- @pytest.mark.xfail(
97
- env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
98
- )
99
- def test_to_python():
100
- mat = m.Matrix(5, 4)
101
- assert memoryview(mat).shape == (5, 4)
102
-
103
- assert mat[2, 3] == 0
104
- mat[2, 3] = 4.0
105
- mat[3, 2] = 7.0
106
- assert mat[2, 3] == 4
107
- assert mat[3, 2] == 7
108
- assert struct.unpack_from("f", mat, (3 * 4 + 2) * 4) == (7,)
109
- assert struct.unpack_from("f", mat, (2 * 4 + 3) * 4) == (4,)
110
-
111
- mat2 = np.array(mat, copy=False)
112
- assert mat2.shape == (5, 4)
113
- assert abs(mat2).sum() == 11
114
- assert mat2[2, 3] == 4
115
- assert mat2[3, 2] == 7
116
- mat2[2, 3] = 5
117
- assert mat2[2, 3] == 5
118
-
119
- cstats = ConstructorStats.get(m.Matrix)
120
- assert cstats.alive() == 1
121
- del mat
122
- pytest.gc_collect()
123
- assert cstats.alive() == 1
124
- del mat2 # holds a mat reference
125
- pytest.gc_collect()
126
- assert cstats.alive() == 0
127
- assert cstats.values() == ["5x4 matrix"]
128
- assert cstats.copy_constructions == 0
129
- # assert cstats.move_constructions >= 0 # Don't invoke any
130
- assert cstats.copy_assignments == 0
131
- assert cstats.move_assignments == 0
132
-
133
-
134
- def test_inherited_protocol():
135
- """SquareMatrix is derived from Matrix and inherits the buffer protocol"""
136
-
137
- matrix = m.SquareMatrix(5)
138
- assert memoryview(matrix).shape == (5, 5)
139
- assert np.asarray(matrix).shape == (5, 5)
140
-
141
-
142
- def test_pointer_to_member_fn():
143
- for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]:
144
- buf = cls()
145
- buf.value = 0x12345678
146
- value = struct.unpack("i", bytearray(buf))[0]
147
- assert value == 0x12345678
148
-
149
-
150
- def test_readonly_buffer():
151
- buf = m.BufferReadOnly(0x64)
152
- view = memoryview(buf)
153
- assert view[0] == 0x64
154
- assert view.readonly
155
- with pytest.raises(TypeError):
156
- view[0] = 0
157
-
158
-
159
- def test_selective_readonly_buffer():
160
- buf = m.BufferReadOnlySelect()
161
-
162
- memoryview(buf)[0] = 0x64
163
- assert buf.value == 0x64
164
-
165
- io.BytesIO(b"A").readinto(buf)
166
- assert buf.value == ord(b"A")
167
-
168
- buf.readonly = True
169
- with pytest.raises(TypeError):
170
- memoryview(buf)[0] = 0
171
- with pytest.raises(TypeError):
172
- io.BytesIO(b"1").readinto(buf)
173
-
174
-
175
- def test_ctypes_array_1d():
176
- char1d = (ctypes.c_char * 10)()
177
- int1d = (ctypes.c_int * 15)()
178
- long1d = (ctypes.c_long * 7)()
179
-
180
- for carray in (char1d, int1d, long1d):
181
- info = m.get_buffer_info(carray)
182
- assert info.itemsize == ctypes.sizeof(carray._type_)
183
- assert info.size == len(carray)
184
- assert info.ndim == 1
185
- assert info.shape == [info.size]
186
- assert info.strides == [info.itemsize]
187
- assert not info.readonly
188
-
189
-
190
- def test_ctypes_array_2d():
191
- char2d = ((ctypes.c_char * 10) * 4)()
192
- int2d = ((ctypes.c_int * 15) * 3)()
193
- long2d = ((ctypes.c_long * 7) * 2)()
194
-
195
- for carray in (char2d, int2d, long2d):
196
- info = m.get_buffer_info(carray)
197
- assert info.itemsize == ctypes.sizeof(carray[0]._type_)
198
- assert info.size == len(carray) * len(carray[0])
199
- assert info.ndim == 2
200
- assert info.shape == [len(carray), len(carray[0])]
201
- assert info.strides == [info.itemsize * len(carray[0]), info.itemsize]
202
- assert not info.readonly
203
-
204
-
205
- def test_ctypes_from_buffer():
206
- test_pystr = b"0123456789"
207
- for pyarray in (test_pystr, bytearray(test_pystr)):
208
- pyinfo = m.get_buffer_info(pyarray)
209
-
210
- if pyinfo.readonly:
211
- cbytes = (ctypes.c_char * len(pyarray)).from_buffer_copy(pyarray)
212
- cinfo = m.get_buffer_info(cbytes)
213
- else:
214
- cbytes = (ctypes.c_char * len(pyarray)).from_buffer(pyarray)
215
- cinfo = m.get_buffer_info(cbytes)
216
-
217
- assert cinfo.size == pyinfo.size
218
- assert cinfo.ndim == pyinfo.ndim
219
- assert cinfo.shape == pyinfo.shape
220
- assert cinfo.strides == pyinfo.strides
221
- assert not cinfo.readonly
222
-
223
-
224
- def test_buffer_docstring():
225
- assert (
226
- m.get_buffer_info.__doc__.strip()
227
- == "get_buffer_info(arg0: Buffer) -> pybind11_tests.buffers.buffer_info"
228
- )
 
1
+ import ctypes
2
+ import io
3
+ import struct
4
+
5
+ import pytest
6
+
7
+ import env
8
+ from pybind11_tests import ConstructorStats
9
+ from pybind11_tests import buffers as m
10
+
11
+ np = pytest.importorskip("numpy")
12
+
13
+ if m.long_double_and_double_have_same_size:
14
+ # Determined by the compiler used to build the pybind11 tests
15
+ # (e.g. MSVC gets here, but MinGW might not).
16
+ np_float128 = None
17
+ np_complex256 = None
18
+ else:
19
+ # Determined by the compiler used to build numpy (e.g. MinGW).
20
+ np_float128 = getattr(np, *["float128"] * 2)
21
+ np_complex256 = getattr(np, *["complex256"] * 2)
22
+
23
+ CPP_NAME_FORMAT_NP_DTYPE_TABLE = [
24
+ ("PyObject *", "O", object),
25
+ ("bool", "?", np.bool_),
26
+ ("std::int8_t", "b", np.int8),
27
+ ("std::uint8_t", "B", np.uint8),
28
+ ("std::int16_t", "h", np.int16),
29
+ ("std::uint16_t", "H", np.uint16),
30
+ ("std::int32_t", "i", np.int32),
31
+ ("std::uint32_t", "I", np.uint32),
32
+ ("std::int64_t", "q", np.int64),
33
+ ("std::uint64_t", "Q", np.uint64),
34
+ ("float", "f", np.float32),
35
+ ("double", "d", np.float64),
36
+ ("long double", "g", np_float128),
37
+ ("std::complex<float>", "Zf", np.complex64),
38
+ ("std::complex<double>", "Zd", np.complex128),
39
+ ("std::complex<long double>", "Zg", np_complex256),
40
+ ]
41
+ CPP_NAME_FORMAT_TABLE = [
42
+ (cpp_name, format)
43
+ for cpp_name, format, np_dtype in CPP_NAME_FORMAT_NP_DTYPE_TABLE
44
+ if np_dtype is not None
45
+ ]
46
+ CPP_NAME_NP_DTYPE_TABLE = [
47
+ (cpp_name, np_dtype) for cpp_name, _, np_dtype in CPP_NAME_FORMAT_NP_DTYPE_TABLE
48
+ ]
49
+
50
+
51
+ @pytest.mark.parametrize(("cpp_name", "np_dtype"), CPP_NAME_NP_DTYPE_TABLE)
52
+ def test_format_descriptor_format_buffer_info_equiv(cpp_name, np_dtype):
53
+ if np_dtype is None:
54
+ pytest.skip(
55
+ f"cpp_name=`{cpp_name}`: `long double` and `double` have same size."
56
+ )
57
+ if isinstance(np_dtype, str):
58
+ pytest.skip(f"np.{np_dtype} does not exist.")
59
+ np_array = np.array([], dtype=np_dtype)
60
+ for other_cpp_name, expected_format in CPP_NAME_FORMAT_TABLE:
61
+ format, np_array_is_matching = m.format_descriptor_format_buffer_info_equiv(
62
+ other_cpp_name, np_array
63
+ )
64
+ assert format == expected_format
65
+ if other_cpp_name == cpp_name:
66
+ assert np_array_is_matching
67
+ else:
68
+ assert not np_array_is_matching
69
+
70
+
71
+ def test_from_python():
72
+ with pytest.raises(RuntimeError) as excinfo:
73
+ m.Matrix(np.array([1, 2, 3])) # trying to assign a 1D array
74
+ assert str(excinfo.value) == "Incompatible buffer format!"
75
+
76
+ m3 = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
77
+ m4 = m.Matrix(m3)
78
+
79
+ for i in range(m4.rows()):
80
+ for j in range(m4.cols()):
81
+ assert m3[i, j] == m4[i, j]
82
+
83
+ cstats = ConstructorStats.get(m.Matrix)
84
+ assert cstats.alive() == 1
85
+ del m3, m4
86
+ assert cstats.alive() == 0
87
+ assert cstats.values() == ["2x3 matrix"]
88
+ assert cstats.copy_constructions == 0
89
+ # assert cstats.move_constructions >= 0 # Don't invoke any
90
+ assert cstats.copy_assignments == 0
91
+ assert cstats.move_assignments == 0
92
+
93
+
94
+ # https://foss.heptapod.net/pypy/pypy/-/issues/2444
95
+ # TODO: fix on recent PyPy
96
+ @pytest.mark.xfail(
97
+ env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
98
+ )
99
+ def test_to_python():
100
+ mat = m.Matrix(5, 4)
101
+ assert memoryview(mat).shape == (5, 4)
102
+
103
+ assert mat[2, 3] == 0
104
+ mat[2, 3] = 4.0
105
+ mat[3, 2] = 7.0
106
+ assert mat[2, 3] == 4
107
+ assert mat[3, 2] == 7
108
+ assert struct.unpack_from("f", mat, (3 * 4 + 2) * 4) == (7,)
109
+ assert struct.unpack_from("f", mat, (2 * 4 + 3) * 4) == (4,)
110
+
111
+ mat2 = np.array(mat, copy=False)
112
+ assert mat2.shape == (5, 4)
113
+ assert abs(mat2).sum() == 11
114
+ assert mat2[2, 3] == 4
115
+ assert mat2[3, 2] == 7
116
+ mat2[2, 3] = 5
117
+ assert mat2[2, 3] == 5
118
+
119
+ cstats = ConstructorStats.get(m.Matrix)
120
+ assert cstats.alive() == 1
121
+ del mat
122
+ pytest.gc_collect()
123
+ assert cstats.alive() == 1
124
+ del mat2 # holds a mat reference
125
+ pytest.gc_collect()
126
+ assert cstats.alive() == 0
127
+ assert cstats.values() == ["5x4 matrix"]
128
+ assert cstats.copy_constructions == 0
129
+ # assert cstats.move_constructions >= 0 # Don't invoke any
130
+ assert cstats.copy_assignments == 0
131
+ assert cstats.move_assignments == 0
132
+
133
+
134
+ def test_inherited_protocol():
135
+ """SquareMatrix is derived from Matrix and inherits the buffer protocol"""
136
+
137
+ matrix = m.SquareMatrix(5)
138
+ assert memoryview(matrix).shape == (5, 5)
139
+ assert np.asarray(matrix).shape == (5, 5)
140
+
141
+
142
+ def test_pointer_to_member_fn():
143
+ for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]:
144
+ buf = cls()
145
+ buf.value = 0x12345678
146
+ value = struct.unpack("i", bytearray(buf))[0]
147
+ assert value == 0x12345678
148
+
149
+
150
+ def test_readonly_buffer():
151
+ buf = m.BufferReadOnly(0x64)
152
+ view = memoryview(buf)
153
+ assert view[0] == 0x64
154
+ assert view.readonly
155
+ with pytest.raises(TypeError):
156
+ view[0] = 0
157
+
158
+
159
+ def test_selective_readonly_buffer():
160
+ buf = m.BufferReadOnlySelect()
161
+
162
+ memoryview(buf)[0] = 0x64
163
+ assert buf.value == 0x64
164
+
165
+ io.BytesIO(b"A").readinto(buf)
166
+ assert buf.value == ord(b"A")
167
+
168
+ buf.readonly = True
169
+ with pytest.raises(TypeError):
170
+ memoryview(buf)[0] = 0
171
+ with pytest.raises(TypeError):
172
+ io.BytesIO(b"1").readinto(buf)
173
+
174
+
175
+ def test_ctypes_array_1d():
176
+ char1d = (ctypes.c_char * 10)()
177
+ int1d = (ctypes.c_int * 15)()
178
+ long1d = (ctypes.c_long * 7)()
179
+
180
+ for carray in (char1d, int1d, long1d):
181
+ info = m.get_buffer_info(carray)
182
+ assert info.itemsize == ctypes.sizeof(carray._type_)
183
+ assert info.size == len(carray)
184
+ assert info.ndim == 1
185
+ assert info.shape == [info.size]
186
+ assert info.strides == [info.itemsize]
187
+ assert not info.readonly
188
+
189
+
190
+ def test_ctypes_array_2d():
191
+ char2d = ((ctypes.c_char * 10) * 4)()
192
+ int2d = ((ctypes.c_int * 15) * 3)()
193
+ long2d = ((ctypes.c_long * 7) * 2)()
194
+
195
+ for carray in (char2d, int2d, long2d):
196
+ info = m.get_buffer_info(carray)
197
+ assert info.itemsize == ctypes.sizeof(carray[0]._type_)
198
+ assert info.size == len(carray) * len(carray[0])
199
+ assert info.ndim == 2
200
+ assert info.shape == [len(carray), len(carray[0])]
201
+ assert info.strides == [info.itemsize * len(carray[0]), info.itemsize]
202
+ assert not info.readonly
203
+
204
+
205
+ def test_ctypes_from_buffer():
206
+ test_pystr = b"0123456789"
207
+ for pyarray in (test_pystr, bytearray(test_pystr)):
208
+ pyinfo = m.get_buffer_info(pyarray)
209
+
210
+ if pyinfo.readonly:
211
+ cbytes = (ctypes.c_char * len(pyarray)).from_buffer_copy(pyarray)
212
+ cinfo = m.get_buffer_info(cbytes)
213
+ else:
214
+ cbytes = (ctypes.c_char * len(pyarray)).from_buffer(pyarray)
215
+ cinfo = m.get_buffer_info(cbytes)
216
+
217
+ assert cinfo.size == pyinfo.size
218
+ assert cinfo.ndim == pyinfo.ndim
219
+ assert cinfo.shape == pyinfo.shape
220
+ assert cinfo.strides == pyinfo.strides
221
+ assert not cinfo.readonly
222
+
223
+
224
+ def test_buffer_docstring():
225
+ assert (
226
+ m.get_buffer_info.__doc__.strip()
227
+ == "get_buffer_info(arg0: Buffer) -> pybind11_tests.buffers.buffer_info"
228
+ )
third_party/CityFlow/extern/pybind11/tests/test_builtin_casters.cpp CHANGED
@@ -1,392 +1,392 @@
1
- /*
2
- tests/test_builtin_casters.cpp -- Casters available without any additional headers
3
-
4
- Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include <pybind11/complex.h>
11
-
12
- #include "pybind11_tests.h"
13
-
14
- struct ConstRefCasted {
15
- int tag;
16
- };
17
-
18
- PYBIND11_NAMESPACE_BEGIN(pybind11)
19
- PYBIND11_NAMESPACE_BEGIN(detail)
20
- template <>
21
- class type_caster<ConstRefCasted> {
22
- public:
23
- static constexpr auto name = const_name<ConstRefCasted>();
24
-
25
- // Input is unimportant, a new value will always be constructed based on the
26
- // cast operator.
27
- bool load(handle, bool) { return true; }
28
-
29
- explicit operator ConstRefCasted &&() {
30
- value = {1};
31
- // NOLINTNEXTLINE(performance-move-const-arg)
32
- return std::move(value);
33
- }
34
- explicit operator ConstRefCasted &() {
35
- value = {2};
36
- return value;
37
- }
38
- explicit operator ConstRefCasted *() {
39
- value = {3};
40
- return &value;
41
- }
42
-
43
- explicit operator const ConstRefCasted &() {
44
- value = {4};
45
- return value;
46
- }
47
- explicit operator const ConstRefCasted *() {
48
- value = {5};
49
- return &value;
50
- }
51
-
52
- // custom cast_op to explicitly propagate types to the conversion operators.
53
- template <typename T_>
54
- using cast_op_type =
55
- /// const
56
- conditional_t<
57
- std::is_same<remove_reference_t<T_>, const ConstRefCasted *>::value,
58
- const ConstRefCasted *,
59
- conditional_t<
60
- std::is_same<T_, const ConstRefCasted &>::value,
61
- const ConstRefCasted &,
62
- /// non-const
63
- conditional_t<std::is_same<remove_reference_t<T_>, ConstRefCasted *>::value,
64
- ConstRefCasted *,
65
- conditional_t<std::is_same<T_, ConstRefCasted &>::value,
66
- ConstRefCasted &,
67
- /* else */ ConstRefCasted &&>>>>;
68
-
69
- private:
70
- ConstRefCasted value = {0};
71
- };
72
- PYBIND11_NAMESPACE_END(detail)
73
- PYBIND11_NAMESPACE_END(pybind11)
74
-
75
- TEST_SUBMODULE(builtin_casters, m) {
76
- PYBIND11_WARNING_PUSH
77
- PYBIND11_WARNING_DISABLE_MSVC(4127)
78
-
79
- // test_simple_string
80
- m.def("string_roundtrip", [](const char *s) { return s; });
81
-
82
- // test_unicode_conversion
83
- // Some test characters in utf16 and utf32 encodings. The last one (the 𝐀) contains a null
84
- // byte
85
- char32_t a32 = 0x61 /*a*/, z32 = 0x7a /*z*/, ib32 = 0x203d /*‽*/, cake32 = 0x1f382 /*🎂*/,
86
- mathbfA32 = 0x1d400 /*𝐀*/;
87
- char16_t b16 = 0x62 /*b*/, z16 = 0x7a, ib16 = 0x203d, cake16_1 = 0xd83c, cake16_2 = 0xdf82,
88
- mathbfA16_1 = 0xd835, mathbfA16_2 = 0xdc00;
89
- std::wstring wstr;
90
- wstr.push_back(0x61); // a
91
- wstr.push_back(0x2e18); // ⸘
92
- if (sizeof(wchar_t) == 2) {
93
- wstr.push_back(mathbfA16_1);
94
- wstr.push_back(mathbfA16_2);
95
- } // 𝐀, utf16
96
- else {
97
- wstr.push_back((wchar_t) mathbfA32);
98
- } // 𝐀, utf32
99
- wstr.push_back(0x7a); // z
100
-
101
- m.def("good_utf8_string", []() {
102
- return std::string((const char *) u8"Say utf8\u203d \U0001f382 \U0001d400");
103
- }); // Say utf8‽ 🎂 𝐀
104
- m.def("good_utf16_string", [=]() {
105
- return std::u16string({b16, ib16, cake16_1, cake16_2, mathbfA16_1, mathbfA16_2, z16});
106
- }); // b‽🎂𝐀z
107
- m.def("good_utf32_string", [=]() {
108
- return std::u32string({a32, mathbfA32, cake32, ib32, z32});
109
- }); // a𝐀🎂‽z
110
- m.def("good_wchar_string", [=]() { return wstr; }); // a‽𝐀z
111
- m.def("bad_utf8_string", []() {
112
- return std::string("abc\xd0"
113
- "def");
114
- });
115
- m.def("bad_utf16_string", [=]() { return std::u16string({b16, char16_t(0xd800), z16}); });
116
- // Under Python 2.7, invalid unicode UTF-32 characters didn't appear to trigger
117
- // UnicodeDecodeError
118
- m.def("bad_utf32_string", [=]() { return std::u32string({a32, char32_t(0xd800), z32}); });
119
- if (sizeof(wchar_t) == 2) {
120
- m.def("bad_wchar_string", [=]() {
121
- return std::wstring({wchar_t(0x61), wchar_t(0xd800)});
122
- });
123
- }
124
- m.def("u8_Z", []() -> char { return 'Z'; });
125
- m.def("u8_eacute", []() -> char { return '\xe9'; });
126
- m.def("u16_ibang", [=]() -> char16_t { return ib16; });
127
- m.def("u32_mathbfA", [=]() -> char32_t { return mathbfA32; });
128
- m.def("wchar_heart", []() -> wchar_t { return 0x2665; });
129
-
130
- // test_single_char_arguments
131
- m.attr("wchar_size") = py::cast(sizeof(wchar_t));
132
- m.def("ord_char", [](char c) -> int { return static_cast<unsigned char>(c); });
133
- m.def("ord_char_lv", [](char &c) -> int { return static_cast<unsigned char>(c); });
134
- m.def("ord_char16", [](char16_t c) -> uint16_t { return c; });
135
- m.def("ord_char16_lv", [](char16_t &c) -> uint16_t { return c; });
136
- m.def("ord_char32", [](char32_t c) -> uint32_t { return c; });
137
- m.def("ord_wchar", [](wchar_t c) -> int { return c; });
138
-
139
- // test_bytes_to_string
140
- m.def("strlen", [](char *s) { return strlen(s); });
141
- m.def("string_length", [](const std::string &s) { return s.length(); });
142
-
143
- #ifdef PYBIND11_HAS_U8STRING
144
- m.attr("has_u8string") = true;
145
- m.def("good_utf8_u8string", []() {
146
- return std::u8string(u8"Say utf8\u203d \U0001f382 \U0001d400");
147
- }); // Say utf8‽ 🎂 𝐀
148
- m.def("bad_utf8_u8string", []() {
149
- return std::u8string((const char8_t *) "abc\xd0"
150
- "def");
151
- });
152
-
153
- m.def("u8_char8_Z", []() -> char8_t { return u8'Z'; });
154
-
155
- // test_single_char_arguments
156
- m.def("ord_char8", [](char8_t c) -> int { return static_cast<unsigned char>(c); });
157
- m.def("ord_char8_lv", [](char8_t &c) -> int { return static_cast<unsigned char>(c); });
158
- #endif
159
-
160
- // test_string_view
161
- #ifdef PYBIND11_HAS_STRING_VIEW
162
- m.attr("has_string_view") = true;
163
- m.def("string_view_print", [](std::string_view s) { py::print(s, s.size()); });
164
- m.def("string_view16_print", [](std::u16string_view s) { py::print(s, s.size()); });
165
- m.def("string_view32_print", [](std::u32string_view s) { py::print(s, s.size()); });
166
- m.def("string_view_chars", [](std::string_view s) {
167
- py::list l;
168
- for (auto c : s) {
169
- l.append((std::uint8_t) c);
170
- }
171
- return l;
172
- });
173
- m.def("string_view16_chars", [](std::u16string_view s) {
174
- py::list l;
175
- for (auto c : s) {
176
- l.append((int) c);
177
- }
178
- return l;
179
- });
180
- m.def("string_view32_chars", [](std::u32string_view s) {
181
- py::list l;
182
- for (auto c : s) {
183
- l.append((int) c);
184
- }
185
- return l;
186
- });
187
- m.def("string_view_return",
188
- []() { return std::string_view((const char *) u8"utf8 secret \U0001f382"); });
189
- m.def("string_view16_return",
190
- []() { return std::u16string_view(u"utf16 secret \U0001f382"); });
191
- m.def("string_view32_return",
192
- []() { return std::u32string_view(U"utf32 secret \U0001f382"); });
193
-
194
- // The inner lambdas here are to also test implicit conversion
195
- using namespace std::literals;
196
- m.def("string_view_bytes",
197
- []() { return [](py::bytes b) { return b; }("abc \x80\x80 def"sv); });
198
- m.def("string_view_str",
199
- []() { return [](py::str s) { return s; }("abc \342\200\275 def"sv); });
200
- m.def("string_view_from_bytes",
201
- [](const py::bytes &b) { return [](std::string_view s) { return s; }(b); });
202
- m.def("string_view_memoryview", []() {
203
- static constexpr auto val = "Have some \360\237\216\202"sv;
204
- return py::memoryview::from_memory(val);
205
- });
206
-
207
- # ifdef PYBIND11_HAS_U8STRING
208
- m.def("string_view8_print", [](std::u8string_view s) { py::print(s, s.size()); });
209
- m.def("string_view8_chars", [](std::u8string_view s) {
210
- py::list l;
211
- for (auto c : s)
212
- l.append((std::uint8_t) c);
213
- return l;
214
- });
215
- m.def("string_view8_return", []() { return std::u8string_view(u8"utf8 secret \U0001f382"); });
216
- m.def("string_view8_str", []() { return py::str{std::u8string_view{u8"abc ‽ def"}}; });
217
- # endif
218
-
219
- struct TypeWithBothOperatorStringAndStringView {
220
- // NOLINTNEXTLINE(google-explicit-constructor)
221
- operator std::string() const { return "success"; }
222
- // NOLINTNEXTLINE(google-explicit-constructor)
223
- operator std::string_view() const { return "failure"; }
224
- };
225
- m.def("bytes_from_type_with_both_operator_string_and_string_view",
226
- []() { return py::bytes(TypeWithBothOperatorStringAndStringView()); });
227
- m.def("str_from_type_with_both_operator_string_and_string_view",
228
- []() { return py::str(TypeWithBothOperatorStringAndStringView()); });
229
- #endif
230
-
231
- // test_integer_casting
232
- m.def("i32_str", [](std::int32_t v) { return std::to_string(v); });
233
- m.def("u32_str", [](std::uint32_t v) { return std::to_string(v); });
234
- m.def("i64_str", [](std::int64_t v) { return std::to_string(v); });
235
- m.def("u64_str", [](std::uint64_t v) { return std::to_string(v); });
236
-
237
- // test_int_convert
238
- m.def("int_passthrough", [](int arg) { return arg; });
239
- m.def(
240
- "int_passthrough_noconvert", [](int arg) { return arg; }, py::arg{}.noconvert());
241
-
242
- // test_tuple
243
- m.def(
244
- "pair_passthrough",
245
- [](const std::pair<bool, std::string> &input) {
246
- return std::make_pair(input.second, input.first);
247
- },
248
- "Return a pair in reversed order");
249
- m.def(
250
- "tuple_passthrough",
251
- [](std::tuple<bool, std::string, int> input) {
252
- return std::make_tuple(std::get<2>(input), std::get<1>(input), std::get<0>(input));
253
- },
254
- "Return a triple in reversed order");
255
- m.def("empty_tuple", []() { return std::tuple<>(); });
256
- static std::pair<RValueCaster, RValueCaster> lvpair;
257
- static std::tuple<RValueCaster, RValueCaster, RValueCaster> lvtuple;
258
- static std::pair<RValueCaster, std::tuple<RValueCaster, std::pair<RValueCaster, RValueCaster>>>
259
- lvnested;
260
- m.def("rvalue_pair", []() { return std::make_pair(RValueCaster{}, RValueCaster{}); });
261
- m.def("lvalue_pair", []() -> const decltype(lvpair) & { return lvpair; });
262
- m.def("rvalue_tuple",
263
- []() { return std::make_tuple(RValueCaster{}, RValueCaster{}, RValueCaster{}); });
264
- m.def("lvalue_tuple", []() -> const decltype(lvtuple) & { return lvtuple; });
265
- m.def("rvalue_nested", []() {
266
- return std::make_pair(
267
- RValueCaster{},
268
- std::make_tuple(RValueCaster{}, std::make_pair(RValueCaster{}, RValueCaster{})));
269
- });
270
- m.def("lvalue_nested", []() -> const decltype(lvnested) & { return lvnested; });
271
-
272
- m.def(
273
- "int_string_pair",
274
- []() {
275
- // Using no-destructor idiom to side-step warnings from overzealous compilers.
276
- static auto *int_string_pair = new std::pair<int, std::string>{2, "items"};
277
- return int_string_pair;
278
- },
279
- py::return_value_policy::reference);
280
-
281
- // test_builtins_cast_return_none
282
- m.def("return_none_string", []() -> std::string * { return nullptr; });
283
- m.def("return_none_char", []() -> const char * { return nullptr; });
284
- m.def("return_none_bool", []() -> bool * { return nullptr; });
285
- m.def("return_none_int", []() -> int * { return nullptr; });
286
- m.def("return_none_float", []() -> float * { return nullptr; });
287
- m.def("return_none_pair", []() -> std::pair<int, int> * { return nullptr; });
288
-
289
- // test_none_deferred
290
- m.def("defer_none_cstring", [](char *) { return false; });
291
- m.def("defer_none_cstring", [](const py::none &) { return true; });
292
- m.def("defer_none_custom", [](UserType *) { return false; });
293
- m.def("defer_none_custom", [](const py::none &) { return true; });
294
- m.def("nodefer_none_void", [](void *) { return true; });
295
- m.def("nodefer_none_void", [](const py::none &) { return false; });
296
-
297
- // test_void_caster
298
- m.def("load_nullptr_t", [](std::nullptr_t) {}); // not useful, but it should still compile
299
- m.def("cast_nullptr_t", []() { return std::nullptr_t{}; });
300
-
301
- // [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
302
-
303
- // test_bool_caster
304
- m.def("bool_passthrough", [](bool arg) { return arg; });
305
- m.def(
306
- "bool_passthrough_noconvert", [](bool arg) { return arg; }, py::arg{}.noconvert());
307
-
308
- // TODO: This should be disabled and fixed in future Intel compilers
309
- #if !defined(__INTEL_COMPILER)
310
- // Test "bool_passthrough_noconvert" again, but using () instead of {} to construct py::arg
311
- // When compiled with the Intel compiler, this results in segmentation faults when importing
312
- // the module. Tested with icc (ICC) 2021.1 Beta 20200827, this should be tested again when
313
- // a newer version of icc is available.
314
- m.def(
315
- "bool_passthrough_noconvert2", [](bool arg) { return arg; }, py::arg().noconvert());
316
- #endif
317
-
318
- // test_reference_wrapper
319
- m.def("refwrap_builtin", [](std::reference_wrapper<int> p) { return 10 * p.get(); });
320
- m.def("refwrap_usertype", [](std::reference_wrapper<UserType> p) { return p.get().value(); });
321
- m.def("refwrap_usertype_const",
322
- [](std::reference_wrapper<const UserType> p) { return p.get().value(); });
323
-
324
- m.def("refwrap_lvalue", []() -> std::reference_wrapper<UserType> {
325
- static UserType x(1);
326
- return std::ref(x);
327
- });
328
- m.def("refwrap_lvalue_const", []() -> std::reference_wrapper<const UserType> {
329
- static UserType x(1);
330
- return std::cref(x);
331
- });
332
-
333
- // Not currently supported (std::pair caster has return-by-value cast operator);
334
- // triggers static_assert failure.
335
- // m.def("refwrap_pair", [](std::reference_wrapper<std::pair<int, int>>) { });
336
-
337
- m.def(
338
- "refwrap_list",
339
- [](bool copy) {
340
- static IncType x1(1), x2(2);
341
- py::list l;
342
- for (const auto &f : {std::ref(x1), std::ref(x2)}) {
343
- l.append(py::cast(
344
- f, copy ? py::return_value_policy::copy : py::return_value_policy::reference));
345
- }
346
- return l;
347
- },
348
- "copy"_a);
349
-
350
- m.def("refwrap_iiw", [](const IncType &w) { return w.value(); });
351
- m.def("refwrap_call_iiw", [](IncType &w, const py::function &f) {
352
- py::list l;
353
- l.append(f(std::ref(w)));
354
- l.append(f(std::cref(w)));
355
- IncType x(w.value());
356
- l.append(f(std::ref(x)));
357
- IncType y(w.value());
358
- auto r3 = std::ref(y);
359
- l.append(f(r3));
360
- return l;
361
- });
362
-
363
- // test_complex
364
- m.def("complex_cast", [](float x) { return "{}"_s.format(x); });
365
- m.def("complex_cast",
366
- [](std::complex<float> x) { return "({}, {})"_s.format(x.real(), x.imag()); });
367
-
368
- // test int vs. long (Python 2)
369
- m.def("int_cast", []() { return (int) 42; });
370
- m.def("long_cast", []() { return (long) 42; });
371
- m.def("longlong_cast", []() { return ULLONG_MAX; });
372
-
373
- /// test void* cast operator
374
- m.def("test_void_caster", []() -> bool {
375
- void *v = (void *) 0xabcd;
376
- py::object o = py::cast(v);
377
- return py::cast<void *>(o) == v;
378
- });
379
-
380
- // Tests const/non-const propagation in cast_op.
381
- m.def("takes", [](ConstRefCasted x) { return x.tag; });
382
- m.def("takes_move", [](ConstRefCasted &&x) { return x.tag; });
383
- m.def("takes_ptr", [](ConstRefCasted *x) { return x->tag; });
384
- m.def("takes_ref", [](ConstRefCasted &x) { return x.tag; });
385
- m.def("takes_ref_wrap", [](std::reference_wrapper<ConstRefCasted> x) { return x.get().tag; });
386
- m.def("takes_const_ptr", [](const ConstRefCasted *x) { return x->tag; });
387
- m.def("takes_const_ref", [](const ConstRefCasted &x) { return x.tag; });
388
- m.def("takes_const_ref_wrap",
389
- [](std::reference_wrapper<const ConstRefCasted> x) { return x.get().tag; });
390
-
391
- PYBIND11_WARNING_POP
392
- }
 
1
+ /*
2
+ tests/test_builtin_casters.cpp -- Casters available without any additional headers
3
+
4
+ Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include <pybind11/complex.h>
11
+
12
+ #include "pybind11_tests.h"
13
+
14
+ struct ConstRefCasted {
15
+ int tag;
16
+ };
17
+
18
+ PYBIND11_NAMESPACE_BEGIN(pybind11)
19
+ PYBIND11_NAMESPACE_BEGIN(detail)
20
+ template <>
21
+ class type_caster<ConstRefCasted> {
22
+ public:
23
+ static constexpr auto name = const_name<ConstRefCasted>();
24
+
25
+ // Input is unimportant, a new value will always be constructed based on the
26
+ // cast operator.
27
+ bool load(handle, bool) { return true; }
28
+
29
+ explicit operator ConstRefCasted &&() {
30
+ value = {1};
31
+ // NOLINTNEXTLINE(performance-move-const-arg)
32
+ return std::move(value);
33
+ }
34
+ explicit operator ConstRefCasted &() {
35
+ value = {2};
36
+ return value;
37
+ }
38
+ explicit operator ConstRefCasted *() {
39
+ value = {3};
40
+ return &value;
41
+ }
42
+
43
+ explicit operator const ConstRefCasted &() {
44
+ value = {4};
45
+ return value;
46
+ }
47
+ explicit operator const ConstRefCasted *() {
48
+ value = {5};
49
+ return &value;
50
+ }
51
+
52
+ // custom cast_op to explicitly propagate types to the conversion operators.
53
+ template <typename T_>
54
+ using cast_op_type =
55
+ /// const
56
+ conditional_t<
57
+ std::is_same<remove_reference_t<T_>, const ConstRefCasted *>::value,
58
+ const ConstRefCasted *,
59
+ conditional_t<
60
+ std::is_same<T_, const ConstRefCasted &>::value,
61
+ const ConstRefCasted &,
62
+ /// non-const
63
+ conditional_t<std::is_same<remove_reference_t<T_>, ConstRefCasted *>::value,
64
+ ConstRefCasted *,
65
+ conditional_t<std::is_same<T_, ConstRefCasted &>::value,
66
+ ConstRefCasted &,
67
+ /* else */ ConstRefCasted &&>>>>;
68
+
69
+ private:
70
+ ConstRefCasted value = {0};
71
+ };
72
+ PYBIND11_NAMESPACE_END(detail)
73
+ PYBIND11_NAMESPACE_END(pybind11)
74
+
75
+ TEST_SUBMODULE(builtin_casters, m) {
76
+ PYBIND11_WARNING_PUSH
77
+ PYBIND11_WARNING_DISABLE_MSVC(4127)
78
+
79
+ // test_simple_string
80
+ m.def("string_roundtrip", [](const char *s) { return s; });
81
+
82
+ // test_unicode_conversion
83
+ // Some test characters in utf16 and utf32 encodings. The last one (the 𝐀) contains a null
84
+ // byte
85
+ char32_t a32 = 0x61 /*a*/, z32 = 0x7a /*z*/, ib32 = 0x203d /*‽*/, cake32 = 0x1f382 /*🎂*/,
86
+ mathbfA32 = 0x1d400 /*𝐀*/;
87
+ char16_t b16 = 0x62 /*b*/, z16 = 0x7a, ib16 = 0x203d, cake16_1 = 0xd83c, cake16_2 = 0xdf82,
88
+ mathbfA16_1 = 0xd835, mathbfA16_2 = 0xdc00;
89
+ std::wstring wstr;
90
+ wstr.push_back(0x61); // a
91
+ wstr.push_back(0x2e18); // ⸘
92
+ if (sizeof(wchar_t) == 2) {
93
+ wstr.push_back(mathbfA16_1);
94
+ wstr.push_back(mathbfA16_2);
95
+ } // 𝐀, utf16
96
+ else {
97
+ wstr.push_back((wchar_t) mathbfA32);
98
+ } // 𝐀, utf32
99
+ wstr.push_back(0x7a); // z
100
+
101
+ m.def("good_utf8_string", []() {
102
+ return std::string((const char *) u8"Say utf8\u203d \U0001f382 \U0001d400");
103
+ }); // Say utf8‽ 🎂 𝐀
104
+ m.def("good_utf16_string", [=]() {
105
+ return std::u16string({b16, ib16, cake16_1, cake16_2, mathbfA16_1, mathbfA16_2, z16});
106
+ }); // b‽🎂𝐀z
107
+ m.def("good_utf32_string", [=]() {
108
+ return std::u32string({a32, mathbfA32, cake32, ib32, z32});
109
+ }); // a𝐀🎂‽z
110
+ m.def("good_wchar_string", [=]() { return wstr; }); // a‽𝐀z
111
+ m.def("bad_utf8_string", []() {
112
+ return std::string("abc\xd0"
113
+ "def");
114
+ });
115
+ m.def("bad_utf16_string", [=]() { return std::u16string({b16, char16_t(0xd800), z16}); });
116
+ // Under Python 2.7, invalid unicode UTF-32 characters didn't appear to trigger
117
+ // UnicodeDecodeError
118
+ m.def("bad_utf32_string", [=]() { return std::u32string({a32, char32_t(0xd800), z32}); });
119
+ if (sizeof(wchar_t) == 2) {
120
+ m.def("bad_wchar_string", [=]() {
121
+ return std::wstring({wchar_t(0x61), wchar_t(0xd800)});
122
+ });
123
+ }
124
+ m.def("u8_Z", []() -> char { return 'Z'; });
125
+ m.def("u8_eacute", []() -> char { return '\xe9'; });
126
+ m.def("u16_ibang", [=]() -> char16_t { return ib16; });
127
+ m.def("u32_mathbfA", [=]() -> char32_t { return mathbfA32; });
128
+ m.def("wchar_heart", []() -> wchar_t { return 0x2665; });
129
+
130
+ // test_single_char_arguments
131
+ m.attr("wchar_size") = py::cast(sizeof(wchar_t));
132
+ m.def("ord_char", [](char c) -> int { return static_cast<unsigned char>(c); });
133
+ m.def("ord_char_lv", [](char &c) -> int { return static_cast<unsigned char>(c); });
134
+ m.def("ord_char16", [](char16_t c) -> uint16_t { return c; });
135
+ m.def("ord_char16_lv", [](char16_t &c) -> uint16_t { return c; });
136
+ m.def("ord_char32", [](char32_t c) -> uint32_t { return c; });
137
+ m.def("ord_wchar", [](wchar_t c) -> int { return c; });
138
+
139
+ // test_bytes_to_string
140
+ m.def("strlen", [](char *s) { return strlen(s); });
141
+ m.def("string_length", [](const std::string &s) { return s.length(); });
142
+
143
+ #ifdef PYBIND11_HAS_U8STRING
144
+ m.attr("has_u8string") = true;
145
+ m.def("good_utf8_u8string", []() {
146
+ return std::u8string(u8"Say utf8\u203d \U0001f382 \U0001d400");
147
+ }); // Say utf8‽ 🎂 𝐀
148
+ m.def("bad_utf8_u8string", []() {
149
+ return std::u8string((const char8_t *) "abc\xd0"
150
+ "def");
151
+ });
152
+
153
+ m.def("u8_char8_Z", []() -> char8_t { return u8'Z'; });
154
+
155
+ // test_single_char_arguments
156
+ m.def("ord_char8", [](char8_t c) -> int { return static_cast<unsigned char>(c); });
157
+ m.def("ord_char8_lv", [](char8_t &c) -> int { return static_cast<unsigned char>(c); });
158
+ #endif
159
+
160
+ // test_string_view
161
+ #ifdef PYBIND11_HAS_STRING_VIEW
162
+ m.attr("has_string_view") = true;
163
+ m.def("string_view_print", [](std::string_view s) { py::print(s, s.size()); });
164
+ m.def("string_view16_print", [](std::u16string_view s) { py::print(s, s.size()); });
165
+ m.def("string_view32_print", [](std::u32string_view s) { py::print(s, s.size()); });
166
+ m.def("string_view_chars", [](std::string_view s) {
167
+ py::list l;
168
+ for (auto c : s) {
169
+ l.append((std::uint8_t) c);
170
+ }
171
+ return l;
172
+ });
173
+ m.def("string_view16_chars", [](std::u16string_view s) {
174
+ py::list l;
175
+ for (auto c : s) {
176
+ l.append((int) c);
177
+ }
178
+ return l;
179
+ });
180
+ m.def("string_view32_chars", [](std::u32string_view s) {
181
+ py::list l;
182
+ for (auto c : s) {
183
+ l.append((int) c);
184
+ }
185
+ return l;
186
+ });
187
+ m.def("string_view_return",
188
+ []() { return std::string_view((const char *) u8"utf8 secret \U0001f382"); });
189
+ m.def("string_view16_return",
190
+ []() { return std::u16string_view(u"utf16 secret \U0001f382"); });
191
+ m.def("string_view32_return",
192
+ []() { return std::u32string_view(U"utf32 secret \U0001f382"); });
193
+
194
+ // The inner lambdas here are to also test implicit conversion
195
+ using namespace std::literals;
196
+ m.def("string_view_bytes",
197
+ []() { return [](py::bytes b) { return b; }("abc \x80\x80 def"sv); });
198
+ m.def("string_view_str",
199
+ []() { return [](py::str s) { return s; }("abc \342\200\275 def"sv); });
200
+ m.def("string_view_from_bytes",
201
+ [](const py::bytes &b) { return [](std::string_view s) { return s; }(b); });
202
+ m.def("string_view_memoryview", []() {
203
+ static constexpr auto val = "Have some \360\237\216\202"sv;
204
+ return py::memoryview::from_memory(val);
205
+ });
206
+
207
+ # ifdef PYBIND11_HAS_U8STRING
208
+ m.def("string_view8_print", [](std::u8string_view s) { py::print(s, s.size()); });
209
+ m.def("string_view8_chars", [](std::u8string_view s) {
210
+ py::list l;
211
+ for (auto c : s)
212
+ l.append((std::uint8_t) c);
213
+ return l;
214
+ });
215
+ m.def("string_view8_return", []() { return std::u8string_view(u8"utf8 secret \U0001f382"); });
216
+ m.def("string_view8_str", []() { return py::str{std::u8string_view{u8"abc ‽ def"}}; });
217
+ # endif
218
+
219
+ struct TypeWithBothOperatorStringAndStringView {
220
+ // NOLINTNEXTLINE(google-explicit-constructor)
221
+ operator std::string() const { return "success"; }
222
+ // NOLINTNEXTLINE(google-explicit-constructor)
223
+ operator std::string_view() const { return "failure"; }
224
+ };
225
+ m.def("bytes_from_type_with_both_operator_string_and_string_view",
226
+ []() { return py::bytes(TypeWithBothOperatorStringAndStringView()); });
227
+ m.def("str_from_type_with_both_operator_string_and_string_view",
228
+ []() { return py::str(TypeWithBothOperatorStringAndStringView()); });
229
+ #endif
230
+
231
+ // test_integer_casting
232
+ m.def("i32_str", [](std::int32_t v) { return std::to_string(v); });
233
+ m.def("u32_str", [](std::uint32_t v) { return std::to_string(v); });
234
+ m.def("i64_str", [](std::int64_t v) { return std::to_string(v); });
235
+ m.def("u64_str", [](std::uint64_t v) { return std::to_string(v); });
236
+
237
+ // test_int_convert
238
+ m.def("int_passthrough", [](int arg) { return arg; });
239
+ m.def(
240
+ "int_passthrough_noconvert", [](int arg) { return arg; }, py::arg{}.noconvert());
241
+
242
+ // test_tuple
243
+ m.def(
244
+ "pair_passthrough",
245
+ [](const std::pair<bool, std::string> &input) {
246
+ return std::make_pair(input.second, input.first);
247
+ },
248
+ "Return a pair in reversed order");
249
+ m.def(
250
+ "tuple_passthrough",
251
+ [](std::tuple<bool, std::string, int> input) {
252
+ return std::make_tuple(std::get<2>(input), std::get<1>(input), std::get<0>(input));
253
+ },
254
+ "Return a triple in reversed order");
255
+ m.def("empty_tuple", []() { return std::tuple<>(); });
256
+ static std::pair<RValueCaster, RValueCaster> lvpair;
257
+ static std::tuple<RValueCaster, RValueCaster, RValueCaster> lvtuple;
258
+ static std::pair<RValueCaster, std::tuple<RValueCaster, std::pair<RValueCaster, RValueCaster>>>
259
+ lvnested;
260
+ m.def("rvalue_pair", []() { return std::make_pair(RValueCaster{}, RValueCaster{}); });
261
+ m.def("lvalue_pair", []() -> const decltype(lvpair) & { return lvpair; });
262
+ m.def("rvalue_tuple",
263
+ []() { return std::make_tuple(RValueCaster{}, RValueCaster{}, RValueCaster{}); });
264
+ m.def("lvalue_tuple", []() -> const decltype(lvtuple) & { return lvtuple; });
265
+ m.def("rvalue_nested", []() {
266
+ return std::make_pair(
267
+ RValueCaster{},
268
+ std::make_tuple(RValueCaster{}, std::make_pair(RValueCaster{}, RValueCaster{})));
269
+ });
270
+ m.def("lvalue_nested", []() -> const decltype(lvnested) & { return lvnested; });
271
+
272
+ m.def(
273
+ "int_string_pair",
274
+ []() {
275
+ // Using no-destructor idiom to side-step warnings from overzealous compilers.
276
+ static auto *int_string_pair = new std::pair<int, std::string>{2, "items"};
277
+ return int_string_pair;
278
+ },
279
+ py::return_value_policy::reference);
280
+
281
+ // test_builtins_cast_return_none
282
+ m.def("return_none_string", []() -> std::string * { return nullptr; });
283
+ m.def("return_none_char", []() -> const char * { return nullptr; });
284
+ m.def("return_none_bool", []() -> bool * { return nullptr; });
285
+ m.def("return_none_int", []() -> int * { return nullptr; });
286
+ m.def("return_none_float", []() -> float * { return nullptr; });
287
+ m.def("return_none_pair", []() -> std::pair<int, int> * { return nullptr; });
288
+
289
+ // test_none_deferred
290
+ m.def("defer_none_cstring", [](char *) { return false; });
291
+ m.def("defer_none_cstring", [](const py::none &) { return true; });
292
+ m.def("defer_none_custom", [](UserType *) { return false; });
293
+ m.def("defer_none_custom", [](const py::none &) { return true; });
294
+ m.def("nodefer_none_void", [](void *) { return true; });
295
+ m.def("nodefer_none_void", [](const py::none &) { return false; });
296
+
297
+ // test_void_caster
298
+ m.def("load_nullptr_t", [](std::nullptr_t) {}); // not useful, but it should still compile
299
+ m.def("cast_nullptr_t", []() { return std::nullptr_t{}; });
300
+
301
+ // [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
302
+
303
+ // test_bool_caster
304
+ m.def("bool_passthrough", [](bool arg) { return arg; });
305
+ m.def(
306
+ "bool_passthrough_noconvert", [](bool arg) { return arg; }, py::arg{}.noconvert());
307
+
308
+ // TODO: This should be disabled and fixed in future Intel compilers
309
+ #if !defined(__INTEL_COMPILER)
310
+ // Test "bool_passthrough_noconvert" again, but using () instead of {} to construct py::arg
311
+ // When compiled with the Intel compiler, this results in segmentation faults when importing
312
+ // the module. Tested with icc (ICC) 2021.1 Beta 20200827, this should be tested again when
313
+ // a newer version of icc is available.
314
+ m.def(
315
+ "bool_passthrough_noconvert2", [](bool arg) { return arg; }, py::arg().noconvert());
316
+ #endif
317
+
318
+ // test_reference_wrapper
319
+ m.def("refwrap_builtin", [](std::reference_wrapper<int> p) { return 10 * p.get(); });
320
+ m.def("refwrap_usertype", [](std::reference_wrapper<UserType> p) { return p.get().value(); });
321
+ m.def("refwrap_usertype_const",
322
+ [](std::reference_wrapper<const UserType> p) { return p.get().value(); });
323
+
324
+ m.def("refwrap_lvalue", []() -> std::reference_wrapper<UserType> {
325
+ static UserType x(1);
326
+ return std::ref(x);
327
+ });
328
+ m.def("refwrap_lvalue_const", []() -> std::reference_wrapper<const UserType> {
329
+ static UserType x(1);
330
+ return std::cref(x);
331
+ });
332
+
333
+ // Not currently supported (std::pair caster has return-by-value cast operator);
334
+ // triggers static_assert failure.
335
+ // m.def("refwrap_pair", [](std::reference_wrapper<std::pair<int, int>>) { });
336
+
337
+ m.def(
338
+ "refwrap_list",
339
+ [](bool copy) {
340
+ static IncType x1(1), x2(2);
341
+ py::list l;
342
+ for (const auto &f : {std::ref(x1), std::ref(x2)}) {
343
+ l.append(py::cast(
344
+ f, copy ? py::return_value_policy::copy : py::return_value_policy::reference));
345
+ }
346
+ return l;
347
+ },
348
+ "copy"_a);
349
+
350
+ m.def("refwrap_iiw", [](const IncType &w) { return w.value(); });
351
+ m.def("refwrap_call_iiw", [](IncType &w, const py::function &f) {
352
+ py::list l;
353
+ l.append(f(std::ref(w)));
354
+ l.append(f(std::cref(w)));
355
+ IncType x(w.value());
356
+ l.append(f(std::ref(x)));
357
+ IncType y(w.value());
358
+ auto r3 = std::ref(y);
359
+ l.append(f(r3));
360
+ return l;
361
+ });
362
+
363
+ // test_complex
364
+ m.def("complex_cast", [](float x) { return "{}"_s.format(x); });
365
+ m.def("complex_cast",
366
+ [](std::complex<float> x) { return "({}, {})"_s.format(x.real(), x.imag()); });
367
+
368
+ // test int vs. long (Python 2)
369
+ m.def("int_cast", []() { return (int) 42; });
370
+ m.def("long_cast", []() { return (long) 42; });
371
+ m.def("longlong_cast", []() { return ULLONG_MAX; });
372
+
373
+ /// test void* cast operator
374
+ m.def("test_void_caster", []() -> bool {
375
+ void *v = (void *) 0xabcd;
376
+ py::object o = py::cast(v);
377
+ return py::cast<void *>(o) == v;
378
+ });
379
+
380
+ // Tests const/non-const propagation in cast_op.
381
+ m.def("takes", [](ConstRefCasted x) { return x.tag; });
382
+ m.def("takes_move", [](ConstRefCasted &&x) { return x.tag; });
383
+ m.def("takes_ptr", [](ConstRefCasted *x) { return x->tag; });
384
+ m.def("takes_ref", [](ConstRefCasted &x) { return x.tag; });
385
+ m.def("takes_ref_wrap", [](std::reference_wrapper<ConstRefCasted> x) { return x.get().tag; });
386
+ m.def("takes_const_ptr", [](const ConstRefCasted *x) { return x->tag; });
387
+ m.def("takes_const_ref", [](const ConstRefCasted &x) { return x.tag; });
388
+ m.def("takes_const_ref_wrap",
389
+ [](std::reference_wrapper<const ConstRefCasted> x) { return x.get().tag; });
390
+
391
+ PYBIND11_WARNING_POP
392
+ }
third_party/CityFlow/extern/pybind11/tests/test_builtin_casters.py CHANGED
@@ -1,528 +1,528 @@
1
- import sys
2
-
3
- import pytest
4
-
5
- import env
6
- from pybind11_tests import IncType, UserType
7
- from pybind11_tests import builtin_casters as m
8
-
9
-
10
- def test_simple_string():
11
- assert m.string_roundtrip("const char *") == "const char *"
12
-
13
-
14
- def test_unicode_conversion():
15
- """Tests unicode conversion and error reporting."""
16
- assert m.good_utf8_string() == "Say utf8‽ 🎂 𝐀"
17
- assert m.good_utf16_string() == "b‽🎂𝐀z"
18
- assert m.good_utf32_string() == "a𝐀🎂‽z"
19
- assert m.good_wchar_string() == "a⸘𝐀z"
20
- if hasattr(m, "has_u8string"):
21
- assert m.good_utf8_u8string() == "Say utf8‽ 🎂 𝐀"
22
-
23
- with pytest.raises(UnicodeDecodeError):
24
- m.bad_utf8_string()
25
-
26
- with pytest.raises(UnicodeDecodeError):
27
- m.bad_utf16_string()
28
-
29
- # These are provided only if they actually fail (they don't when 32-bit)
30
- if hasattr(m, "bad_utf32_string"):
31
- with pytest.raises(UnicodeDecodeError):
32
- m.bad_utf32_string()
33
- if hasattr(m, "bad_wchar_string"):
34
- with pytest.raises(UnicodeDecodeError):
35
- m.bad_wchar_string()
36
- if hasattr(m, "has_u8string"):
37
- with pytest.raises(UnicodeDecodeError):
38
- m.bad_utf8_u8string()
39
-
40
- assert m.u8_Z() == "Z"
41
- assert m.u8_eacute() == "é"
42
- assert m.u16_ibang() == "‽"
43
- assert m.u32_mathbfA() == "𝐀"
44
- assert m.wchar_heart() == "♥"
45
- if hasattr(m, "has_u8string"):
46
- assert m.u8_char8_Z() == "Z"
47
-
48
-
49
- def test_single_char_arguments():
50
- """Tests failures for passing invalid inputs to char-accepting functions"""
51
-
52
- def toobig_message(r):
53
- return f"Character code point not in range({r:#x})"
54
-
55
- toolong_message = "Expected a character, but multi-character string found"
56
-
57
- assert m.ord_char("a") == 0x61 # simple ASCII
58
- assert m.ord_char_lv("b") == 0x62
59
- assert (
60
- m.ord_char("é") == 0xE9
61
- ) # requires 2 bytes in utf-8, but can be stuffed in a char
62
- with pytest.raises(ValueError) as excinfo:
63
- assert m.ord_char("Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
64
- assert str(excinfo.value) == toobig_message(0x100)
65
- with pytest.raises(ValueError) as excinfo:
66
- assert m.ord_char("ab")
67
- assert str(excinfo.value) == toolong_message
68
-
69
- assert m.ord_char16("a") == 0x61
70
- assert m.ord_char16("é") == 0xE9
71
- assert m.ord_char16_lv("ê") == 0xEA
72
- assert m.ord_char16("Ā") == 0x100
73
- assert m.ord_char16("‽") == 0x203D
74
- assert m.ord_char16("♥") == 0x2665
75
- assert m.ord_char16_lv("♡") == 0x2661
76
- with pytest.raises(ValueError) as excinfo:
77
- assert m.ord_char16("🎂") == 0x1F382 # requires surrogate pair
78
- assert str(excinfo.value) == toobig_message(0x10000)
79
- with pytest.raises(ValueError) as excinfo:
80
- assert m.ord_char16("aa")
81
- assert str(excinfo.value) == toolong_message
82
-
83
- assert m.ord_char32("a") == 0x61
84
- assert m.ord_char32("é") == 0xE9
85
- assert m.ord_char32("Ā") == 0x100
86
- assert m.ord_char32("‽") == 0x203D
87
- assert m.ord_char32("♥") == 0x2665
88
- assert m.ord_char32("🎂") == 0x1F382
89
- with pytest.raises(ValueError) as excinfo:
90
- assert m.ord_char32("aa")
91
- assert str(excinfo.value) == toolong_message
92
-
93
- assert m.ord_wchar("a") == 0x61
94
- assert m.ord_wchar("é") == 0xE9
95
- assert m.ord_wchar("Ā") == 0x100
96
- assert m.ord_wchar("‽") == 0x203D
97
- assert m.ord_wchar("♥") == 0x2665
98
- if m.wchar_size == 2:
99
- with pytest.raises(ValueError) as excinfo:
100
- assert m.ord_wchar("🎂") == 0x1F382 # requires surrogate pair
101
- assert str(excinfo.value) == toobig_message(0x10000)
102
- else:
103
- assert m.ord_wchar("🎂") == 0x1F382
104
- with pytest.raises(ValueError) as excinfo:
105
- assert m.ord_wchar("aa")
106
- assert str(excinfo.value) == toolong_message
107
-
108
- if hasattr(m, "has_u8string"):
109
- assert m.ord_char8("a") == 0x61 # simple ASCII
110
- assert m.ord_char8_lv("b") == 0x62
111
- assert (
112
- m.ord_char8("é") == 0xE9
113
- ) # requires 2 bytes in utf-8, but can be stuffed in a char
114
- with pytest.raises(ValueError) as excinfo:
115
- assert m.ord_char8("Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
116
- assert str(excinfo.value) == toobig_message(0x100)
117
- with pytest.raises(ValueError) as excinfo:
118
- assert m.ord_char8("ab")
119
- assert str(excinfo.value) == toolong_message
120
-
121
-
122
- def test_bytes_to_string():
123
- """Tests the ability to pass bytes to C++ string-accepting functions. Note that this is
124
- one-way: the only way to return bytes to Python is via the pybind11::bytes class."""
125
- # Issue #816
126
-
127
- assert m.strlen(b"hi") == 2
128
- assert m.string_length(b"world") == 5
129
- assert m.string_length(b"a\x00b") == 3
130
- assert m.strlen(b"a\x00b") == 1 # C-string limitation
131
-
132
- # passing in a utf8 encoded string should work
133
- assert m.string_length("💩".encode()) == 4
134
-
135
-
136
- def test_bytearray_to_string():
137
- """Tests the ability to pass bytearray to C++ string-accepting functions"""
138
- assert m.string_length(bytearray(b"Hi")) == 2
139
- assert m.strlen(bytearray(b"bytearray")) == 9
140
- assert m.string_length(bytearray()) == 0
141
- assert m.string_length(bytearray("🦜", "utf-8", "strict")) == 4
142
- assert m.string_length(bytearray(b"\x80")) == 1
143
-
144
-
145
- @pytest.mark.skipif(not hasattr(m, "has_string_view"), reason="no <string_view>")
146
- def test_string_view(capture):
147
- """Tests support for C++17 string_view arguments and return values"""
148
- assert m.string_view_chars("Hi") == [72, 105]
149
- assert m.string_view_chars("Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
150
- assert m.string_view16_chars("Hi 🎂") == [72, 105, 32, 0xD83C, 0xDF82]
151
- assert m.string_view32_chars("Hi 🎂") == [72, 105, 32, 127874]
152
- if hasattr(m, "has_u8string"):
153
- assert m.string_view8_chars("Hi") == [72, 105]
154
- assert m.string_view8_chars("Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
155
-
156
- assert m.string_view_return() == "utf8 secret 🎂"
157
- assert m.string_view16_return() == "utf16 secret 🎂"
158
- assert m.string_view32_return() == "utf32 secret 🎂"
159
- if hasattr(m, "has_u8string"):
160
- assert m.string_view8_return() == "utf8 secret 🎂"
161
-
162
- with capture:
163
- m.string_view_print("Hi")
164
- m.string_view_print("utf8 🎂")
165
- m.string_view16_print("utf16 🎂")
166
- m.string_view32_print("utf32 🎂")
167
- assert (
168
- capture
169
- == """
170
- Hi 2
171
- utf8 🎂 9
172
- utf16 🎂 8
173
- utf32 🎂 7
174
- """
175
- )
176
- if hasattr(m, "has_u8string"):
177
- with capture:
178
- m.string_view8_print("Hi")
179
- m.string_view8_print("utf8 🎂")
180
- assert (
181
- capture
182
- == """
183
- Hi 2
184
- utf8 🎂 9
185
- """
186
- )
187
-
188
- with capture:
189
- m.string_view_print("Hi, ascii")
190
- m.string_view_print("Hi, utf8 🎂")
191
- m.string_view16_print("Hi, utf16 🎂")
192
- m.string_view32_print("Hi, utf32 🎂")
193
- assert (
194
- capture
195
- == """
196
- Hi, ascii 9
197
- Hi, utf8 🎂 13
198
- Hi, utf16 🎂 12
199
- Hi, utf32 🎂 11
200
- """
201
- )
202
- if hasattr(m, "has_u8string"):
203
- with capture:
204
- m.string_view8_print("Hi, ascii")
205
- m.string_view8_print("Hi, utf8 🎂")
206
- assert (
207
- capture
208
- == """
209
- Hi, ascii 9
210
- Hi, utf8 🎂 13
211
- """
212
- )
213
-
214
- assert m.string_view_bytes() == b"abc \x80\x80 def"
215
- assert m.string_view_str() == "abc ‽ def"
216
- assert m.string_view_from_bytes("abc ‽ def".encode()) == "abc ‽ def"
217
- if hasattr(m, "has_u8string"):
218
- assert m.string_view8_str() == "abc ‽ def"
219
- assert m.string_view_memoryview() == "Have some 🎂".encode()
220
-
221
- assert m.bytes_from_type_with_both_operator_string_and_string_view() == b"success"
222
- assert m.str_from_type_with_both_operator_string_and_string_view() == "success"
223
-
224
-
225
- def test_integer_casting():
226
- """Issue #929 - out-of-range integer values shouldn't be accepted"""
227
- assert m.i32_str(-1) == "-1"
228
- assert m.i64_str(-1) == "-1"
229
- assert m.i32_str(2000000000) == "2000000000"
230
- assert m.u32_str(2000000000) == "2000000000"
231
- assert m.i64_str(-999999999999) == "-999999999999"
232
- assert m.u64_str(999999999999) == "999999999999"
233
-
234
- with pytest.raises(TypeError) as excinfo:
235
- m.u32_str(-1)
236
- assert "incompatible function arguments" in str(excinfo.value)
237
- with pytest.raises(TypeError) as excinfo:
238
- m.u64_str(-1)
239
- assert "incompatible function arguments" in str(excinfo.value)
240
- with pytest.raises(TypeError) as excinfo:
241
- m.i32_str(-3000000000)
242
- assert "incompatible function arguments" in str(excinfo.value)
243
- with pytest.raises(TypeError) as excinfo:
244
- m.i32_str(3000000000)
245
- assert "incompatible function arguments" in str(excinfo.value)
246
-
247
-
248
- def test_int_convert():
249
- class Int:
250
- def __int__(self):
251
- return 42
252
-
253
- class NotInt:
254
- pass
255
-
256
- class Float:
257
- def __float__(self):
258
- return 41.99999
259
-
260
- class Index:
261
- def __index__(self):
262
- return 42
263
-
264
- class IntAndIndex:
265
- def __int__(self):
266
- return 42
267
-
268
- def __index__(self):
269
- return 0
270
-
271
- class RaisingTypeErrorOnIndex:
272
- def __index__(self):
273
- raise TypeError
274
-
275
- def __int__(self):
276
- return 42
277
-
278
- class RaisingValueErrorOnIndex:
279
- def __index__(self):
280
- raise ValueError
281
-
282
- def __int__(self):
283
- return 42
284
-
285
- convert, noconvert = m.int_passthrough, m.int_passthrough_noconvert
286
-
287
- def requires_conversion(v):
288
- pytest.raises(TypeError, noconvert, v)
289
-
290
- def cant_convert(v):
291
- pytest.raises(TypeError, convert, v)
292
-
293
- assert convert(7) == 7
294
- assert noconvert(7) == 7
295
- cant_convert(3.14159)
296
- # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
297
- # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
298
- if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
299
- with env.deprecated_call():
300
- assert convert(Int()) == 42
301
- else:
302
- assert convert(Int()) == 42
303
- requires_conversion(Int())
304
- cant_convert(NotInt())
305
- cant_convert(Float())
306
-
307
- # Before Python 3.8, `PyLong_AsLong` does not pick up on `obj.__index__`,
308
- # but pybind11 "backports" this behavior.
309
- assert convert(Index()) == 42
310
- assert noconvert(Index()) == 42
311
- assert convert(IntAndIndex()) == 0 # Fishy; `int(DoubleThought)` == 42
312
- assert noconvert(IntAndIndex()) == 0
313
- assert convert(RaisingTypeErrorOnIndex()) == 42
314
- requires_conversion(RaisingTypeErrorOnIndex())
315
- assert convert(RaisingValueErrorOnIndex()) == 42
316
- requires_conversion(RaisingValueErrorOnIndex())
317
-
318
-
319
- def test_numpy_int_convert():
320
- np = pytest.importorskip("numpy")
321
-
322
- convert, noconvert = m.int_passthrough, m.int_passthrough_noconvert
323
-
324
- def require_implicit(v):
325
- pytest.raises(TypeError, noconvert, v)
326
-
327
- # `np.intc` is an alias that corresponds to a C++ `int`
328
- assert convert(np.intc(42)) == 42
329
- assert noconvert(np.intc(42)) == 42
330
-
331
- # The implicit conversion from np.float32 is undesirable but currently accepted.
332
- # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
333
- # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
334
- # https://github.com/pybind/pybind11/issues/3408
335
- if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
336
- with env.deprecated_call():
337
- assert convert(np.float32(3.14159)) == 3
338
- else:
339
- assert convert(np.float32(3.14159)) == 3
340
- require_implicit(np.float32(3.14159))
341
-
342
-
343
- def test_tuple(doc):
344
- """std::pair <-> tuple & std::tuple <-> tuple"""
345
- assert m.pair_passthrough((True, "test")) == ("test", True)
346
- assert m.tuple_passthrough((True, "test", 5)) == (5, "test", True)
347
- # Any sequence can be cast to a std::pair or std::tuple
348
- assert m.pair_passthrough([True, "test"]) == ("test", True)
349
- assert m.tuple_passthrough([True, "test", 5]) == (5, "test", True)
350
- assert m.empty_tuple() == ()
351
-
352
- assert (
353
- doc(m.pair_passthrough)
354
- == """
355
- pair_passthrough(arg0: tuple[bool, str]) -> tuple[str, bool]
356
-
357
- Return a pair in reversed order
358
- """
359
- )
360
- assert (
361
- doc(m.tuple_passthrough)
362
- == """
363
- tuple_passthrough(arg0: tuple[bool, str, int]) -> tuple[int, str, bool]
364
-
365
- Return a triple in reversed order
366
- """
367
- )
368
-
369
- assert m.rvalue_pair() == ("rvalue", "rvalue")
370
- assert m.lvalue_pair() == ("lvalue", "lvalue")
371
- assert m.rvalue_tuple() == ("rvalue", "rvalue", "rvalue")
372
- assert m.lvalue_tuple() == ("lvalue", "lvalue", "lvalue")
373
- assert m.rvalue_nested() == ("rvalue", ("rvalue", ("rvalue", "rvalue")))
374
- assert m.lvalue_nested() == ("lvalue", ("lvalue", ("lvalue", "lvalue")))
375
-
376
- assert m.int_string_pair() == (2, "items")
377
-
378
-
379
- def test_builtins_cast_return_none():
380
- """Casters produced with PYBIND11_TYPE_CASTER() should convert nullptr to None"""
381
- assert m.return_none_string() is None
382
- assert m.return_none_char() is None
383
- assert m.return_none_bool() is None
384
- assert m.return_none_int() is None
385
- assert m.return_none_float() is None
386
- assert m.return_none_pair() is None
387
-
388
-
389
- def test_none_deferred():
390
- """None passed as various argument types should defer to other overloads"""
391
- assert not m.defer_none_cstring("abc")
392
- assert m.defer_none_cstring(None)
393
- assert not m.defer_none_custom(UserType())
394
- assert m.defer_none_custom(None)
395
- assert m.nodefer_none_void(None)
396
-
397
-
398
- def test_void_caster():
399
- assert m.load_nullptr_t(None) is None
400
- assert m.cast_nullptr_t() is None
401
-
402
-
403
- def test_reference_wrapper():
404
- """std::reference_wrapper for builtin and user types"""
405
- assert m.refwrap_builtin(42) == 420
406
- assert m.refwrap_usertype(UserType(42)) == 42
407
- assert m.refwrap_usertype_const(UserType(42)) == 42
408
-
409
- with pytest.raises(TypeError) as excinfo:
410
- m.refwrap_builtin(None)
411
- assert "incompatible function arguments" in str(excinfo.value)
412
-
413
- with pytest.raises(TypeError) as excinfo:
414
- m.refwrap_usertype(None)
415
- assert "incompatible function arguments" in str(excinfo.value)
416
-
417
- assert m.refwrap_lvalue().value == 1
418
- assert m.refwrap_lvalue_const().value == 1
419
-
420
- a1 = m.refwrap_list(copy=True)
421
- a2 = m.refwrap_list(copy=True)
422
- assert [x.value for x in a1] == [2, 3]
423
- assert [x.value for x in a2] == [2, 3]
424
- assert a1[0] is not a2[0]
425
- assert a1[1] is not a2[1]
426
-
427
- b1 = m.refwrap_list(copy=False)
428
- b2 = m.refwrap_list(copy=False)
429
- assert [x.value for x in b1] == [1, 2]
430
- assert [x.value for x in b2] == [1, 2]
431
- assert b1[0] is b2[0]
432
- assert b1[1] is b2[1]
433
-
434
- assert m.refwrap_iiw(IncType(5)) == 5
435
- assert m.refwrap_call_iiw(IncType(10), m.refwrap_iiw) == [10, 10, 10, 10]
436
-
437
-
438
- def test_complex_cast():
439
- """std::complex casts"""
440
- assert m.complex_cast(1) == "1.0"
441
- assert m.complex_cast(2j) == "(0.0, 2.0)"
442
-
443
-
444
- def test_bool_caster():
445
- """Test bool caster implicit conversions."""
446
- convert, noconvert = m.bool_passthrough, m.bool_passthrough_noconvert
447
-
448
- def require_implicit(v):
449
- pytest.raises(TypeError, noconvert, v)
450
-
451
- def cant_convert(v):
452
- pytest.raises(TypeError, convert, v)
453
-
454
- # straight up bool
455
- assert convert(True) is True
456
- assert convert(False) is False
457
- assert noconvert(True) is True
458
- assert noconvert(False) is False
459
-
460
- # None requires implicit conversion
461
- require_implicit(None)
462
- assert convert(None) is False
463
-
464
- class A:
465
- def __init__(self, x):
466
- self.x = x
467
-
468
- def __nonzero__(self):
469
- return self.x
470
-
471
- def __bool__(self):
472
- return self.x
473
-
474
- class B:
475
- pass
476
-
477
- # Arbitrary objects are not accepted
478
- cant_convert(object())
479
- cant_convert(B())
480
-
481
- # Objects with __nonzero__ / __bool__ defined can be converted
482
- require_implicit(A(True))
483
- assert convert(A(True)) is True
484
- assert convert(A(False)) is False
485
-
486
-
487
- def test_numpy_bool():
488
- np = pytest.importorskip("numpy")
489
-
490
- convert, noconvert = m.bool_passthrough, m.bool_passthrough_noconvert
491
-
492
- def cant_convert(v):
493
- pytest.raises(TypeError, convert, v)
494
-
495
- # np.bool_ is not considered implicit
496
- assert convert(np.bool_(True)) is True
497
- assert convert(np.bool_(False)) is False
498
- assert noconvert(np.bool_(True)) is True
499
- assert noconvert(np.bool_(False)) is False
500
- cant_convert(np.zeros(2, dtype="int"))
501
-
502
-
503
- def test_int_long():
504
- assert isinstance(m.int_cast(), int)
505
- assert isinstance(m.long_cast(), int)
506
- assert isinstance(m.longlong_cast(), int)
507
-
508
-
509
- def test_void_caster_2():
510
- assert m.test_void_caster()
511
-
512
-
513
- def test_const_ref_caster():
514
- """Verifies that const-ref is propagated through type_caster cast_op.
515
- The returned ConstRefCasted type is a minimal type that is constructed to
516
- reference the casting mode used.
517
- """
518
- x = False
519
- assert m.takes(x) == 1
520
- assert m.takes_move(x) == 1
521
-
522
- assert m.takes_ptr(x) == 3
523
- assert m.takes_ref(x) == 2
524
- assert m.takes_ref_wrap(x) == 2
525
-
526
- assert m.takes_const_ptr(x) == 5
527
- assert m.takes_const_ref(x) == 4
528
- assert m.takes_const_ref_wrap(x) == 4
 
1
+ import sys
2
+
3
+ import pytest
4
+
5
+ import env
6
+ from pybind11_tests import IncType, UserType
7
+ from pybind11_tests import builtin_casters as m
8
+
9
+
10
+ def test_simple_string():
11
+ assert m.string_roundtrip("const char *") == "const char *"
12
+
13
+
14
+ def test_unicode_conversion():
15
+ """Tests unicode conversion and error reporting."""
16
+ assert m.good_utf8_string() == "Say utf8‽ 🎂 𝐀"
17
+ assert m.good_utf16_string() == "b‽🎂𝐀z"
18
+ assert m.good_utf32_string() == "a𝐀🎂‽z"
19
+ assert m.good_wchar_string() == "a⸘𝐀z"
20
+ if hasattr(m, "has_u8string"):
21
+ assert m.good_utf8_u8string() == "Say utf8‽ 🎂 𝐀"
22
+
23
+ with pytest.raises(UnicodeDecodeError):
24
+ m.bad_utf8_string()
25
+
26
+ with pytest.raises(UnicodeDecodeError):
27
+ m.bad_utf16_string()
28
+
29
+ # These are provided only if they actually fail (they don't when 32-bit)
30
+ if hasattr(m, "bad_utf32_string"):
31
+ with pytest.raises(UnicodeDecodeError):
32
+ m.bad_utf32_string()
33
+ if hasattr(m, "bad_wchar_string"):
34
+ with pytest.raises(UnicodeDecodeError):
35
+ m.bad_wchar_string()
36
+ if hasattr(m, "has_u8string"):
37
+ with pytest.raises(UnicodeDecodeError):
38
+ m.bad_utf8_u8string()
39
+
40
+ assert m.u8_Z() == "Z"
41
+ assert m.u8_eacute() == "é"
42
+ assert m.u16_ibang() == "‽"
43
+ assert m.u32_mathbfA() == "𝐀"
44
+ assert m.wchar_heart() == "♥"
45
+ if hasattr(m, "has_u8string"):
46
+ assert m.u8_char8_Z() == "Z"
47
+
48
+
49
+ def test_single_char_arguments():
50
+ """Tests failures for passing invalid inputs to char-accepting functions"""
51
+
52
+ def toobig_message(r):
53
+ return f"Character code point not in range({r:#x})"
54
+
55
+ toolong_message = "Expected a character, but multi-character string found"
56
+
57
+ assert m.ord_char("a") == 0x61 # simple ASCII
58
+ assert m.ord_char_lv("b") == 0x62
59
+ assert (
60
+ m.ord_char("é") == 0xE9
61
+ ) # requires 2 bytes in utf-8, but can be stuffed in a char
62
+ with pytest.raises(ValueError) as excinfo:
63
+ assert m.ord_char("Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
64
+ assert str(excinfo.value) == toobig_message(0x100)
65
+ with pytest.raises(ValueError) as excinfo:
66
+ assert m.ord_char("ab")
67
+ assert str(excinfo.value) == toolong_message
68
+
69
+ assert m.ord_char16("a") == 0x61
70
+ assert m.ord_char16("é") == 0xE9
71
+ assert m.ord_char16_lv("ê") == 0xEA
72
+ assert m.ord_char16("Ā") == 0x100
73
+ assert m.ord_char16("‽") == 0x203D
74
+ assert m.ord_char16("♥") == 0x2665
75
+ assert m.ord_char16_lv("♡") == 0x2661
76
+ with pytest.raises(ValueError) as excinfo:
77
+ assert m.ord_char16("🎂") == 0x1F382 # requires surrogate pair
78
+ assert str(excinfo.value) == toobig_message(0x10000)
79
+ with pytest.raises(ValueError) as excinfo:
80
+ assert m.ord_char16("aa")
81
+ assert str(excinfo.value) == toolong_message
82
+
83
+ assert m.ord_char32("a") == 0x61
84
+ assert m.ord_char32("é") == 0xE9
85
+ assert m.ord_char32("Ā") == 0x100
86
+ assert m.ord_char32("‽") == 0x203D
87
+ assert m.ord_char32("♥") == 0x2665
88
+ assert m.ord_char32("🎂") == 0x1F382
89
+ with pytest.raises(ValueError) as excinfo:
90
+ assert m.ord_char32("aa")
91
+ assert str(excinfo.value) == toolong_message
92
+
93
+ assert m.ord_wchar("a") == 0x61
94
+ assert m.ord_wchar("é") == 0xE9
95
+ assert m.ord_wchar("Ā") == 0x100
96
+ assert m.ord_wchar("‽") == 0x203D
97
+ assert m.ord_wchar("♥") == 0x2665
98
+ if m.wchar_size == 2:
99
+ with pytest.raises(ValueError) as excinfo:
100
+ assert m.ord_wchar("🎂") == 0x1F382 # requires surrogate pair
101
+ assert str(excinfo.value) == toobig_message(0x10000)
102
+ else:
103
+ assert m.ord_wchar("🎂") == 0x1F382
104
+ with pytest.raises(ValueError) as excinfo:
105
+ assert m.ord_wchar("aa")
106
+ assert str(excinfo.value) == toolong_message
107
+
108
+ if hasattr(m, "has_u8string"):
109
+ assert m.ord_char8("a") == 0x61 # simple ASCII
110
+ assert m.ord_char8_lv("b") == 0x62
111
+ assert (
112
+ m.ord_char8("é") == 0xE9
113
+ ) # requires 2 bytes in utf-8, but can be stuffed in a char
114
+ with pytest.raises(ValueError) as excinfo:
115
+ assert m.ord_char8("Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
116
+ assert str(excinfo.value) == toobig_message(0x100)
117
+ with pytest.raises(ValueError) as excinfo:
118
+ assert m.ord_char8("ab")
119
+ assert str(excinfo.value) == toolong_message
120
+
121
+
122
+ def test_bytes_to_string():
123
+ """Tests the ability to pass bytes to C++ string-accepting functions. Note that this is
124
+ one-way: the only way to return bytes to Python is via the pybind11::bytes class."""
125
+ # Issue #816
126
+
127
+ assert m.strlen(b"hi") == 2
128
+ assert m.string_length(b"world") == 5
129
+ assert m.string_length(b"a\x00b") == 3
130
+ assert m.strlen(b"a\x00b") == 1 # C-string limitation
131
+
132
+ # passing in a utf8 encoded string should work
133
+ assert m.string_length("💩".encode()) == 4
134
+
135
+
136
+ def test_bytearray_to_string():
137
+ """Tests the ability to pass bytearray to C++ string-accepting functions"""
138
+ assert m.string_length(bytearray(b"Hi")) == 2
139
+ assert m.strlen(bytearray(b"bytearray")) == 9
140
+ assert m.string_length(bytearray()) == 0
141
+ assert m.string_length(bytearray("🦜", "utf-8", "strict")) == 4
142
+ assert m.string_length(bytearray(b"\x80")) == 1
143
+
144
+
145
+ @pytest.mark.skipif(not hasattr(m, "has_string_view"), reason="no <string_view>")
146
+ def test_string_view(capture):
147
+ """Tests support for C++17 string_view arguments and return values"""
148
+ assert m.string_view_chars("Hi") == [72, 105]
149
+ assert m.string_view_chars("Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
150
+ assert m.string_view16_chars("Hi 🎂") == [72, 105, 32, 0xD83C, 0xDF82]
151
+ assert m.string_view32_chars("Hi 🎂") == [72, 105, 32, 127874]
152
+ if hasattr(m, "has_u8string"):
153
+ assert m.string_view8_chars("Hi") == [72, 105]
154
+ assert m.string_view8_chars("Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
155
+
156
+ assert m.string_view_return() == "utf8 secret 🎂"
157
+ assert m.string_view16_return() == "utf16 secret 🎂"
158
+ assert m.string_view32_return() == "utf32 secret 🎂"
159
+ if hasattr(m, "has_u8string"):
160
+ assert m.string_view8_return() == "utf8 secret 🎂"
161
+
162
+ with capture:
163
+ m.string_view_print("Hi")
164
+ m.string_view_print("utf8 🎂")
165
+ m.string_view16_print("utf16 🎂")
166
+ m.string_view32_print("utf32 🎂")
167
+ assert (
168
+ capture
169
+ == """
170
+ Hi 2
171
+ utf8 🎂 9
172
+ utf16 🎂 8
173
+ utf32 🎂 7
174
+ """
175
+ )
176
+ if hasattr(m, "has_u8string"):
177
+ with capture:
178
+ m.string_view8_print("Hi")
179
+ m.string_view8_print("utf8 🎂")
180
+ assert (
181
+ capture
182
+ == """
183
+ Hi 2
184
+ utf8 🎂 9
185
+ """
186
+ )
187
+
188
+ with capture:
189
+ m.string_view_print("Hi, ascii")
190
+ m.string_view_print("Hi, utf8 🎂")
191
+ m.string_view16_print("Hi, utf16 🎂")
192
+ m.string_view32_print("Hi, utf32 🎂")
193
+ assert (
194
+ capture
195
+ == """
196
+ Hi, ascii 9
197
+ Hi, utf8 🎂 13
198
+ Hi, utf16 🎂 12
199
+ Hi, utf32 🎂 11
200
+ """
201
+ )
202
+ if hasattr(m, "has_u8string"):
203
+ with capture:
204
+ m.string_view8_print("Hi, ascii")
205
+ m.string_view8_print("Hi, utf8 🎂")
206
+ assert (
207
+ capture
208
+ == """
209
+ Hi, ascii 9
210
+ Hi, utf8 🎂 13
211
+ """
212
+ )
213
+
214
+ assert m.string_view_bytes() == b"abc \x80\x80 def"
215
+ assert m.string_view_str() == "abc ‽ def"
216
+ assert m.string_view_from_bytes("abc ‽ def".encode()) == "abc ‽ def"
217
+ if hasattr(m, "has_u8string"):
218
+ assert m.string_view8_str() == "abc ‽ def"
219
+ assert m.string_view_memoryview() == "Have some 🎂".encode()
220
+
221
+ assert m.bytes_from_type_with_both_operator_string_and_string_view() == b"success"
222
+ assert m.str_from_type_with_both_operator_string_and_string_view() == "success"
223
+
224
+
225
+ def test_integer_casting():
226
+ """Issue #929 - out-of-range integer values shouldn't be accepted"""
227
+ assert m.i32_str(-1) == "-1"
228
+ assert m.i64_str(-1) == "-1"
229
+ assert m.i32_str(2000000000) == "2000000000"
230
+ assert m.u32_str(2000000000) == "2000000000"
231
+ assert m.i64_str(-999999999999) == "-999999999999"
232
+ assert m.u64_str(999999999999) == "999999999999"
233
+
234
+ with pytest.raises(TypeError) as excinfo:
235
+ m.u32_str(-1)
236
+ assert "incompatible function arguments" in str(excinfo.value)
237
+ with pytest.raises(TypeError) as excinfo:
238
+ m.u64_str(-1)
239
+ assert "incompatible function arguments" in str(excinfo.value)
240
+ with pytest.raises(TypeError) as excinfo:
241
+ m.i32_str(-3000000000)
242
+ assert "incompatible function arguments" in str(excinfo.value)
243
+ with pytest.raises(TypeError) as excinfo:
244
+ m.i32_str(3000000000)
245
+ assert "incompatible function arguments" in str(excinfo.value)
246
+
247
+
248
+ def test_int_convert():
249
+ class Int:
250
+ def __int__(self):
251
+ return 42
252
+
253
+ class NotInt:
254
+ pass
255
+
256
+ class Float:
257
+ def __float__(self):
258
+ return 41.99999
259
+
260
+ class Index:
261
+ def __index__(self):
262
+ return 42
263
+
264
+ class IntAndIndex:
265
+ def __int__(self):
266
+ return 42
267
+
268
+ def __index__(self):
269
+ return 0
270
+
271
+ class RaisingTypeErrorOnIndex:
272
+ def __index__(self):
273
+ raise TypeError
274
+
275
+ def __int__(self):
276
+ return 42
277
+
278
+ class RaisingValueErrorOnIndex:
279
+ def __index__(self):
280
+ raise ValueError
281
+
282
+ def __int__(self):
283
+ return 42
284
+
285
+ convert, noconvert = m.int_passthrough, m.int_passthrough_noconvert
286
+
287
+ def requires_conversion(v):
288
+ pytest.raises(TypeError, noconvert, v)
289
+
290
+ def cant_convert(v):
291
+ pytest.raises(TypeError, convert, v)
292
+
293
+ assert convert(7) == 7
294
+ assert noconvert(7) == 7
295
+ cant_convert(3.14159)
296
+ # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
297
+ # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
298
+ if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
299
+ with env.deprecated_call():
300
+ assert convert(Int()) == 42
301
+ else:
302
+ assert convert(Int()) == 42
303
+ requires_conversion(Int())
304
+ cant_convert(NotInt())
305
+ cant_convert(Float())
306
+
307
+ # Before Python 3.8, `PyLong_AsLong` does not pick up on `obj.__index__`,
308
+ # but pybind11 "backports" this behavior.
309
+ assert convert(Index()) == 42
310
+ assert noconvert(Index()) == 42
311
+ assert convert(IntAndIndex()) == 0 # Fishy; `int(DoubleThought)` == 42
312
+ assert noconvert(IntAndIndex()) == 0
313
+ assert convert(RaisingTypeErrorOnIndex()) == 42
314
+ requires_conversion(RaisingTypeErrorOnIndex())
315
+ assert convert(RaisingValueErrorOnIndex()) == 42
316
+ requires_conversion(RaisingValueErrorOnIndex())
317
+
318
+
319
+ def test_numpy_int_convert():
320
+ np = pytest.importorskip("numpy")
321
+
322
+ convert, noconvert = m.int_passthrough, m.int_passthrough_noconvert
323
+
324
+ def require_implicit(v):
325
+ pytest.raises(TypeError, noconvert, v)
326
+
327
+ # `np.intc` is an alias that corresponds to a C++ `int`
328
+ assert convert(np.intc(42)) == 42
329
+ assert noconvert(np.intc(42)) == 42
330
+
331
+ # The implicit conversion from np.float32 is undesirable but currently accepted.
332
+ # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
333
+ # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
334
+ # https://github.com/pybind/pybind11/issues/3408
335
+ if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
336
+ with env.deprecated_call():
337
+ assert convert(np.float32(3.14159)) == 3
338
+ else:
339
+ assert convert(np.float32(3.14159)) == 3
340
+ require_implicit(np.float32(3.14159))
341
+
342
+
343
+ def test_tuple(doc):
344
+ """std::pair <-> tuple & std::tuple <-> tuple"""
345
+ assert m.pair_passthrough((True, "test")) == ("test", True)
346
+ assert m.tuple_passthrough((True, "test", 5)) == (5, "test", True)
347
+ # Any sequence can be cast to a std::pair or std::tuple
348
+ assert m.pair_passthrough([True, "test"]) == ("test", True)
349
+ assert m.tuple_passthrough([True, "test", 5]) == (5, "test", True)
350
+ assert m.empty_tuple() == ()
351
+
352
+ assert (
353
+ doc(m.pair_passthrough)
354
+ == """
355
+ pair_passthrough(arg0: tuple[bool, str]) -> tuple[str, bool]
356
+
357
+ Return a pair in reversed order
358
+ """
359
+ )
360
+ assert (
361
+ doc(m.tuple_passthrough)
362
+ == """
363
+ tuple_passthrough(arg0: tuple[bool, str, int]) -> tuple[int, str, bool]
364
+
365
+ Return a triple in reversed order
366
+ """
367
+ )
368
+
369
+ assert m.rvalue_pair() == ("rvalue", "rvalue")
370
+ assert m.lvalue_pair() == ("lvalue", "lvalue")
371
+ assert m.rvalue_tuple() == ("rvalue", "rvalue", "rvalue")
372
+ assert m.lvalue_tuple() == ("lvalue", "lvalue", "lvalue")
373
+ assert m.rvalue_nested() == ("rvalue", ("rvalue", ("rvalue", "rvalue")))
374
+ assert m.lvalue_nested() == ("lvalue", ("lvalue", ("lvalue", "lvalue")))
375
+
376
+ assert m.int_string_pair() == (2, "items")
377
+
378
+
379
+ def test_builtins_cast_return_none():
380
+ """Casters produced with PYBIND11_TYPE_CASTER() should convert nullptr to None"""
381
+ assert m.return_none_string() is None
382
+ assert m.return_none_char() is None
383
+ assert m.return_none_bool() is None
384
+ assert m.return_none_int() is None
385
+ assert m.return_none_float() is None
386
+ assert m.return_none_pair() is None
387
+
388
+
389
+ def test_none_deferred():
390
+ """None passed as various argument types should defer to other overloads"""
391
+ assert not m.defer_none_cstring("abc")
392
+ assert m.defer_none_cstring(None)
393
+ assert not m.defer_none_custom(UserType())
394
+ assert m.defer_none_custom(None)
395
+ assert m.nodefer_none_void(None)
396
+
397
+
398
+ def test_void_caster():
399
+ assert m.load_nullptr_t(None) is None
400
+ assert m.cast_nullptr_t() is None
401
+
402
+
403
+ def test_reference_wrapper():
404
+ """std::reference_wrapper for builtin and user types"""
405
+ assert m.refwrap_builtin(42) == 420
406
+ assert m.refwrap_usertype(UserType(42)) == 42
407
+ assert m.refwrap_usertype_const(UserType(42)) == 42
408
+
409
+ with pytest.raises(TypeError) as excinfo:
410
+ m.refwrap_builtin(None)
411
+ assert "incompatible function arguments" in str(excinfo.value)
412
+
413
+ with pytest.raises(TypeError) as excinfo:
414
+ m.refwrap_usertype(None)
415
+ assert "incompatible function arguments" in str(excinfo.value)
416
+
417
+ assert m.refwrap_lvalue().value == 1
418
+ assert m.refwrap_lvalue_const().value == 1
419
+
420
+ a1 = m.refwrap_list(copy=True)
421
+ a2 = m.refwrap_list(copy=True)
422
+ assert [x.value for x in a1] == [2, 3]
423
+ assert [x.value for x in a2] == [2, 3]
424
+ assert a1[0] is not a2[0]
425
+ assert a1[1] is not a2[1]
426
+
427
+ b1 = m.refwrap_list(copy=False)
428
+ b2 = m.refwrap_list(copy=False)
429
+ assert [x.value for x in b1] == [1, 2]
430
+ assert [x.value for x in b2] == [1, 2]
431
+ assert b1[0] is b2[0]
432
+ assert b1[1] is b2[1]
433
+
434
+ assert m.refwrap_iiw(IncType(5)) == 5
435
+ assert m.refwrap_call_iiw(IncType(10), m.refwrap_iiw) == [10, 10, 10, 10]
436
+
437
+
438
+ def test_complex_cast():
439
+ """std::complex casts"""
440
+ assert m.complex_cast(1) == "1.0"
441
+ assert m.complex_cast(2j) == "(0.0, 2.0)"
442
+
443
+
444
+ def test_bool_caster():
445
+ """Test bool caster implicit conversions."""
446
+ convert, noconvert = m.bool_passthrough, m.bool_passthrough_noconvert
447
+
448
+ def require_implicit(v):
449
+ pytest.raises(TypeError, noconvert, v)
450
+
451
+ def cant_convert(v):
452
+ pytest.raises(TypeError, convert, v)
453
+
454
+ # straight up bool
455
+ assert convert(True) is True
456
+ assert convert(False) is False
457
+ assert noconvert(True) is True
458
+ assert noconvert(False) is False
459
+
460
+ # None requires implicit conversion
461
+ require_implicit(None)
462
+ assert convert(None) is False
463
+
464
+ class A:
465
+ def __init__(self, x):
466
+ self.x = x
467
+
468
+ def __nonzero__(self):
469
+ return self.x
470
+
471
+ def __bool__(self):
472
+ return self.x
473
+
474
+ class B:
475
+ pass
476
+
477
+ # Arbitrary objects are not accepted
478
+ cant_convert(object())
479
+ cant_convert(B())
480
+
481
+ # Objects with __nonzero__ / __bool__ defined can be converted
482
+ require_implicit(A(True))
483
+ assert convert(A(True)) is True
484
+ assert convert(A(False)) is False
485
+
486
+
487
+ def test_numpy_bool():
488
+ np = pytest.importorskip("numpy")
489
+
490
+ convert, noconvert = m.bool_passthrough, m.bool_passthrough_noconvert
491
+
492
+ def cant_convert(v):
493
+ pytest.raises(TypeError, convert, v)
494
+
495
+ # np.bool_ is not considered implicit
496
+ assert convert(np.bool_(True)) is True
497
+ assert convert(np.bool_(False)) is False
498
+ assert noconvert(np.bool_(True)) is True
499
+ assert noconvert(np.bool_(False)) is False
500
+ cant_convert(np.zeros(2, dtype="int"))
501
+
502
+
503
+ def test_int_long():
504
+ assert isinstance(m.int_cast(), int)
505
+ assert isinstance(m.long_cast(), int)
506
+ assert isinstance(m.longlong_cast(), int)
507
+
508
+
509
+ def test_void_caster_2():
510
+ assert m.test_void_caster()
511
+
512
+
513
+ def test_const_ref_caster():
514
+ """Verifies that const-ref is propagated through type_caster cast_op.
515
+ The returned ConstRefCasted type is a minimal type that is constructed to
516
+ reference the casting mode used.
517
+ """
518
+ x = False
519
+ assert m.takes(x) == 1
520
+ assert m.takes_move(x) == 1
521
+
522
+ assert m.takes_ptr(x) == 3
523
+ assert m.takes_ref(x) == 2
524
+ assert m.takes_ref_wrap(x) == 2
525
+
526
+ assert m.takes_const_ptr(x) == 5
527
+ assert m.takes_const_ref(x) == 4
528
+ assert m.takes_const_ref_wrap(x) == 4
third_party/CityFlow/extern/pybind11/tests/test_call_policies.cpp CHANGED
@@ -1,115 +1,115 @@
1
- /*
2
- tests/test_call_policies.cpp -- keep_alive and call_guard
3
-
4
- Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include "pybind11_tests.h"
11
-
12
- struct CustomGuard {
13
- static bool enabled;
14
-
15
- CustomGuard() { enabled = true; }
16
- ~CustomGuard() { enabled = false; }
17
-
18
- static const char *report_status() { return enabled ? "guarded" : "unguarded"; }
19
- };
20
- bool CustomGuard::enabled = false;
21
-
22
- struct DependentGuard {
23
- static bool enabled;
24
-
25
- DependentGuard() { enabled = CustomGuard::enabled; }
26
- ~DependentGuard() { enabled = false; }
27
-
28
- static const char *report_status() { return enabled ? "guarded" : "unguarded"; }
29
- };
30
- bool DependentGuard::enabled = false;
31
-
32
- TEST_SUBMODULE(call_policies, m) {
33
- // Parent/Child are used in:
34
- // test_keep_alive_argument, test_keep_alive_return_value, test_alive_gc_derived,
35
- // test_alive_gc_multi_derived, test_return_none, test_keep_alive_constructor
36
- class Child {
37
- public:
38
- Child() { py::print("Allocating child."); }
39
- Child(const Child &) = default;
40
- Child(Child &&) = default;
41
- ~Child() { py::print("Releasing child."); }
42
- };
43
- py::class_<Child>(m, "Child").def(py::init<>());
44
-
45
- class Parent {
46
- public:
47
- Parent() { py::print("Allocating parent."); }
48
- Parent(const Parent &parent) = default;
49
- ~Parent() { py::print("Releasing parent."); }
50
- void addChild(Child *) {}
51
- Child *returnChild() { return new Child(); }
52
- Child *returnNullChild() { return nullptr; }
53
- static Child *staticFunction(Parent *) { return new Child(); }
54
- };
55
- py::class_<Parent>(m, "Parent")
56
- .def(py::init<>())
57
- .def(py::init([](Child *) { return new Parent(); }), py::keep_alive<1, 2>())
58
- .def("addChild", &Parent::addChild)
59
- .def("addChildKeepAlive", &Parent::addChild, py::keep_alive<1, 2>())
60
- .def("returnChild", &Parent::returnChild)
61
- .def("returnChildKeepAlive", &Parent::returnChild, py::keep_alive<1, 0>())
62
- .def("returnNullChildKeepAliveChild", &Parent::returnNullChild, py::keep_alive<1, 0>())
63
- .def("returnNullChildKeepAliveParent", &Parent::returnNullChild, py::keep_alive<0, 1>())
64
- .def_static("staticFunction", &Parent::staticFunction, py::keep_alive<1, 0>());
65
-
66
- m.def(
67
- "free_function", [](Parent *, Child *) {}, py::keep_alive<1, 2>());
68
- m.def(
69
- "invalid_arg_index", [] {}, py::keep_alive<0, 1>());
70
-
71
- #if !defined(PYPY_VERSION)
72
- // test_alive_gc
73
- class ParentGC : public Parent {
74
- public:
75
- using Parent::Parent;
76
- };
77
- py::class_<ParentGC, Parent>(m, "ParentGC", py::dynamic_attr()).def(py::init<>());
78
- #endif
79
-
80
- // test_call_guard
81
- m.def("unguarded_call", &CustomGuard::report_status);
82
- m.def("guarded_call", &CustomGuard::report_status, py::call_guard<CustomGuard>());
83
-
84
- m.def(
85
- "multiple_guards_correct_order",
86
- []() {
87
- return CustomGuard::report_status() + std::string(" & ")
88
- + DependentGuard::report_status();
89
- },
90
- py::call_guard<CustomGuard, DependentGuard>());
91
-
92
- m.def(
93
- "multiple_guards_wrong_order",
94
- []() {
95
- return DependentGuard::report_status() + std::string(" & ")
96
- + CustomGuard::report_status();
97
- },
98
- py::call_guard<DependentGuard, CustomGuard>());
99
-
100
- #if defined(WITH_THREAD) && !defined(PYPY_VERSION)
101
- // `py::call_guard<py::gil_scoped_release>()` should work in PyPy as well,
102
- // but it's unclear how to test it without `PyGILState_GetThisThreadState`.
103
- auto report_gil_status = []() {
104
- auto is_gil_held = false;
105
- if (auto *tstate = py::detail::get_thread_state_unchecked()) {
106
- is_gil_held = (tstate == PyGILState_GetThisThreadState());
107
- }
108
-
109
- return is_gil_held ? "GIL held" : "GIL released";
110
- };
111
-
112
- m.def("with_gil", report_gil_status);
113
- m.def("without_gil", report_gil_status, py::call_guard<py::gil_scoped_release>());
114
- #endif
115
- }
 
1
+ /*
2
+ tests/test_call_policies.cpp -- keep_alive and call_guard
3
+
4
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include "pybind11_tests.h"
11
+
12
+ struct CustomGuard {
13
+ static bool enabled;
14
+
15
+ CustomGuard() { enabled = true; }
16
+ ~CustomGuard() { enabled = false; }
17
+
18
+ static const char *report_status() { return enabled ? "guarded" : "unguarded"; }
19
+ };
20
+ bool CustomGuard::enabled = false;
21
+
22
+ struct DependentGuard {
23
+ static bool enabled;
24
+
25
+ DependentGuard() { enabled = CustomGuard::enabled; }
26
+ ~DependentGuard() { enabled = false; }
27
+
28
+ static const char *report_status() { return enabled ? "guarded" : "unguarded"; }
29
+ };
30
+ bool DependentGuard::enabled = false;
31
+
32
+ TEST_SUBMODULE(call_policies, m) {
33
+ // Parent/Child are used in:
34
+ // test_keep_alive_argument, test_keep_alive_return_value, test_alive_gc_derived,
35
+ // test_alive_gc_multi_derived, test_return_none, test_keep_alive_constructor
36
+ class Child {
37
+ public:
38
+ Child() { py::print("Allocating child."); }
39
+ Child(const Child &) = default;
40
+ Child(Child &&) = default;
41
+ ~Child() { py::print("Releasing child."); }
42
+ };
43
+ py::class_<Child>(m, "Child").def(py::init<>());
44
+
45
+ class Parent {
46
+ public:
47
+ Parent() { py::print("Allocating parent."); }
48
+ Parent(const Parent &parent) = default;
49
+ ~Parent() { py::print("Releasing parent."); }
50
+ void addChild(Child *) {}
51
+ Child *returnChild() { return new Child(); }
52
+ Child *returnNullChild() { return nullptr; }
53
+ static Child *staticFunction(Parent *) { return new Child(); }
54
+ };
55
+ py::class_<Parent>(m, "Parent")
56
+ .def(py::init<>())
57
+ .def(py::init([](Child *) { return new Parent(); }), py::keep_alive<1, 2>())
58
+ .def("addChild", &Parent::addChild)
59
+ .def("addChildKeepAlive", &Parent::addChild, py::keep_alive<1, 2>())
60
+ .def("returnChild", &Parent::returnChild)
61
+ .def("returnChildKeepAlive", &Parent::returnChild, py::keep_alive<1, 0>())
62
+ .def("returnNullChildKeepAliveChild", &Parent::returnNullChild, py::keep_alive<1, 0>())
63
+ .def("returnNullChildKeepAliveParent", &Parent::returnNullChild, py::keep_alive<0, 1>())
64
+ .def_static("staticFunction", &Parent::staticFunction, py::keep_alive<1, 0>());
65
+
66
+ m.def(
67
+ "free_function", [](Parent *, Child *) {}, py::keep_alive<1, 2>());
68
+ m.def(
69
+ "invalid_arg_index", [] {}, py::keep_alive<0, 1>());
70
+
71
+ #if !defined(PYPY_VERSION)
72
+ // test_alive_gc
73
+ class ParentGC : public Parent {
74
+ public:
75
+ using Parent::Parent;
76
+ };
77
+ py::class_<ParentGC, Parent>(m, "ParentGC", py::dynamic_attr()).def(py::init<>());
78
+ #endif
79
+
80
+ // test_call_guard
81
+ m.def("unguarded_call", &CustomGuard::report_status);
82
+ m.def("guarded_call", &CustomGuard::report_status, py::call_guard<CustomGuard>());
83
+
84
+ m.def(
85
+ "multiple_guards_correct_order",
86
+ []() {
87
+ return CustomGuard::report_status() + std::string(" & ")
88
+ + DependentGuard::report_status();
89
+ },
90
+ py::call_guard<CustomGuard, DependentGuard>());
91
+
92
+ m.def(
93
+ "multiple_guards_wrong_order",
94
+ []() {
95
+ return DependentGuard::report_status() + std::string(" & ")
96
+ + CustomGuard::report_status();
97
+ },
98
+ py::call_guard<DependentGuard, CustomGuard>());
99
+
100
+ #if defined(WITH_THREAD) && !defined(PYPY_VERSION)
101
+ // `py::call_guard<py::gil_scoped_release>()` should work in PyPy as well,
102
+ // but it's unclear how to test it without `PyGILState_GetThisThreadState`.
103
+ auto report_gil_status = []() {
104
+ auto is_gil_held = false;
105
+ if (auto *tstate = py::detail::get_thread_state_unchecked()) {
106
+ is_gil_held = (tstate == PyGILState_GetThisThreadState());
107
+ }
108
+
109
+ return is_gil_held ? "GIL held" : "GIL released";
110
+ };
111
+
112
+ m.def("with_gil", report_gil_status);
113
+ m.def("without_gil", report_gil_status, py::call_guard<py::gil_scoped_release>());
114
+ #endif
115
+ }
third_party/CityFlow/extern/pybind11/tests/test_call_policies.py CHANGED
@@ -1,247 +1,247 @@
1
- import pytest
2
-
3
- import env # noqa: F401
4
- from pybind11_tests import ConstructorStats
5
- from pybind11_tests import call_policies as m
6
-
7
-
8
- @pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False)
9
- def test_keep_alive_argument(capture):
10
- n_inst = ConstructorStats.detail_reg_inst()
11
- with capture:
12
- p = m.Parent()
13
- assert capture == "Allocating parent."
14
- with capture:
15
- p.addChild(m.Child())
16
- assert ConstructorStats.detail_reg_inst() == n_inst + 1
17
- assert (
18
- capture
19
- == """
20
- Allocating child.
21
- Releasing child.
22
- """
23
- )
24
- with capture:
25
- del p
26
- assert ConstructorStats.detail_reg_inst() == n_inst
27
- assert capture == "Releasing parent."
28
-
29
- with capture:
30
- p = m.Parent()
31
- assert capture == "Allocating parent."
32
- with capture:
33
- p.addChildKeepAlive(m.Child())
34
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
35
- assert capture == "Allocating child."
36
- with capture:
37
- del p
38
- assert ConstructorStats.detail_reg_inst() == n_inst
39
- assert (
40
- capture
41
- == """
42
- Releasing parent.
43
- Releasing child.
44
- """
45
- )
46
-
47
- p = m.Parent()
48
- c = m.Child()
49
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
50
- m.free_function(p, c)
51
- del c
52
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
53
- del p
54
- assert ConstructorStats.detail_reg_inst() == n_inst
55
-
56
- with pytest.raises(RuntimeError) as excinfo:
57
- m.invalid_arg_index()
58
- assert str(excinfo.value) == "Could not activate keep_alive!"
59
-
60
-
61
- def test_keep_alive_return_value(capture):
62
- n_inst = ConstructorStats.detail_reg_inst()
63
- with capture:
64
- p = m.Parent()
65
- assert capture == "Allocating parent."
66
- with capture:
67
- p.returnChild()
68
- assert ConstructorStats.detail_reg_inst() == n_inst + 1
69
- assert (
70
- capture
71
- == """
72
- Allocating child.
73
- Releasing child.
74
- """
75
- )
76
- with capture:
77
- del p
78
- assert ConstructorStats.detail_reg_inst() == n_inst
79
- assert capture == "Releasing parent."
80
-
81
- with capture:
82
- p = m.Parent()
83
- assert capture == "Allocating parent."
84
- with capture:
85
- p.returnChildKeepAlive()
86
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
87
- assert capture == "Allocating child."
88
- with capture:
89
- del p
90
- assert ConstructorStats.detail_reg_inst() == n_inst
91
- assert (
92
- capture
93
- == """
94
- Releasing parent.
95
- Releasing child.
96
- """
97
- )
98
-
99
- p = m.Parent()
100
- assert ConstructorStats.detail_reg_inst() == n_inst + 1
101
- with capture:
102
- m.Parent.staticFunction(p)
103
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
104
- assert capture == "Allocating child."
105
- with capture:
106
- del p
107
- assert ConstructorStats.detail_reg_inst() == n_inst
108
- assert (
109
- capture
110
- == """
111
- Releasing parent.
112
- Releasing child.
113
- """
114
- )
115
-
116
-
117
- # https://foss.heptapod.net/pypy/pypy/-/issues/2447
118
- @pytest.mark.xfail("env.PYPY", reason="_PyObject_GetDictPtr is unimplemented")
119
- def test_alive_gc(capture):
120
- n_inst = ConstructorStats.detail_reg_inst()
121
- p = m.ParentGC()
122
- p.addChildKeepAlive(m.Child())
123
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
124
- lst = [p]
125
- lst.append(lst) # creates a circular reference
126
- with capture:
127
- del p, lst
128
- assert ConstructorStats.detail_reg_inst() == n_inst
129
- assert (
130
- capture
131
- == """
132
- Releasing parent.
133
- Releasing child.
134
- """
135
- )
136
-
137
-
138
- def test_alive_gc_derived(capture):
139
- class Derived(m.Parent):
140
- pass
141
-
142
- n_inst = ConstructorStats.detail_reg_inst()
143
- p = Derived()
144
- p.addChildKeepAlive(m.Child())
145
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
146
- lst = [p]
147
- lst.append(lst) # creates a circular reference
148
- with capture:
149
- del p, lst
150
- assert ConstructorStats.detail_reg_inst() == n_inst
151
- assert (
152
- capture
153
- == """
154
- Releasing parent.
155
- Releasing child.
156
- """
157
- )
158
-
159
-
160
- def test_alive_gc_multi_derived(capture):
161
- class Derived(m.Parent, m.Child):
162
- def __init__(self):
163
- m.Parent.__init__(self)
164
- m.Child.__init__(self)
165
-
166
- n_inst = ConstructorStats.detail_reg_inst()
167
- p = Derived()
168
- p.addChildKeepAlive(m.Child())
169
- # +3 rather than +2 because Derived corresponds to two registered instances
170
- assert ConstructorStats.detail_reg_inst() == n_inst + 3
171
- lst = [p]
172
- lst.append(lst) # creates a circular reference
173
- with capture:
174
- del p, lst
175
- assert ConstructorStats.detail_reg_inst() == n_inst
176
- assert (
177
- capture
178
- == """
179
- Releasing parent.
180
- Releasing child.
181
- Releasing child.
182
- """
183
- )
184
-
185
-
186
- def test_return_none(capture):
187
- n_inst = ConstructorStats.detail_reg_inst()
188
- with capture:
189
- p = m.Parent()
190
- assert capture == "Allocating parent."
191
- with capture:
192
- p.returnNullChildKeepAliveChild()
193
- assert ConstructorStats.detail_reg_inst() == n_inst + 1
194
- assert capture == ""
195
- with capture:
196
- del p
197
- assert ConstructorStats.detail_reg_inst() == n_inst
198
- assert capture == "Releasing parent."
199
-
200
- with capture:
201
- p = m.Parent()
202
- assert capture == "Allocating parent."
203
- with capture:
204
- p.returnNullChildKeepAliveParent()
205
- assert ConstructorStats.detail_reg_inst() == n_inst + 1
206
- assert capture == ""
207
- with capture:
208
- del p
209
- assert ConstructorStats.detail_reg_inst() == n_inst
210
- assert capture == "Releasing parent."
211
-
212
-
213
- def test_keep_alive_constructor(capture):
214
- n_inst = ConstructorStats.detail_reg_inst()
215
-
216
- with capture:
217
- p = m.Parent(m.Child())
218
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
219
- assert (
220
- capture
221
- == """
222
- Allocating child.
223
- Allocating parent.
224
- """
225
- )
226
- with capture:
227
- del p
228
- assert ConstructorStats.detail_reg_inst() == n_inst
229
- assert (
230
- capture
231
- == """
232
- Releasing parent.
233
- Releasing child.
234
- """
235
- )
236
-
237
-
238
- def test_call_guard():
239
- assert m.unguarded_call() == "unguarded"
240
- assert m.guarded_call() == "guarded"
241
-
242
- assert m.multiple_guards_correct_order() == "guarded & guarded"
243
- assert m.multiple_guards_wrong_order() == "unguarded & guarded"
244
-
245
- if hasattr(m, "with_gil"):
246
- assert m.with_gil() == "GIL held"
247
- assert m.without_gil() == "GIL released"
 
1
+ import pytest
2
+
3
+ import env # noqa: F401
4
+ from pybind11_tests import ConstructorStats
5
+ from pybind11_tests import call_policies as m
6
+
7
+
8
+ @pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False)
9
+ def test_keep_alive_argument(capture):
10
+ n_inst = ConstructorStats.detail_reg_inst()
11
+ with capture:
12
+ p = m.Parent()
13
+ assert capture == "Allocating parent."
14
+ with capture:
15
+ p.addChild(m.Child())
16
+ assert ConstructorStats.detail_reg_inst() == n_inst + 1
17
+ assert (
18
+ capture
19
+ == """
20
+ Allocating child.
21
+ Releasing child.
22
+ """
23
+ )
24
+ with capture:
25
+ del p
26
+ assert ConstructorStats.detail_reg_inst() == n_inst
27
+ assert capture == "Releasing parent."
28
+
29
+ with capture:
30
+ p = m.Parent()
31
+ assert capture == "Allocating parent."
32
+ with capture:
33
+ p.addChildKeepAlive(m.Child())
34
+ assert ConstructorStats.detail_reg_inst() == n_inst + 2
35
+ assert capture == "Allocating child."
36
+ with capture:
37
+ del p
38
+ assert ConstructorStats.detail_reg_inst() == n_inst
39
+ assert (
40
+ capture
41
+ == """
42
+ Releasing parent.
43
+ Releasing child.
44
+ """
45
+ )
46
+
47
+ p = m.Parent()
48
+ c = m.Child()
49
+ assert ConstructorStats.detail_reg_inst() == n_inst + 2
50
+ m.free_function(p, c)
51
+ del c
52
+ assert ConstructorStats.detail_reg_inst() == n_inst + 2
53
+ del p
54
+ assert ConstructorStats.detail_reg_inst() == n_inst
55
+
56
+ with pytest.raises(RuntimeError) as excinfo:
57
+ m.invalid_arg_index()
58
+ assert str(excinfo.value) == "Could not activate keep_alive!"
59
+
60
+
61
+ def test_keep_alive_return_value(capture):
62
+ n_inst = ConstructorStats.detail_reg_inst()
63
+ with capture:
64
+ p = m.Parent()
65
+ assert capture == "Allocating parent."
66
+ with capture:
67
+ p.returnChild()
68
+ assert ConstructorStats.detail_reg_inst() == n_inst + 1
69
+ assert (
70
+ capture
71
+ == """
72
+ Allocating child.
73
+ Releasing child.
74
+ """
75
+ )
76
+ with capture:
77
+ del p
78
+ assert ConstructorStats.detail_reg_inst() == n_inst
79
+ assert capture == "Releasing parent."
80
+
81
+ with capture:
82
+ p = m.Parent()
83
+ assert capture == "Allocating parent."
84
+ with capture:
85
+ p.returnChildKeepAlive()
86
+ assert ConstructorStats.detail_reg_inst() == n_inst + 2
87
+ assert capture == "Allocating child."
88
+ with capture:
89
+ del p
90
+ assert ConstructorStats.detail_reg_inst() == n_inst
91
+ assert (
92
+ capture
93
+ == """
94
+ Releasing parent.
95
+ Releasing child.
96
+ """
97
+ )
98
+
99
+ p = m.Parent()
100
+ assert ConstructorStats.detail_reg_inst() == n_inst + 1
101
+ with capture:
102
+ m.Parent.staticFunction(p)
103
+ assert ConstructorStats.detail_reg_inst() == n_inst + 2
104
+ assert capture == "Allocating child."
105
+ with capture:
106
+ del p
107
+ assert ConstructorStats.detail_reg_inst() == n_inst
108
+ assert (
109
+ capture
110
+ == """
111
+ Releasing parent.
112
+ Releasing child.
113
+ """
114
+ )
115
+
116
+
117
+ # https://foss.heptapod.net/pypy/pypy/-/issues/2447
118
+ @pytest.mark.xfail("env.PYPY", reason="_PyObject_GetDictPtr is unimplemented")
119
+ def test_alive_gc(capture):
120
+ n_inst = ConstructorStats.detail_reg_inst()
121
+ p = m.ParentGC()
122
+ p.addChildKeepAlive(m.Child())
123
+ assert ConstructorStats.detail_reg_inst() == n_inst + 2
124
+ lst = [p]
125
+ lst.append(lst) # creates a circular reference
126
+ with capture:
127
+ del p, lst
128
+ assert ConstructorStats.detail_reg_inst() == n_inst
129
+ assert (
130
+ capture
131
+ == """
132
+ Releasing parent.
133
+ Releasing child.
134
+ """
135
+ )
136
+
137
+
138
+ def test_alive_gc_derived(capture):
139
+ class Derived(m.Parent):
140
+ pass
141
+
142
+ n_inst = ConstructorStats.detail_reg_inst()
143
+ p = Derived()
144
+ p.addChildKeepAlive(m.Child())
145
+ assert ConstructorStats.detail_reg_inst() == n_inst + 2
146
+ lst = [p]
147
+ lst.append(lst) # creates a circular reference
148
+ with capture:
149
+ del p, lst
150
+ assert ConstructorStats.detail_reg_inst() == n_inst
151
+ assert (
152
+ capture
153
+ == """
154
+ Releasing parent.
155
+ Releasing child.
156
+ """
157
+ )
158
+
159
+
160
+ def test_alive_gc_multi_derived(capture):
161
+ class Derived(m.Parent, m.Child):
162
+ def __init__(self):
163
+ m.Parent.__init__(self)
164
+ m.Child.__init__(self)
165
+
166
+ n_inst = ConstructorStats.detail_reg_inst()
167
+ p = Derived()
168
+ p.addChildKeepAlive(m.Child())
169
+ # +3 rather than +2 because Derived corresponds to two registered instances
170
+ assert ConstructorStats.detail_reg_inst() == n_inst + 3
171
+ lst = [p]
172
+ lst.append(lst) # creates a circular reference
173
+ with capture:
174
+ del p, lst
175
+ assert ConstructorStats.detail_reg_inst() == n_inst
176
+ assert (
177
+ capture
178
+ == """
179
+ Releasing parent.
180
+ Releasing child.
181
+ Releasing child.
182
+ """
183
+ )
184
+
185
+
186
+ def test_return_none(capture):
187
+ n_inst = ConstructorStats.detail_reg_inst()
188
+ with capture:
189
+ p = m.Parent()
190
+ assert capture == "Allocating parent."
191
+ with capture:
192
+ p.returnNullChildKeepAliveChild()
193
+ assert ConstructorStats.detail_reg_inst() == n_inst + 1
194
+ assert capture == ""
195
+ with capture:
196
+ del p
197
+ assert ConstructorStats.detail_reg_inst() == n_inst
198
+ assert capture == "Releasing parent."
199
+
200
+ with capture:
201
+ p = m.Parent()
202
+ assert capture == "Allocating parent."
203
+ with capture:
204
+ p.returnNullChildKeepAliveParent()
205
+ assert ConstructorStats.detail_reg_inst() == n_inst + 1
206
+ assert capture == ""
207
+ with capture:
208
+ del p
209
+ assert ConstructorStats.detail_reg_inst() == n_inst
210
+ assert capture == "Releasing parent."
211
+
212
+
213
+ def test_keep_alive_constructor(capture):
214
+ n_inst = ConstructorStats.detail_reg_inst()
215
+
216
+ with capture:
217
+ p = m.Parent(m.Child())
218
+ assert ConstructorStats.detail_reg_inst() == n_inst + 2
219
+ assert (
220
+ capture
221
+ == """
222
+ Allocating child.
223
+ Allocating parent.
224
+ """
225
+ )
226
+ with capture:
227
+ del p
228
+ assert ConstructorStats.detail_reg_inst() == n_inst
229
+ assert (
230
+ capture
231
+ == """
232
+ Releasing parent.
233
+ Releasing child.
234
+ """
235
+ )
236
+
237
+
238
+ def test_call_guard():
239
+ assert m.unguarded_call() == "unguarded"
240
+ assert m.guarded_call() == "guarded"
241
+
242
+ assert m.multiple_guards_correct_order() == "guarded & guarded"
243
+ assert m.multiple_guards_wrong_order() == "unguarded & guarded"
244
+
245
+ if hasattr(m, "with_gil"):
246
+ assert m.with_gil() == "GIL held"
247
+ assert m.without_gil() == "GIL released"
third_party/CityFlow/extern/pybind11/tests/test_callbacks.cpp CHANGED
@@ -1,280 +1,280 @@
1
- /*
2
- tests/test_callbacks.cpp -- callbacks
3
-
4
- Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include <pybind11/functional.h>
11
-
12
- #include "constructor_stats.h"
13
- #include "pybind11_tests.h"
14
-
15
- #include <thread>
16
-
17
- int dummy_function(int i) { return i + 1; }
18
-
19
- TEST_SUBMODULE(callbacks, m) {
20
- // test_callbacks, test_function_signatures
21
- m.def("test_callback1", [](const py::object &func) { return func(); });
22
- m.def("test_callback2", [](const py::object &func) { return func("Hello", 'x', true, 5); });
23
- m.def("test_callback3", [](const std::function<int(int)> &func) {
24
- return "func(43) = " + std::to_string(func(43));
25
- });
26
- m.def("test_callback4",
27
- []() -> std::function<int(int)> { return [](int i) { return i + 1; }; });
28
- m.def("test_callback5",
29
- []() { return py::cpp_function([](int i) { return i + 1; }, py::arg("number")); });
30
-
31
- // test_keyword_args_and_generalized_unpacking
32
- m.def("test_tuple_unpacking", [](const py::function &f) {
33
- auto t1 = py::make_tuple(2, 3);
34
- auto t2 = py::make_tuple(5, 6);
35
- return f("positional", 1, *t1, 4, *t2);
36
- });
37
-
38
- m.def("test_dict_unpacking", [](const py::function &f) {
39
- auto d1 = py::dict("key"_a = "value", "a"_a = 1);
40
- auto d2 = py::dict();
41
- auto d3 = py::dict("b"_a = 2);
42
- return f("positional", 1, **d1, **d2, **d3);
43
- });
44
-
45
- m.def("test_keyword_args", [](const py::function &f) { return f("x"_a = 10, "y"_a = 20); });
46
-
47
- m.def("test_unpacking_and_keywords1", [](const py::function &f) {
48
- auto args = py::make_tuple(2);
49
- auto kwargs = py::dict("d"_a = 4);
50
- return f(1, *args, "c"_a = 3, **kwargs);
51
- });
52
-
53
- m.def("test_unpacking_and_keywords2", [](const py::function &f) {
54
- auto kwargs1 = py::dict("a"_a = 1);
55
- auto kwargs2 = py::dict("c"_a = 3, "d"_a = 4);
56
- return f("positional",
57
- *py::make_tuple(1),
58
- 2,
59
- *py::make_tuple(3, 4),
60
- 5,
61
- "key"_a = "value",
62
- **kwargs1,
63
- "b"_a = 2,
64
- **kwargs2,
65
- "e"_a = 5);
66
- });
67
-
68
- m.def("test_unpacking_error1", [](const py::function &f) {
69
- auto kwargs = py::dict("x"_a = 3);
70
- return f("x"_a = 1, "y"_a = 2, **kwargs); // duplicate ** after keyword
71
- });
72
-
73
- m.def("test_unpacking_error2", [](const py::function &f) {
74
- auto kwargs = py::dict("x"_a = 3);
75
- return f(**kwargs, "x"_a = 1); // duplicate keyword after **
76
- });
77
-
78
- m.def("test_arg_conversion_error1",
79
- [](const py::function &f) { f(234, UnregisteredType(), "kw"_a = 567); });
80
-
81
- m.def("test_arg_conversion_error2", [](const py::function &f) {
82
- f(234, "expected_name"_a = UnregisteredType(), "kw"_a = 567);
83
- });
84
-
85
- // test_lambda_closure_cleanup
86
- struct Payload {
87
- Payload() { print_default_created(this); }
88
- ~Payload() { print_destroyed(this); }
89
- Payload(const Payload &) { print_copy_created(this); }
90
- Payload(Payload &&) noexcept { print_move_created(this); }
91
- };
92
- // Export the payload constructor statistics for testing purposes:
93
- m.def("payload_cstats", &ConstructorStats::get<Payload>);
94
- m.def("test_lambda_closure_cleanup", []() -> std::function<void()> {
95
- Payload p;
96
-
97
- // In this situation, `Func` in the implementation of
98
- // `cpp_function::initialize` is NOT trivially destructible.
99
- return [p]() {
100
- /* p should be cleaned up when the returned function is garbage collected */
101
- (void) p;
102
- };
103
- });
104
-
105
- class CppCallable {
106
- public:
107
- CppCallable() { track_default_created(this); }
108
- ~CppCallable() { track_destroyed(this); }
109
- CppCallable(const CppCallable &) { track_copy_created(this); }
110
- CppCallable(CppCallable &&) noexcept { track_move_created(this); }
111
- void operator()() {}
112
- };
113
-
114
- m.def("test_cpp_callable_cleanup", []() {
115
- // Related issue: https://github.com/pybind/pybind11/issues/3228
116
- // Related PR: https://github.com/pybind/pybind11/pull/3229
117
- py::list alive_counts;
118
- ConstructorStats &stat = ConstructorStats::get<CppCallable>();
119
- alive_counts.append(stat.alive());
120
- {
121
- CppCallable cpp_callable;
122
- alive_counts.append(stat.alive());
123
- {
124
- // In this situation, `Func` in the implementation of
125
- // `cpp_function::initialize` IS trivially destructible,
126
- // only `capture` is not.
127
- py::cpp_function py_func(cpp_callable);
128
- py::detail::silence_unused_warnings(py_func);
129
- alive_counts.append(stat.alive());
130
- }
131
- alive_counts.append(stat.alive());
132
- {
133
- py::cpp_function py_func(std::move(cpp_callable));
134
- py::detail::silence_unused_warnings(py_func);
135
- alive_counts.append(stat.alive());
136
- }
137
- alive_counts.append(stat.alive());
138
- }
139
- alive_counts.append(stat.alive());
140
- return alive_counts;
141
- });
142
-
143
- // test_cpp_function_roundtrip
144
- /* Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer */
145
- m.def("dummy_function", &dummy_function);
146
- m.def("dummy_function_overloaded", [](int i, int j) { return i + j; });
147
- m.def("dummy_function_overloaded", &dummy_function);
148
- m.def("dummy_function2", [](int i, int j) { return i + j; });
149
- m.def(
150
- "roundtrip",
151
- [](std::function<int(int)> f, bool expect_none = false) {
152
- if (expect_none && f) {
153
- throw std::runtime_error("Expected None to be converted to empty std::function");
154
- }
155
- return f;
156
- },
157
- py::arg("f"),
158
- py::arg("expect_none") = false);
159
- m.def("test_dummy_function", [](const std::function<int(int)> &f) -> std::string {
160
- using fn_type = int (*)(int);
161
- const auto *result = f.target<fn_type>();
162
- if (!result) {
163
- auto r = f(1);
164
- return "can't convert to function pointer: eval(1) = " + std::to_string(r);
165
- }
166
- if (*result == dummy_function) {
167
- auto r = (*result)(1);
168
- return "matches dummy_function: eval(1) = " + std::to_string(r);
169
- }
170
- return "argument does NOT match dummy_function. This should never happen!";
171
- });
172
-
173
- class AbstractBase {
174
- public:
175
- // [workaround(intel)] = default does not work here
176
- // Defaulting this destructor results in linking errors with the Intel compiler
177
- // (in Debug builds only, tested with icpc (ICC) 2021.1 Beta 20200827)
178
- virtual ~AbstractBase() {} // NOLINT(modernize-use-equals-default)
179
- virtual unsigned int func() = 0;
180
- };
181
- m.def("func_accepting_func_accepting_base",
182
- [](const std::function<double(AbstractBase &)> &) {});
183
-
184
- struct MovableObject {
185
- bool valid = true;
186
-
187
- MovableObject() = default;
188
- MovableObject(const MovableObject &) = default;
189
- MovableObject &operator=(const MovableObject &) = default;
190
- MovableObject(MovableObject &&o) noexcept : valid(o.valid) { o.valid = false; }
191
- MovableObject &operator=(MovableObject &&o) noexcept {
192
- valid = o.valid;
193
- o.valid = false;
194
- return *this;
195
- }
196
- };
197
- py::class_<MovableObject>(m, "MovableObject");
198
-
199
- // test_movable_object
200
- m.def("callback_with_movable", [](const std::function<void(MovableObject &)> &f) {
201
- auto x = MovableObject();
202
- f(x); // lvalue reference shouldn't move out object
203
- return x.valid; // must still return `true`
204
- });
205
-
206
- // test_bound_method_callback
207
- struct CppBoundMethodTest {};
208
- py::class_<CppBoundMethodTest>(m, "CppBoundMethodTest")
209
- .def(py::init<>())
210
- .def("triple", [](CppBoundMethodTest &, int val) { return 3 * val; });
211
-
212
- // This checks that builtin functions can be passed as callbacks
213
- // rather than throwing RuntimeError due to trying to extract as capsule
214
- m.def("test_sum_builtin",
215
- [](const std::function<double(py::iterable)> &sum_builtin, const py::iterable &i) {
216
- return sum_builtin(i);
217
- });
218
-
219
- // test async Python callbacks
220
- using callback_f = std::function<void(int)>;
221
- m.def("test_async_callback", [](const callback_f &f, const py::list &work) {
222
- // make detached thread that calls `f` with piece of work after a little delay
223
- auto start_f = [f](int j) {
224
- auto invoke_f = [f, j] {
225
- std::this_thread::sleep_for(std::chrono::milliseconds(50));
226
- f(j);
227
- };
228
- auto t = std::thread(std::move(invoke_f));
229
- t.detach();
230
- };
231
-
232
- // spawn worker threads
233
- for (auto i : work) {
234
- start_f(py::cast<int>(i));
235
- }
236
- });
237
-
238
- m.def("callback_num_times", [](const py::function &f, std::size_t num) {
239
- for (std::size_t i = 0; i < num; i++) {
240
- f();
241
- }
242
- });
243
-
244
- auto *custom_def = []() {
245
- static PyMethodDef def;
246
- def.ml_name = "example_name";
247
- def.ml_doc = "Example doc";
248
- def.ml_meth = [](PyObject *, PyObject *args) -> PyObject * {
249
- if (PyTuple_Size(args) != 1) {
250
- throw std::runtime_error("Invalid number of arguments for example_name");
251
- }
252
- PyObject *first = PyTuple_GetItem(args, 0);
253
- if (!PyLong_Check(first)) {
254
- throw std::runtime_error("Invalid argument to example_name");
255
- }
256
- auto result = py::cast(PyLong_AsLong(first) * 9);
257
- return result.release().ptr();
258
- };
259
- def.ml_flags = METH_VARARGS;
260
- return &def;
261
- }();
262
-
263
- // rec_capsule with name that has the same value (but not pointer) as our internal one
264
- // This capsule should be detected by our code as foreign and not inspected as the pointers
265
- // shouldn't match
266
- constexpr const char *rec_capsule_name
267
- = pybind11::detail::internals_function_record_capsule_name;
268
- py::capsule rec_capsule(std::malloc(1), [](void *data) { std::free(data); });
269
- rec_capsule.set_name(rec_capsule_name);
270
- m.add_object("custom_function", PyCFunction_New(custom_def, rec_capsule.ptr()));
271
-
272
- // This test requires a new ABI version to pass
273
- #if PYBIND11_INTERNALS_VERSION > 4
274
- // rec_capsule with nullptr name
275
- py::capsule rec_capsule2(std::malloc(1), [](void *data) { std::free(data); });
276
- m.add_object("custom_function2", PyCFunction_New(custom_def, rec_capsule2.ptr()));
277
- #else
278
- m.add_object("custom_function2", py::none());
279
- #endif
280
- }
 
1
+ /*
2
+ tests/test_callbacks.cpp -- callbacks
3
+
4
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include <pybind11/functional.h>
11
+
12
+ #include "constructor_stats.h"
13
+ #include "pybind11_tests.h"
14
+
15
+ #include <thread>
16
+
17
+ int dummy_function(int i) { return i + 1; }
18
+
19
+ TEST_SUBMODULE(callbacks, m) {
20
+ // test_callbacks, test_function_signatures
21
+ m.def("test_callback1", [](const py::object &func) { return func(); });
22
+ m.def("test_callback2", [](const py::object &func) { return func("Hello", 'x', true, 5); });
23
+ m.def("test_callback3", [](const std::function<int(int)> &func) {
24
+ return "func(43) = " + std::to_string(func(43));
25
+ });
26
+ m.def("test_callback4",
27
+ []() -> std::function<int(int)> { return [](int i) { return i + 1; }; });
28
+ m.def("test_callback5",
29
+ []() { return py::cpp_function([](int i) { return i + 1; }, py::arg("number")); });
30
+
31
+ // test_keyword_args_and_generalized_unpacking
32
+ m.def("test_tuple_unpacking", [](const py::function &f) {
33
+ auto t1 = py::make_tuple(2, 3);
34
+ auto t2 = py::make_tuple(5, 6);
35
+ return f("positional", 1, *t1, 4, *t2);
36
+ });
37
+
38
+ m.def("test_dict_unpacking", [](const py::function &f) {
39
+ auto d1 = py::dict("key"_a = "value", "a"_a = 1);
40
+ auto d2 = py::dict();
41
+ auto d3 = py::dict("b"_a = 2);
42
+ return f("positional", 1, **d1, **d2, **d3);
43
+ });
44
+
45
+ m.def("test_keyword_args", [](const py::function &f) { return f("x"_a = 10, "y"_a = 20); });
46
+
47
+ m.def("test_unpacking_and_keywords1", [](const py::function &f) {
48
+ auto args = py::make_tuple(2);
49
+ auto kwargs = py::dict("d"_a = 4);
50
+ return f(1, *args, "c"_a = 3, **kwargs);
51
+ });
52
+
53
+ m.def("test_unpacking_and_keywords2", [](const py::function &f) {
54
+ auto kwargs1 = py::dict("a"_a = 1);
55
+ auto kwargs2 = py::dict("c"_a = 3, "d"_a = 4);
56
+ return f("positional",
57
+ *py::make_tuple(1),
58
+ 2,
59
+ *py::make_tuple(3, 4),
60
+ 5,
61
+ "key"_a = "value",
62
+ **kwargs1,
63
+ "b"_a = 2,
64
+ **kwargs2,
65
+ "e"_a = 5);
66
+ });
67
+
68
+ m.def("test_unpacking_error1", [](const py::function &f) {
69
+ auto kwargs = py::dict("x"_a = 3);
70
+ return f("x"_a = 1, "y"_a = 2, **kwargs); // duplicate ** after keyword
71
+ });
72
+
73
+ m.def("test_unpacking_error2", [](const py::function &f) {
74
+ auto kwargs = py::dict("x"_a = 3);
75
+ return f(**kwargs, "x"_a = 1); // duplicate keyword after **
76
+ });
77
+
78
+ m.def("test_arg_conversion_error1",
79
+ [](const py::function &f) { f(234, UnregisteredType(), "kw"_a = 567); });
80
+
81
+ m.def("test_arg_conversion_error2", [](const py::function &f) {
82
+ f(234, "expected_name"_a = UnregisteredType(), "kw"_a = 567);
83
+ });
84
+
85
+ // test_lambda_closure_cleanup
86
+ struct Payload {
87
+ Payload() { print_default_created(this); }
88
+ ~Payload() { print_destroyed(this); }
89
+ Payload(const Payload &) { print_copy_created(this); }
90
+ Payload(Payload &&) noexcept { print_move_created(this); }
91
+ };
92
+ // Export the payload constructor statistics for testing purposes:
93
+ m.def("payload_cstats", &ConstructorStats::get<Payload>);
94
+ m.def("test_lambda_closure_cleanup", []() -> std::function<void()> {
95
+ Payload p;
96
+
97
+ // In this situation, `Func` in the implementation of
98
+ // `cpp_function::initialize` is NOT trivially destructible.
99
+ return [p]() {
100
+ /* p should be cleaned up when the returned function is garbage collected */
101
+ (void) p;
102
+ };
103
+ });
104
+
105
+ class CppCallable {
106
+ public:
107
+ CppCallable() { track_default_created(this); }
108
+ ~CppCallable() { track_destroyed(this); }
109
+ CppCallable(const CppCallable &) { track_copy_created(this); }
110
+ CppCallable(CppCallable &&) noexcept { track_move_created(this); }
111
+ void operator()() {}
112
+ };
113
+
114
+ m.def("test_cpp_callable_cleanup", []() {
115
+ // Related issue: https://github.com/pybind/pybind11/issues/3228
116
+ // Related PR: https://github.com/pybind/pybind11/pull/3229
117
+ py::list alive_counts;
118
+ ConstructorStats &stat = ConstructorStats::get<CppCallable>();
119
+ alive_counts.append(stat.alive());
120
+ {
121
+ CppCallable cpp_callable;
122
+ alive_counts.append(stat.alive());
123
+ {
124
+ // In this situation, `Func` in the implementation of
125
+ // `cpp_function::initialize` IS trivially destructible,
126
+ // only `capture` is not.
127
+ py::cpp_function py_func(cpp_callable);
128
+ py::detail::silence_unused_warnings(py_func);
129
+ alive_counts.append(stat.alive());
130
+ }
131
+ alive_counts.append(stat.alive());
132
+ {
133
+ py::cpp_function py_func(std::move(cpp_callable));
134
+ py::detail::silence_unused_warnings(py_func);
135
+ alive_counts.append(stat.alive());
136
+ }
137
+ alive_counts.append(stat.alive());
138
+ }
139
+ alive_counts.append(stat.alive());
140
+ return alive_counts;
141
+ });
142
+
143
+ // test_cpp_function_roundtrip
144
+ /* Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer */
145
+ m.def("dummy_function", &dummy_function);
146
+ m.def("dummy_function_overloaded", [](int i, int j) { return i + j; });
147
+ m.def("dummy_function_overloaded", &dummy_function);
148
+ m.def("dummy_function2", [](int i, int j) { return i + j; });
149
+ m.def(
150
+ "roundtrip",
151
+ [](std::function<int(int)> f, bool expect_none = false) {
152
+ if (expect_none && f) {
153
+ throw std::runtime_error("Expected None to be converted to empty std::function");
154
+ }
155
+ return f;
156
+ },
157
+ py::arg("f"),
158
+ py::arg("expect_none") = false);
159
+ m.def("test_dummy_function", [](const std::function<int(int)> &f) -> std::string {
160
+ using fn_type = int (*)(int);
161
+ const auto *result = f.target<fn_type>();
162
+ if (!result) {
163
+ auto r = f(1);
164
+ return "can't convert to function pointer: eval(1) = " + std::to_string(r);
165
+ }
166
+ if (*result == dummy_function) {
167
+ auto r = (*result)(1);
168
+ return "matches dummy_function: eval(1) = " + std::to_string(r);
169
+ }
170
+ return "argument does NOT match dummy_function. This should never happen!";
171
+ });
172
+
173
+ class AbstractBase {
174
+ public:
175
+ // [workaround(intel)] = default does not work here
176
+ // Defaulting this destructor results in linking errors with the Intel compiler
177
+ // (in Debug builds only, tested with icpc (ICC) 2021.1 Beta 20200827)
178
+ virtual ~AbstractBase() {} // NOLINT(modernize-use-equals-default)
179
+ virtual unsigned int func() = 0;
180
+ };
181
+ m.def("func_accepting_func_accepting_base",
182
+ [](const std::function<double(AbstractBase &)> &) {});
183
+
184
+ struct MovableObject {
185
+ bool valid = true;
186
+
187
+ MovableObject() = default;
188
+ MovableObject(const MovableObject &) = default;
189
+ MovableObject &operator=(const MovableObject &) = default;
190
+ MovableObject(MovableObject &&o) noexcept : valid(o.valid) { o.valid = false; }
191
+ MovableObject &operator=(MovableObject &&o) noexcept {
192
+ valid = o.valid;
193
+ o.valid = false;
194
+ return *this;
195
+ }
196
+ };
197
+ py::class_<MovableObject>(m, "MovableObject");
198
+
199
+ // test_movable_object
200
+ m.def("callback_with_movable", [](const std::function<void(MovableObject &)> &f) {
201
+ auto x = MovableObject();
202
+ f(x); // lvalue reference shouldn't move out object
203
+ return x.valid; // must still return `true`
204
+ });
205
+
206
+ // test_bound_method_callback
207
+ struct CppBoundMethodTest {};
208
+ py::class_<CppBoundMethodTest>(m, "CppBoundMethodTest")
209
+ .def(py::init<>())
210
+ .def("triple", [](CppBoundMethodTest &, int val) { return 3 * val; });
211
+
212
+ // This checks that builtin functions can be passed as callbacks
213
+ // rather than throwing RuntimeError due to trying to extract as capsule
214
+ m.def("test_sum_builtin",
215
+ [](const std::function<double(py::iterable)> &sum_builtin, const py::iterable &i) {
216
+ return sum_builtin(i);
217
+ });
218
+
219
+ // test async Python callbacks
220
+ using callback_f = std::function<void(int)>;
221
+ m.def("test_async_callback", [](const callback_f &f, const py::list &work) {
222
+ // make detached thread that calls `f` with piece of work after a little delay
223
+ auto start_f = [f](int j) {
224
+ auto invoke_f = [f, j] {
225
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
226
+ f(j);
227
+ };
228
+ auto t = std::thread(std::move(invoke_f));
229
+ t.detach();
230
+ };
231
+
232
+ // spawn worker threads
233
+ for (auto i : work) {
234
+ start_f(py::cast<int>(i));
235
+ }
236
+ });
237
+
238
+ m.def("callback_num_times", [](const py::function &f, std::size_t num) {
239
+ for (std::size_t i = 0; i < num; i++) {
240
+ f();
241
+ }
242
+ });
243
+
244
+ auto *custom_def = []() {
245
+ static PyMethodDef def;
246
+ def.ml_name = "example_name";
247
+ def.ml_doc = "Example doc";
248
+ def.ml_meth = [](PyObject *, PyObject *args) -> PyObject * {
249
+ if (PyTuple_Size(args) != 1) {
250
+ throw std::runtime_error("Invalid number of arguments for example_name");
251
+ }
252
+ PyObject *first = PyTuple_GetItem(args, 0);
253
+ if (!PyLong_Check(first)) {
254
+ throw std::runtime_error("Invalid argument to example_name");
255
+ }
256
+ auto result = py::cast(PyLong_AsLong(first) * 9);
257
+ return result.release().ptr();
258
+ };
259
+ def.ml_flags = METH_VARARGS;
260
+ return &def;
261
+ }();
262
+
263
+ // rec_capsule with name that has the same value (but not pointer) as our internal one
264
+ // This capsule should be detected by our code as foreign and not inspected as the pointers
265
+ // shouldn't match
266
+ constexpr const char *rec_capsule_name
267
+ = pybind11::detail::internals_function_record_capsule_name;
268
+ py::capsule rec_capsule(std::malloc(1), [](void *data) { std::free(data); });
269
+ rec_capsule.set_name(rec_capsule_name);
270
+ m.add_object("custom_function", PyCFunction_New(custom_def, rec_capsule.ptr()));
271
+
272
+ // This test requires a new ABI version to pass
273
+ #if PYBIND11_INTERNALS_VERSION > 4
274
+ // rec_capsule with nullptr name
275
+ py::capsule rec_capsule2(std::malloc(1), [](void *data) { std::free(data); });
276
+ m.add_object("custom_function2", PyCFunction_New(custom_def, rec_capsule2.ptr()));
277
+ #else
278
+ m.add_object("custom_function2", py::none());
279
+ #endif
280
+ }
third_party/CityFlow/extern/pybind11/tests/test_callbacks.py CHANGED
@@ -1,225 +1,225 @@
1
- import time
2
- from threading import Thread
3
-
4
- import pytest
5
-
6
- import env # noqa: F401
7
- from pybind11_tests import callbacks as m
8
- from pybind11_tests import detailed_error_messages_enabled
9
-
10
-
11
- def test_callbacks():
12
- from functools import partial
13
-
14
- def func1():
15
- return "func1"
16
-
17
- def func2(a, b, c, d):
18
- return "func2", a, b, c, d
19
-
20
- def func3(a):
21
- return f"func3({a})"
22
-
23
- assert m.test_callback1(func1) == "func1"
24
- assert m.test_callback2(func2) == ("func2", "Hello", "x", True, 5)
25
- assert m.test_callback1(partial(func2, 1, 2, 3, 4)) == ("func2", 1, 2, 3, 4)
26
- assert m.test_callback1(partial(func3, "partial")) == "func3(partial)"
27
- assert m.test_callback3(lambda i: i + 1) == "func(43) = 44"
28
-
29
- f = m.test_callback4()
30
- assert f(43) == 44
31
- f = m.test_callback5()
32
- assert f(number=43) == 44
33
-
34
-
35
- def test_bound_method_callback():
36
- # Bound Python method:
37
- class MyClass:
38
- def double(self, val):
39
- return 2 * val
40
-
41
- z = MyClass()
42
- assert m.test_callback3(z.double) == "func(43) = 86"
43
-
44
- z = m.CppBoundMethodTest()
45
- assert m.test_callback3(z.triple) == "func(43) = 129"
46
-
47
-
48
- def test_keyword_args_and_generalized_unpacking():
49
- def f(*args, **kwargs):
50
- return args, kwargs
51
-
52
- assert m.test_tuple_unpacking(f) == (("positional", 1, 2, 3, 4, 5, 6), {})
53
- assert m.test_dict_unpacking(f) == (
54
- ("positional", 1),
55
- {"key": "value", "a": 1, "b": 2},
56
- )
57
- assert m.test_keyword_args(f) == ((), {"x": 10, "y": 20})
58
- assert m.test_unpacking_and_keywords1(f) == ((1, 2), {"c": 3, "d": 4})
59
- assert m.test_unpacking_and_keywords2(f) == (
60
- ("positional", 1, 2, 3, 4, 5),
61
- {"key": "value", "a": 1, "b": 2, "c": 3, "d": 4, "e": 5},
62
- )
63
-
64
- with pytest.raises(TypeError) as excinfo:
65
- m.test_unpacking_error1(f)
66
- assert "Got multiple values for keyword argument" in str(excinfo.value)
67
-
68
- with pytest.raises(TypeError) as excinfo:
69
- m.test_unpacking_error2(f)
70
- assert "Got multiple values for keyword argument" in str(excinfo.value)
71
-
72
- with pytest.raises(RuntimeError) as excinfo:
73
- m.test_arg_conversion_error1(f)
74
- assert str(excinfo.value) == "Unable to convert call argument " + (
75
- "'1' of type 'UnregisteredType' to Python object"
76
- if detailed_error_messages_enabled
77
- else "'1' to Python object (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"
78
- )
79
-
80
- with pytest.raises(RuntimeError) as excinfo:
81
- m.test_arg_conversion_error2(f)
82
- assert str(excinfo.value) == "Unable to convert call argument " + (
83
- "'expected_name' of type 'UnregisteredType' to Python object"
84
- if detailed_error_messages_enabled
85
- else "'expected_name' to Python object "
86
- "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"
87
- )
88
-
89
-
90
- def test_lambda_closure_cleanup():
91
- m.test_lambda_closure_cleanup()
92
- cstats = m.payload_cstats()
93
- assert cstats.alive() == 0
94
- assert cstats.copy_constructions == 1
95
- assert cstats.move_constructions >= 1
96
-
97
-
98
- def test_cpp_callable_cleanup():
99
- alive_counts = m.test_cpp_callable_cleanup()
100
- assert alive_counts == [0, 1, 2, 1, 2, 1, 0]
101
-
102
-
103
- def test_cpp_function_roundtrip():
104
- """Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer"""
105
-
106
- assert (
107
- m.test_dummy_function(m.dummy_function) == "matches dummy_function: eval(1) = 2"
108
- )
109
- assert (
110
- m.test_dummy_function(m.roundtrip(m.dummy_function))
111
- == "matches dummy_function: eval(1) = 2"
112
- )
113
- assert (
114
- m.test_dummy_function(m.dummy_function_overloaded)
115
- == "matches dummy_function: eval(1) = 2"
116
- )
117
- assert m.roundtrip(None, expect_none=True) is None
118
- assert (
119
- m.test_dummy_function(lambda x: x + 2)
120
- == "can't convert to function pointer: eval(1) = 3"
121
- )
122
-
123
- with pytest.raises(TypeError) as excinfo:
124
- m.test_dummy_function(m.dummy_function2)
125
- assert "incompatible function arguments" in str(excinfo.value)
126
-
127
- with pytest.raises(TypeError) as excinfo:
128
- m.test_dummy_function(lambda x, y: x + y)
129
- assert any(
130
- s in str(excinfo.value)
131
- for s in ("missing 1 required positional argument", "takes exactly 2 arguments")
132
- )
133
-
134
-
135
- def test_function_signatures(doc):
136
- assert doc(m.test_callback3) == "test_callback3(arg0: Callable[[int], int]) -> str"
137
- assert doc(m.test_callback4) == "test_callback4() -> Callable[[int], int]"
138
-
139
-
140
- def test_movable_object():
141
- assert m.callback_with_movable(lambda _: None) is True
142
-
143
-
144
- @pytest.mark.skipif(
145
- "env.PYPY",
146
- reason="PyPy segfaults on here. See discussion on #1413.",
147
- )
148
- def test_python_builtins():
149
- """Test if python builtins like sum() can be used as callbacks"""
150
- assert m.test_sum_builtin(sum, [1, 2, 3]) == 6
151
- assert m.test_sum_builtin(sum, []) == 0
152
-
153
-
154
- def test_async_callbacks():
155
- # serves as state for async callback
156
- class Item:
157
- def __init__(self, value):
158
- self.value = value
159
-
160
- res = []
161
-
162
- # generate stateful lambda that will store result in `res`
163
- def gen_f():
164
- s = Item(3)
165
- return lambda j: res.append(s.value + j)
166
-
167
- # do some work async
168
- work = [1, 2, 3, 4]
169
- m.test_async_callback(gen_f(), work)
170
- # wait until work is done
171
- from time import sleep
172
-
173
- sleep(0.5)
174
- assert sum(res) == sum(x + 3 for x in work)
175
-
176
-
177
- def test_async_async_callbacks():
178
- t = Thread(target=test_async_callbacks)
179
- t.start()
180
- t.join()
181
-
182
-
183
- def test_callback_num_times():
184
- # Super-simple micro-benchmarking related to PR #2919.
185
- # Example runtimes (Intel Xeon 2.2GHz, fully optimized):
186
- # num_millions 1, repeats 2: 0.1 secs
187
- # num_millions 20, repeats 10: 11.5 secs
188
- one_million = 1000000
189
- num_millions = 1 # Try 20 for actual micro-benchmarking.
190
- repeats = 2 # Try 10.
191
- rates = []
192
- for rep in range(repeats):
193
- t0 = time.time()
194
- m.callback_num_times(lambda: None, num_millions * one_million)
195
- td = time.time() - t0
196
- rate = num_millions / td if td else 0
197
- rates.append(rate)
198
- if not rep:
199
- print()
200
- print(
201
- f"callback_num_times: {num_millions:d} million / {td:.3f} seconds = {rate:.3f} million / second"
202
- )
203
- if len(rates) > 1:
204
- print("Min Mean Max")
205
- print(f"{min(rates):6.3f} {sum(rates) / len(rates):6.3f} {max(rates):6.3f}")
206
-
207
-
208
- def test_custom_func():
209
- assert m.custom_function(4) == 36
210
- assert m.roundtrip(m.custom_function)(4) == 36
211
-
212
-
213
- @pytest.mark.skipif(
214
- m.custom_function2 is None, reason="Current PYBIND11_INTERNALS_VERSION too low"
215
- )
216
- def test_custom_func2():
217
- assert m.custom_function2(3) == 27
218
- assert m.roundtrip(m.custom_function2)(3) == 27
219
-
220
-
221
- def test_callback_docstring():
222
- assert (
223
- m.test_tuple_unpacking.__doc__.strip()
224
- == "test_tuple_unpacking(arg0: Callable) -> object"
225
- )
 
1
+ import time
2
+ from threading import Thread
3
+
4
+ import pytest
5
+
6
+ import env # noqa: F401
7
+ from pybind11_tests import callbacks as m
8
+ from pybind11_tests import detailed_error_messages_enabled
9
+
10
+
11
+ def test_callbacks():
12
+ from functools import partial
13
+
14
+ def func1():
15
+ return "func1"
16
+
17
+ def func2(a, b, c, d):
18
+ return "func2", a, b, c, d
19
+
20
+ def func3(a):
21
+ return f"func3({a})"
22
+
23
+ assert m.test_callback1(func1) == "func1"
24
+ assert m.test_callback2(func2) == ("func2", "Hello", "x", True, 5)
25
+ assert m.test_callback1(partial(func2, 1, 2, 3, 4)) == ("func2", 1, 2, 3, 4)
26
+ assert m.test_callback1(partial(func3, "partial")) == "func3(partial)"
27
+ assert m.test_callback3(lambda i: i + 1) == "func(43) = 44"
28
+
29
+ f = m.test_callback4()
30
+ assert f(43) == 44
31
+ f = m.test_callback5()
32
+ assert f(number=43) == 44
33
+
34
+
35
+ def test_bound_method_callback():
36
+ # Bound Python method:
37
+ class MyClass:
38
+ def double(self, val):
39
+ return 2 * val
40
+
41
+ z = MyClass()
42
+ assert m.test_callback3(z.double) == "func(43) = 86"
43
+
44
+ z = m.CppBoundMethodTest()
45
+ assert m.test_callback3(z.triple) == "func(43) = 129"
46
+
47
+
48
+ def test_keyword_args_and_generalized_unpacking():
49
+ def f(*args, **kwargs):
50
+ return args, kwargs
51
+
52
+ assert m.test_tuple_unpacking(f) == (("positional", 1, 2, 3, 4, 5, 6), {})
53
+ assert m.test_dict_unpacking(f) == (
54
+ ("positional", 1),
55
+ {"key": "value", "a": 1, "b": 2},
56
+ )
57
+ assert m.test_keyword_args(f) == ((), {"x": 10, "y": 20})
58
+ assert m.test_unpacking_and_keywords1(f) == ((1, 2), {"c": 3, "d": 4})
59
+ assert m.test_unpacking_and_keywords2(f) == (
60
+ ("positional", 1, 2, 3, 4, 5),
61
+ {"key": "value", "a": 1, "b": 2, "c": 3, "d": 4, "e": 5},
62
+ )
63
+
64
+ with pytest.raises(TypeError) as excinfo:
65
+ m.test_unpacking_error1(f)
66
+ assert "Got multiple values for keyword argument" in str(excinfo.value)
67
+
68
+ with pytest.raises(TypeError) as excinfo:
69
+ m.test_unpacking_error2(f)
70
+ assert "Got multiple values for keyword argument" in str(excinfo.value)
71
+
72
+ with pytest.raises(RuntimeError) as excinfo:
73
+ m.test_arg_conversion_error1(f)
74
+ assert str(excinfo.value) == "Unable to convert call argument " + (
75
+ "'1' of type 'UnregisteredType' to Python object"
76
+ if detailed_error_messages_enabled
77
+ else "'1' to Python object (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"
78
+ )
79
+
80
+ with pytest.raises(RuntimeError) as excinfo:
81
+ m.test_arg_conversion_error2(f)
82
+ assert str(excinfo.value) == "Unable to convert call argument " + (
83
+ "'expected_name' of type 'UnregisteredType' to Python object"
84
+ if detailed_error_messages_enabled
85
+ else "'expected_name' to Python object "
86
+ "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"
87
+ )
88
+
89
+
90
+ def test_lambda_closure_cleanup():
91
+ m.test_lambda_closure_cleanup()
92
+ cstats = m.payload_cstats()
93
+ assert cstats.alive() == 0
94
+ assert cstats.copy_constructions == 1
95
+ assert cstats.move_constructions >= 1
96
+
97
+
98
+ def test_cpp_callable_cleanup():
99
+ alive_counts = m.test_cpp_callable_cleanup()
100
+ assert alive_counts == [0, 1, 2, 1, 2, 1, 0]
101
+
102
+
103
+ def test_cpp_function_roundtrip():
104
+ """Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer"""
105
+
106
+ assert (
107
+ m.test_dummy_function(m.dummy_function) == "matches dummy_function: eval(1) = 2"
108
+ )
109
+ assert (
110
+ m.test_dummy_function(m.roundtrip(m.dummy_function))
111
+ == "matches dummy_function: eval(1) = 2"
112
+ )
113
+ assert (
114
+ m.test_dummy_function(m.dummy_function_overloaded)
115
+ == "matches dummy_function: eval(1) = 2"
116
+ )
117
+ assert m.roundtrip(None, expect_none=True) is None
118
+ assert (
119
+ m.test_dummy_function(lambda x: x + 2)
120
+ == "can't convert to function pointer: eval(1) = 3"
121
+ )
122
+
123
+ with pytest.raises(TypeError) as excinfo:
124
+ m.test_dummy_function(m.dummy_function2)
125
+ assert "incompatible function arguments" in str(excinfo.value)
126
+
127
+ with pytest.raises(TypeError) as excinfo:
128
+ m.test_dummy_function(lambda x, y: x + y)
129
+ assert any(
130
+ s in str(excinfo.value)
131
+ for s in ("missing 1 required positional argument", "takes exactly 2 arguments")
132
+ )
133
+
134
+
135
+ def test_function_signatures(doc):
136
+ assert doc(m.test_callback3) == "test_callback3(arg0: Callable[[int], int]) -> str"
137
+ assert doc(m.test_callback4) == "test_callback4() -> Callable[[int], int]"
138
+
139
+
140
+ def test_movable_object():
141
+ assert m.callback_with_movable(lambda _: None) is True
142
+
143
+
144
+ @pytest.mark.skipif(
145
+ "env.PYPY",
146
+ reason="PyPy segfaults on here. See discussion on #1413.",
147
+ )
148
+ def test_python_builtins():
149
+ """Test if python builtins like sum() can be used as callbacks"""
150
+ assert m.test_sum_builtin(sum, [1, 2, 3]) == 6
151
+ assert m.test_sum_builtin(sum, []) == 0
152
+
153
+
154
+ def test_async_callbacks():
155
+ # serves as state for async callback
156
+ class Item:
157
+ def __init__(self, value):
158
+ self.value = value
159
+
160
+ res = []
161
+
162
+ # generate stateful lambda that will store result in `res`
163
+ def gen_f():
164
+ s = Item(3)
165
+ return lambda j: res.append(s.value + j)
166
+
167
+ # do some work async
168
+ work = [1, 2, 3, 4]
169
+ m.test_async_callback(gen_f(), work)
170
+ # wait until work is done
171
+ from time import sleep
172
+
173
+ sleep(0.5)
174
+ assert sum(res) == sum(x + 3 for x in work)
175
+
176
+
177
+ def test_async_async_callbacks():
178
+ t = Thread(target=test_async_callbacks)
179
+ t.start()
180
+ t.join()
181
+
182
+
183
+ def test_callback_num_times():
184
+ # Super-simple micro-benchmarking related to PR #2919.
185
+ # Example runtimes (Intel Xeon 2.2GHz, fully optimized):
186
+ # num_millions 1, repeats 2: 0.1 secs
187
+ # num_millions 20, repeats 10: 11.5 secs
188
+ one_million = 1000000
189
+ num_millions = 1 # Try 20 for actual micro-benchmarking.
190
+ repeats = 2 # Try 10.
191
+ rates = []
192
+ for rep in range(repeats):
193
+ t0 = time.time()
194
+ m.callback_num_times(lambda: None, num_millions * one_million)
195
+ td = time.time() - t0
196
+ rate = num_millions / td if td else 0
197
+ rates.append(rate)
198
+ if not rep:
199
+ print()
200
+ print(
201
+ f"callback_num_times: {num_millions:d} million / {td:.3f} seconds = {rate:.3f} million / second"
202
+ )
203
+ if len(rates) > 1:
204
+ print("Min Mean Max")
205
+ print(f"{min(rates):6.3f} {sum(rates) / len(rates):6.3f} {max(rates):6.3f}")
206
+
207
+
208
+ def test_custom_func():
209
+ assert m.custom_function(4) == 36
210
+ assert m.roundtrip(m.custom_function)(4) == 36
211
+
212
+
213
+ @pytest.mark.skipif(
214
+ m.custom_function2 is None, reason="Current PYBIND11_INTERNALS_VERSION too low"
215
+ )
216
+ def test_custom_func2():
217
+ assert m.custom_function2(3) == 27
218
+ assert m.roundtrip(m.custom_function2)(3) == 27
219
+
220
+
221
+ def test_callback_docstring():
222
+ assert (
223
+ m.test_tuple_unpacking.__doc__.strip()
224
+ == "test_tuple_unpacking(arg0: Callable) -> object"
225
+ )
third_party/CityFlow/extern/pybind11/tests/test_chrono.cpp CHANGED
@@ -1,81 +1,81 @@
1
- /*
2
- tests/test_chrono.cpp -- test conversions to/from std::chrono types
3
-
4
- Copyright (c) 2016 Trent Houliston <trent@houliston.me> and
5
- Wenzel Jakob <wenzel.jakob@epfl.ch>
6
-
7
- All rights reserved. Use of this source code is governed by a
8
- BSD-style license that can be found in the LICENSE file.
9
- */
10
-
11
- #include <pybind11/chrono.h>
12
-
13
- #include "pybind11_tests.h"
14
-
15
- #include <chrono>
16
-
17
- struct different_resolutions {
18
- using time_point_h = std::chrono::time_point<std::chrono::system_clock, std::chrono::hours>;
19
- using time_point_m = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
20
- using time_point_s = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
21
- using time_point_ms
22
- = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;
23
- using time_point_us
24
- = std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds>;
25
- time_point_h timestamp_h;
26
- time_point_m timestamp_m;
27
- time_point_s timestamp_s;
28
- time_point_ms timestamp_ms;
29
- time_point_us timestamp_us;
30
- };
31
-
32
- TEST_SUBMODULE(chrono, m) {
33
- using system_time = std::chrono::system_clock::time_point;
34
- using steady_time = std::chrono::steady_clock::time_point;
35
-
36
- using timespan = std::chrono::duration<int64_t, std::nano>;
37
- using timestamp = std::chrono::time_point<std::chrono::system_clock, timespan>;
38
-
39
- // test_chrono_system_clock
40
- // Return the current time off the wall clock
41
- m.def("test_chrono1", []() { return std::chrono::system_clock::now(); });
42
-
43
- // test_chrono_system_clock_roundtrip
44
- // Round trip the passed in system clock time
45
- m.def("test_chrono2", [](system_time t) { return t; });
46
-
47
- // test_chrono_duration_roundtrip
48
- // Round trip the passed in duration
49
- m.def("test_chrono3", [](std::chrono::system_clock::duration d) { return d; });
50
-
51
- // test_chrono_duration_subtraction_equivalence
52
- // Difference between two passed in time_points
53
- m.def("test_chrono4", [](system_time a, system_time b) { return a - b; });
54
-
55
- // test_chrono_steady_clock
56
- // Return the current time off the steady_clock
57
- m.def("test_chrono5", []() { return std::chrono::steady_clock::now(); });
58
-
59
- // test_chrono_steady_clock_roundtrip
60
- // Round trip a steady clock timepoint
61
- m.def("test_chrono6", [](steady_time t) { return t; });
62
-
63
- // test_floating_point_duration
64
- // Roundtrip a duration in microseconds from a float argument
65
- m.def("test_chrono7", [](std::chrono::microseconds t) { return t; });
66
- // Float durations (issue #719)
67
- m.def("test_chrono_float_diff",
68
- [](std::chrono::duration<float> a, std::chrono::duration<float> b) { return a - b; });
69
-
70
- m.def("test_nano_timepoint",
71
- [](timestamp start, timespan delta) -> timestamp { return start + delta; });
72
-
73
- // Test different resolutions
74
- py::class_<different_resolutions>(m, "different_resolutions")
75
- .def(py::init<>())
76
- .def_readwrite("timestamp_h", &different_resolutions::timestamp_h)
77
- .def_readwrite("timestamp_m", &different_resolutions::timestamp_m)
78
- .def_readwrite("timestamp_s", &different_resolutions::timestamp_s)
79
- .def_readwrite("timestamp_ms", &different_resolutions::timestamp_ms)
80
- .def_readwrite("timestamp_us", &different_resolutions::timestamp_us);
81
- }
 
1
+ /*
2
+ tests/test_chrono.cpp -- test conversions to/from std::chrono types
3
+
4
+ Copyright (c) 2016 Trent Houliston <trent@houliston.me> and
5
+ Wenzel Jakob <wenzel.jakob@epfl.ch>
6
+
7
+ All rights reserved. Use of this source code is governed by a
8
+ BSD-style license that can be found in the LICENSE file.
9
+ */
10
+
11
+ #include <pybind11/chrono.h>
12
+
13
+ #include "pybind11_tests.h"
14
+
15
+ #include <chrono>
16
+
17
+ struct different_resolutions {
18
+ using time_point_h = std::chrono::time_point<std::chrono::system_clock, std::chrono::hours>;
19
+ using time_point_m = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
20
+ using time_point_s = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
21
+ using time_point_ms
22
+ = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;
23
+ using time_point_us
24
+ = std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds>;
25
+ time_point_h timestamp_h;
26
+ time_point_m timestamp_m;
27
+ time_point_s timestamp_s;
28
+ time_point_ms timestamp_ms;
29
+ time_point_us timestamp_us;
30
+ };
31
+
32
+ TEST_SUBMODULE(chrono, m) {
33
+ using system_time = std::chrono::system_clock::time_point;
34
+ using steady_time = std::chrono::steady_clock::time_point;
35
+
36
+ using timespan = std::chrono::duration<int64_t, std::nano>;
37
+ using timestamp = std::chrono::time_point<std::chrono::system_clock, timespan>;
38
+
39
+ // test_chrono_system_clock
40
+ // Return the current time off the wall clock
41
+ m.def("test_chrono1", []() { return std::chrono::system_clock::now(); });
42
+
43
+ // test_chrono_system_clock_roundtrip
44
+ // Round trip the passed in system clock time
45
+ m.def("test_chrono2", [](system_time t) { return t; });
46
+
47
+ // test_chrono_duration_roundtrip
48
+ // Round trip the passed in duration
49
+ m.def("test_chrono3", [](std::chrono::system_clock::duration d) { return d; });
50
+
51
+ // test_chrono_duration_subtraction_equivalence
52
+ // Difference between two passed in time_points
53
+ m.def("test_chrono4", [](system_time a, system_time b) { return a - b; });
54
+
55
+ // test_chrono_steady_clock
56
+ // Return the current time off the steady_clock
57
+ m.def("test_chrono5", []() { return std::chrono::steady_clock::now(); });
58
+
59
+ // test_chrono_steady_clock_roundtrip
60
+ // Round trip a steady clock timepoint
61
+ m.def("test_chrono6", [](steady_time t) { return t; });
62
+
63
+ // test_floating_point_duration
64
+ // Roundtrip a duration in microseconds from a float argument
65
+ m.def("test_chrono7", [](std::chrono::microseconds t) { return t; });
66
+ // Float durations (issue #719)
67
+ m.def("test_chrono_float_diff",
68
+ [](std::chrono::duration<float> a, std::chrono::duration<float> b) { return a - b; });
69
+
70
+ m.def("test_nano_timepoint",
71
+ [](timestamp start, timespan delta) -> timestamp { return start + delta; });
72
+
73
+ // Test different resolutions
74
+ py::class_<different_resolutions>(m, "different_resolutions")
75
+ .def(py::init<>())
76
+ .def_readwrite("timestamp_h", &different_resolutions::timestamp_h)
77
+ .def_readwrite("timestamp_m", &different_resolutions::timestamp_m)
78
+ .def_readwrite("timestamp_s", &different_resolutions::timestamp_s)
79
+ .def_readwrite("timestamp_ms", &different_resolutions::timestamp_ms)
80
+ .def_readwrite("timestamp_us", &different_resolutions::timestamp_us);
81
+ }
third_party/CityFlow/extern/pybind11/tests/test_chrono.py CHANGED
@@ -1,205 +1,205 @@
1
- import datetime
2
-
3
- import pytest
4
-
5
- import env # noqa: F401
6
- from pybind11_tests import chrono as m
7
-
8
-
9
- def test_chrono_system_clock():
10
- # Get the time from both c++ and datetime
11
- date0 = datetime.datetime.today()
12
- date1 = m.test_chrono1()
13
- date2 = datetime.datetime.today()
14
-
15
- # The returned value should be a datetime
16
- assert isinstance(date1, datetime.datetime)
17
-
18
- # The numbers should vary by a very small amount (time it took to execute)
19
- diff_python = abs(date2 - date0)
20
- diff = abs(date1 - date2)
21
-
22
- # There should never be a days difference
23
- assert diff.days == 0
24
-
25
- # Since datetime.datetime.today() calls time.time(), and on some platforms
26
- # that has 1 second accuracy, we compare this way
27
- assert diff.seconds <= diff_python.seconds
28
-
29
-
30
- def test_chrono_system_clock_roundtrip():
31
- date1 = datetime.datetime.today()
32
-
33
- # Roundtrip the time
34
- date2 = m.test_chrono2(date1)
35
-
36
- # The returned value should be a datetime
37
- assert isinstance(date2, datetime.datetime)
38
-
39
- # They should be identical (no information lost on roundtrip)
40
- diff = abs(date1 - date2)
41
- assert diff == datetime.timedelta(0)
42
-
43
-
44
- def test_chrono_system_clock_roundtrip_date():
45
- date1 = datetime.date.today()
46
-
47
- # Roundtrip the time
48
- datetime2 = m.test_chrono2(date1)
49
- date2 = datetime2.date()
50
- time2 = datetime2.time()
51
-
52
- # The returned value should be a datetime
53
- assert isinstance(datetime2, datetime.datetime)
54
- assert isinstance(date2, datetime.date)
55
- assert isinstance(time2, datetime.time)
56
-
57
- # They should be identical (no information lost on roundtrip)
58
- diff = abs(date1 - date2)
59
- assert diff.days == 0
60
- assert diff.seconds == 0
61
- assert diff.microseconds == 0
62
-
63
- # Year, Month & Day should be the same after the round trip
64
- assert date1 == date2
65
-
66
- # There should be no time information
67
- assert time2.hour == 0
68
- assert time2.minute == 0
69
- assert time2.second == 0
70
- assert time2.microsecond == 0
71
-
72
-
73
- SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif(
74
- "env.WIN", reason="TZ environment variable only supported on POSIX"
75
- )
76
-
77
-
78
- @pytest.mark.parametrize(
79
- "time1",
80
- [
81
- datetime.datetime.today().time(),
82
- datetime.time(0, 0, 0),
83
- datetime.time(0, 0, 0, 1),
84
- datetime.time(0, 28, 45, 109827),
85
- datetime.time(0, 59, 59, 999999),
86
- datetime.time(1, 0, 0),
87
- datetime.time(5, 59, 59, 0),
88
- datetime.time(5, 59, 59, 1),
89
- ],
90
- )
91
- @pytest.mark.parametrize(
92
- "tz",
93
- [
94
- None,
95
- pytest.param("Europe/Brussels", marks=SKIP_TZ_ENV_ON_WIN),
96
- pytest.param("Asia/Pyongyang", marks=SKIP_TZ_ENV_ON_WIN),
97
- pytest.param("America/New_York", marks=SKIP_TZ_ENV_ON_WIN),
98
- ],
99
- )
100
- def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch):
101
- if tz is not None:
102
- monkeypatch.setenv("TZ", f"/usr/share/zoneinfo/{tz}")
103
-
104
- # Roundtrip the time
105
- datetime2 = m.test_chrono2(time1)
106
- date2 = datetime2.date()
107
- time2 = datetime2.time()
108
-
109
- # The returned value should be a datetime
110
- assert isinstance(datetime2, datetime.datetime)
111
- assert isinstance(date2, datetime.date)
112
- assert isinstance(time2, datetime.time)
113
-
114
- # Hour, Minute, Second & Microsecond should be the same after the round trip
115
- assert time1 == time2
116
-
117
- # There should be no date information (i.e. date = python base date)
118
- assert date2.year == 1970
119
- assert date2.month == 1
120
- assert date2.day == 1
121
-
122
-
123
- def test_chrono_duration_roundtrip():
124
- # Get the difference between two times (a timedelta)
125
- date1 = datetime.datetime.today()
126
- date2 = datetime.datetime.today()
127
- diff = date2 - date1
128
-
129
- # Make sure this is a timedelta
130
- assert isinstance(diff, datetime.timedelta)
131
-
132
- cpp_diff = m.test_chrono3(diff)
133
-
134
- assert cpp_diff == diff
135
-
136
- # Negative timedelta roundtrip
137
- diff = datetime.timedelta(microseconds=-1)
138
- cpp_diff = m.test_chrono3(diff)
139
-
140
- assert cpp_diff == diff
141
-
142
-
143
- def test_chrono_duration_subtraction_equivalence():
144
- date1 = datetime.datetime.today()
145
- date2 = datetime.datetime.today()
146
-
147
- diff = date2 - date1
148
- cpp_diff = m.test_chrono4(date2, date1)
149
-
150
- assert cpp_diff == diff
151
-
152
-
153
- def test_chrono_duration_subtraction_equivalence_date():
154
- date1 = datetime.date.today()
155
- date2 = datetime.date.today()
156
-
157
- diff = date2 - date1
158
- cpp_diff = m.test_chrono4(date2, date1)
159
-
160
- assert cpp_diff == diff
161
-
162
-
163
- def test_chrono_steady_clock():
164
- time1 = m.test_chrono5()
165
- assert isinstance(time1, datetime.timedelta)
166
-
167
-
168
- def test_chrono_steady_clock_roundtrip():
169
- time1 = datetime.timedelta(days=10, seconds=10, microseconds=100)
170
- time2 = m.test_chrono6(time1)
171
-
172
- assert isinstance(time2, datetime.timedelta)
173
-
174
- # They should be identical (no information lost on roundtrip)
175
- assert time1 == time2
176
-
177
-
178
- def test_floating_point_duration():
179
- # Test using a floating point number in seconds
180
- time = m.test_chrono7(35.525123)
181
-
182
- assert isinstance(time, datetime.timedelta)
183
-
184
- assert time.seconds == 35
185
- assert 525122 <= time.microseconds <= 525123
186
-
187
- diff = m.test_chrono_float_diff(43.789012, 1.123456)
188
- assert diff.seconds == 42
189
- assert 665556 <= diff.microseconds <= 665557
190
-
191
-
192
- def test_nano_timepoint():
193
- time = datetime.datetime.now()
194
- time1 = m.test_nano_timepoint(time, datetime.timedelta(seconds=60))
195
- assert time1 == time + datetime.timedelta(seconds=60)
196
-
197
-
198
- def test_chrono_different_resolutions():
199
- resolutions = m.different_resolutions()
200
- time = datetime.datetime.now()
201
- resolutions.timestamp_h = time
202
- resolutions.timestamp_m = time
203
- resolutions.timestamp_s = time
204
- resolutions.timestamp_ms = time
205
- resolutions.timestamp_us = time
 
1
+ import datetime
2
+
3
+ import pytest
4
+
5
+ import env # noqa: F401
6
+ from pybind11_tests import chrono as m
7
+
8
+
9
+ def test_chrono_system_clock():
10
+ # Get the time from both c++ and datetime
11
+ date0 = datetime.datetime.today()
12
+ date1 = m.test_chrono1()
13
+ date2 = datetime.datetime.today()
14
+
15
+ # The returned value should be a datetime
16
+ assert isinstance(date1, datetime.datetime)
17
+
18
+ # The numbers should vary by a very small amount (time it took to execute)
19
+ diff_python = abs(date2 - date0)
20
+ diff = abs(date1 - date2)
21
+
22
+ # There should never be a days difference
23
+ assert diff.days == 0
24
+
25
+ # Since datetime.datetime.today() calls time.time(), and on some platforms
26
+ # that has 1 second accuracy, we compare this way
27
+ assert diff.seconds <= diff_python.seconds
28
+
29
+
30
+ def test_chrono_system_clock_roundtrip():
31
+ date1 = datetime.datetime.today()
32
+
33
+ # Roundtrip the time
34
+ date2 = m.test_chrono2(date1)
35
+
36
+ # The returned value should be a datetime
37
+ assert isinstance(date2, datetime.datetime)
38
+
39
+ # They should be identical (no information lost on roundtrip)
40
+ diff = abs(date1 - date2)
41
+ assert diff == datetime.timedelta(0)
42
+
43
+
44
+ def test_chrono_system_clock_roundtrip_date():
45
+ date1 = datetime.date.today()
46
+
47
+ # Roundtrip the time
48
+ datetime2 = m.test_chrono2(date1)
49
+ date2 = datetime2.date()
50
+ time2 = datetime2.time()
51
+
52
+ # The returned value should be a datetime
53
+ assert isinstance(datetime2, datetime.datetime)
54
+ assert isinstance(date2, datetime.date)
55
+ assert isinstance(time2, datetime.time)
56
+
57
+ # They should be identical (no information lost on roundtrip)
58
+ diff = abs(date1 - date2)
59
+ assert diff.days == 0
60
+ assert diff.seconds == 0
61
+ assert diff.microseconds == 0
62
+
63
+ # Year, Month & Day should be the same after the round trip
64
+ assert date1 == date2
65
+
66
+ # There should be no time information
67
+ assert time2.hour == 0
68
+ assert time2.minute == 0
69
+ assert time2.second == 0
70
+ assert time2.microsecond == 0
71
+
72
+
73
+ SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif(
74
+ "env.WIN", reason="TZ environment variable only supported on POSIX"
75
+ )
76
+
77
+
78
+ @pytest.mark.parametrize(
79
+ "time1",
80
+ [
81
+ datetime.datetime.today().time(),
82
+ datetime.time(0, 0, 0),
83
+ datetime.time(0, 0, 0, 1),
84
+ datetime.time(0, 28, 45, 109827),
85
+ datetime.time(0, 59, 59, 999999),
86
+ datetime.time(1, 0, 0),
87
+ datetime.time(5, 59, 59, 0),
88
+ datetime.time(5, 59, 59, 1),
89
+ ],
90
+ )
91
+ @pytest.mark.parametrize(
92
+ "tz",
93
+ [
94
+ None,
95
+ pytest.param("Europe/Brussels", marks=SKIP_TZ_ENV_ON_WIN),
96
+ pytest.param("Asia/Pyongyang", marks=SKIP_TZ_ENV_ON_WIN),
97
+ pytest.param("America/New_York", marks=SKIP_TZ_ENV_ON_WIN),
98
+ ],
99
+ )
100
+ def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch):
101
+ if tz is not None:
102
+ monkeypatch.setenv("TZ", f"/usr/share/zoneinfo/{tz}")
103
+
104
+ # Roundtrip the time
105
+ datetime2 = m.test_chrono2(time1)
106
+ date2 = datetime2.date()
107
+ time2 = datetime2.time()
108
+
109
+ # The returned value should be a datetime
110
+ assert isinstance(datetime2, datetime.datetime)
111
+ assert isinstance(date2, datetime.date)
112
+ assert isinstance(time2, datetime.time)
113
+
114
+ # Hour, Minute, Second & Microsecond should be the same after the round trip
115
+ assert time1 == time2
116
+
117
+ # There should be no date information (i.e. date = python base date)
118
+ assert date2.year == 1970
119
+ assert date2.month == 1
120
+ assert date2.day == 1
121
+
122
+
123
+ def test_chrono_duration_roundtrip():
124
+ # Get the difference between two times (a timedelta)
125
+ date1 = datetime.datetime.today()
126
+ date2 = datetime.datetime.today()
127
+ diff = date2 - date1
128
+
129
+ # Make sure this is a timedelta
130
+ assert isinstance(diff, datetime.timedelta)
131
+
132
+ cpp_diff = m.test_chrono3(diff)
133
+
134
+ assert cpp_diff == diff
135
+
136
+ # Negative timedelta roundtrip
137
+ diff = datetime.timedelta(microseconds=-1)
138
+ cpp_diff = m.test_chrono3(diff)
139
+
140
+ assert cpp_diff == diff
141
+
142
+
143
+ def test_chrono_duration_subtraction_equivalence():
144
+ date1 = datetime.datetime.today()
145
+ date2 = datetime.datetime.today()
146
+
147
+ diff = date2 - date1
148
+ cpp_diff = m.test_chrono4(date2, date1)
149
+
150
+ assert cpp_diff == diff
151
+
152
+
153
+ def test_chrono_duration_subtraction_equivalence_date():
154
+ date1 = datetime.date.today()
155
+ date2 = datetime.date.today()
156
+
157
+ diff = date2 - date1
158
+ cpp_diff = m.test_chrono4(date2, date1)
159
+
160
+ assert cpp_diff == diff
161
+
162
+
163
+ def test_chrono_steady_clock():
164
+ time1 = m.test_chrono5()
165
+ assert isinstance(time1, datetime.timedelta)
166
+
167
+
168
+ def test_chrono_steady_clock_roundtrip():
169
+ time1 = datetime.timedelta(days=10, seconds=10, microseconds=100)
170
+ time2 = m.test_chrono6(time1)
171
+
172
+ assert isinstance(time2, datetime.timedelta)
173
+
174
+ # They should be identical (no information lost on roundtrip)
175
+ assert time1 == time2
176
+
177
+
178
+ def test_floating_point_duration():
179
+ # Test using a floating point number in seconds
180
+ time = m.test_chrono7(35.525123)
181
+
182
+ assert isinstance(time, datetime.timedelta)
183
+
184
+ assert time.seconds == 35
185
+ assert 525122 <= time.microseconds <= 525123
186
+
187
+ diff = m.test_chrono_float_diff(43.789012, 1.123456)
188
+ assert diff.seconds == 42
189
+ assert 665556 <= diff.microseconds <= 665557
190
+
191
+
192
+ def test_nano_timepoint():
193
+ time = datetime.datetime.now()
194
+ time1 = m.test_nano_timepoint(time, datetime.timedelta(seconds=60))
195
+ assert time1 == time + datetime.timedelta(seconds=60)
196
+
197
+
198
+ def test_chrono_different_resolutions():
199
+ resolutions = m.different_resolutions()
200
+ time = datetime.datetime.now()
201
+ resolutions.timestamp_h = time
202
+ resolutions.timestamp_m = time
203
+ resolutions.timestamp_s = time
204
+ resolutions.timestamp_ms = time
205
+ resolutions.timestamp_us = time
third_party/CityFlow/extern/pybind11/tests/test_class.cpp CHANGED
@@ -1,657 +1,657 @@
1
- /*
2
- tests/test_class.cpp -- test py::class_ definitions and basic functionality
3
-
4
- Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #if defined(__INTEL_COMPILER) && __cplusplus >= 201703L
11
- // Intel compiler requires a separate header file to support aligned new operators
12
- // and does not set the __cpp_aligned_new feature macro.
13
- // This header needs to be included before pybind11.
14
- # include <aligned_new>
15
- #endif
16
-
17
- #include <pybind11/stl.h>
18
-
19
- #include "constructor_stats.h"
20
- #include "local_bindings.h"
21
- #include "pybind11_tests.h"
22
-
23
- #include <utility>
24
-
25
- PYBIND11_WARNING_DISABLE_MSVC(4324)
26
- // warning C4324: structure was padded due to alignment specifier
27
-
28
- // test_brace_initialization
29
- struct NoBraceInitialization {
30
- explicit NoBraceInitialization(std::vector<int> v) : vec{std::move(v)} {}
31
- template <typename T>
32
- NoBraceInitialization(std::initializer_list<T> l) : vec(l) {}
33
-
34
- std::vector<int> vec;
35
- };
36
-
37
- namespace test_class {
38
- namespace pr4220_tripped_over_this { // PR #4227
39
-
40
- template <int>
41
- struct SoEmpty {};
42
-
43
- template <typename T>
44
- std::string get_msg(const T &) {
45
- return "This is really only meant to exercise successful compilation.";
46
- }
47
-
48
- using Empty0 = SoEmpty<0x0>;
49
-
50
- void bind_empty0(py::module_ &m) {
51
- py::class_<Empty0>(m, "Empty0").def(py::init<>()).def("get_msg", get_msg<Empty0>);
52
- }
53
-
54
- } // namespace pr4220_tripped_over_this
55
- } // namespace test_class
56
-
57
- TEST_SUBMODULE(class_, m) {
58
- m.def("obj_class_name", [](py::handle obj) { return py::detail::obj_class_name(obj.ptr()); });
59
-
60
- // test_instance
61
- struct NoConstructor {
62
- NoConstructor() = default;
63
- NoConstructor(const NoConstructor &) = default;
64
- NoConstructor(NoConstructor &&) = default;
65
- static NoConstructor *new_instance() {
66
- auto *ptr = new NoConstructor();
67
- print_created(ptr, "via new_instance");
68
- return ptr;
69
- }
70
- ~NoConstructor() { print_destroyed(this); }
71
- };
72
- struct NoConstructorNew {
73
- NoConstructorNew() = default;
74
- NoConstructorNew(const NoConstructorNew &) = default;
75
- NoConstructorNew(NoConstructorNew &&) = default;
76
- static NoConstructorNew *new_instance() {
77
- auto *ptr = new NoConstructorNew();
78
- print_created(ptr, "via new_instance");
79
- return ptr;
80
- }
81
- ~NoConstructorNew() { print_destroyed(this); }
82
- };
83
-
84
- py::class_<NoConstructor>(m, "NoConstructor")
85
- .def_static("new_instance", &NoConstructor::new_instance, "Return an instance");
86
-
87
- py::class_<NoConstructorNew>(m, "NoConstructorNew")
88
- .def(py::init([]() { return nullptr; })) // Need a NOOP __init__
89
- .def_static("__new__",
90
- [](const py::object &) { return NoConstructorNew::new_instance(); });
91
-
92
- // test_inheritance
93
- class Pet {
94
- public:
95
- Pet(const std::string &name, const std::string &species)
96
- : m_name(name), m_species(species) {}
97
- std::string name() const { return m_name; }
98
- std::string species() const { return m_species; }
99
-
100
- private:
101
- std::string m_name;
102
- std::string m_species;
103
- };
104
-
105
- class Dog : public Pet {
106
- public:
107
- explicit Dog(const std::string &name) : Pet(name, "dog") {}
108
- std::string bark() const { return "Woof!"; }
109
- };
110
-
111
- class Rabbit : public Pet {
112
- public:
113
- explicit Rabbit(const std::string &name) : Pet(name, "parrot") {}
114
- };
115
-
116
- class Hamster : public Pet {
117
- public:
118
- explicit Hamster(const std::string &name) : Pet(name, "rodent") {}
119
- };
120
-
121
- class Chimera : public Pet {
122
- Chimera() : Pet("Kimmy", "chimera") {}
123
- };
124
-
125
- py::class_<Pet> pet_class(m, "Pet");
126
- pet_class.def(py::init<std::string, std::string>())
127
- .def("name", &Pet::name)
128
- .def("species", &Pet::species);
129
-
130
- /* One way of declaring a subclass relationship: reference parent's class_ object */
131
- py::class_<Dog>(m, "Dog", pet_class).def(py::init<std::string>());
132
-
133
- /* Another way of declaring a subclass relationship: reference parent's C++ type */
134
- py::class_<Rabbit, Pet>(m, "Rabbit").def(py::init<std::string>());
135
-
136
- /* And another: list parent in class template arguments */
137
- py::class_<Hamster, Pet>(m, "Hamster").def(py::init<std::string>());
138
-
139
- /* Constructors are not inherited by default */
140
- py::class_<Chimera, Pet>(m, "Chimera");
141
-
142
- m.def("pet_name_species",
143
- [](const Pet &pet) { return pet.name() + " is a " + pet.species(); });
144
- m.def("dog_bark", [](const Dog &dog) { return dog.bark(); });
145
-
146
- // test_automatic_upcasting
147
- struct BaseClass {
148
- BaseClass() = default;
149
- BaseClass(const BaseClass &) = default;
150
- BaseClass(BaseClass &&) = default;
151
- virtual ~BaseClass() = default;
152
- };
153
- struct DerivedClass1 : BaseClass {};
154
- struct DerivedClass2 : BaseClass {};
155
-
156
- py::class_<BaseClass>(m, "BaseClass").def(py::init<>());
157
- py::class_<DerivedClass1>(m, "DerivedClass1").def(py::init<>());
158
- py::class_<DerivedClass2>(m, "DerivedClass2").def(py::init<>());
159
-
160
- m.def("return_class_1", []() -> BaseClass * { return new DerivedClass1(); });
161
- m.def("return_class_2", []() -> BaseClass * { return new DerivedClass2(); });
162
- m.def("return_class_n", [](int n) -> BaseClass * {
163
- if (n == 1) {
164
- return new DerivedClass1();
165
- }
166
- if (n == 2) {
167
- return new DerivedClass2();
168
- }
169
- return new BaseClass();
170
- });
171
- m.def("return_none", []() -> BaseClass * { return nullptr; });
172
-
173
- // test_isinstance
174
- m.def("check_instances", [](const py::list &l) {
175
- return py::make_tuple(py::isinstance<py::tuple>(l[0]),
176
- py::isinstance<py::dict>(l[1]),
177
- py::isinstance<Pet>(l[2]),
178
- py::isinstance<Pet>(l[3]),
179
- py::isinstance<Dog>(l[4]),
180
- py::isinstance<Rabbit>(l[5]),
181
- py::isinstance<UnregisteredType>(l[6]));
182
- });
183
-
184
- struct Invalid {};
185
-
186
- // test_type
187
- m.def("check_type", [](int category) {
188
- // Currently not supported (via a fail at compile time)
189
- // See https://github.com/pybind/pybind11/issues/2486
190
- // if (category == 2)
191
- // return py::type::of<int>();
192
- if (category == 1) {
193
- return py::type::of<DerivedClass1>();
194
- }
195
- return py::type::of<Invalid>();
196
- });
197
-
198
- m.def("get_type_of", [](py::object ob) { return py::type::of(std::move(ob)); });
199
-
200
- m.def("get_type_classic", [](py::handle h) { return h.get_type(); });
201
-
202
- m.def("as_type", [](const py::object &ob) { return py::type(ob); });
203
-
204
- // test_mismatched_holder
205
- struct MismatchBase1 {};
206
- struct MismatchDerived1 : MismatchBase1 {};
207
-
208
- struct MismatchBase2 {};
209
- struct MismatchDerived2 : MismatchBase2 {};
210
-
211
- m.def("mismatched_holder_1", []() {
212
- auto mod = py::module_::import("__main__");
213
- py::class_<MismatchBase1, std::shared_ptr<MismatchBase1>>(mod, "MismatchBase1");
214
- py::class_<MismatchDerived1, MismatchBase1>(mod, "MismatchDerived1");
215
- });
216
- m.def("mismatched_holder_2", []() {
217
- auto mod = py::module_::import("__main__");
218
- py::class_<MismatchBase2>(mod, "MismatchBase2");
219
- py::class_<MismatchDerived2, std::shared_ptr<MismatchDerived2>, MismatchBase2>(
220
- mod, "MismatchDerived2");
221
- });
222
-
223
- // test_override_static
224
- // #511: problem with inheritance + overwritten def_static
225
- struct MyBase {
226
- static std::unique_ptr<MyBase> make() { return std::unique_ptr<MyBase>(new MyBase()); }
227
- };
228
-
229
- struct MyDerived : MyBase {
230
- static std::unique_ptr<MyDerived> make() {
231
- return std::unique_ptr<MyDerived>(new MyDerived());
232
- }
233
- };
234
-
235
- py::class_<MyBase>(m, "MyBase").def_static("make", &MyBase::make);
236
-
237
- py::class_<MyDerived, MyBase>(m, "MyDerived")
238
- .def_static("make", &MyDerived::make)
239
- .def_static("make2", &MyDerived::make);
240
-
241
- // test_implicit_conversion_life_support
242
- struct ConvertibleFromUserType {
243
- int i;
244
-
245
- explicit ConvertibleFromUserType(UserType u) : i(u.value()) {}
246
- };
247
-
248
- py::class_<ConvertibleFromUserType>(m, "AcceptsUserType").def(py::init<UserType>());
249
- py::implicitly_convertible<UserType, ConvertibleFromUserType>();
250
-
251
- m.def("implicitly_convert_argument", [](const ConvertibleFromUserType &r) { return r.i; });
252
- m.def("implicitly_convert_variable", [](const py::object &o) {
253
- // `o` is `UserType` and `r` is a reference to a temporary created by implicit
254
- // conversion. This is valid when called inside a bound function because the temp
255
- // object is attached to the same life support system as the arguments.
256
- const auto &r = o.cast<const ConvertibleFromUserType &>();
257
- return r.i;
258
- });
259
- m.add_object("implicitly_convert_variable_fail", [&] {
260
- auto f = [](PyObject *, PyObject *args) -> PyObject * {
261
- auto o = py::reinterpret_borrow<py::tuple>(args)[0];
262
- try { // It should fail here because there is no life support.
263
- o.cast<const ConvertibleFromUserType &>();
264
- } catch (const py::cast_error &e) {
265
- return py::str(e.what()).release().ptr();
266
- }
267
- return py::str().release().ptr();
268
- };
269
-
270
- auto *def = new PyMethodDef{"f", f, METH_VARARGS, nullptr};
271
- py::capsule def_capsule(def,
272
- [](void *ptr) { delete reinterpret_cast<PyMethodDef *>(ptr); });
273
- return py::reinterpret_steal<py::object>(
274
- PyCFunction_NewEx(def, def_capsule.ptr(), m.ptr()));
275
- }());
276
-
277
- // test_operator_new_delete
278
- struct HasOpNewDel {
279
- std::uint64_t i;
280
- static void *operator new(size_t s) {
281
- py::print("A new", s);
282
- return ::operator new(s);
283
- }
284
- static void *operator new(size_t s, void *ptr) {
285
- py::print("A placement-new", s);
286
- return ptr;
287
- }
288
- static void operator delete(void *p) {
289
- py::print("A delete");
290
- return ::operator delete(p);
291
- }
292
- };
293
- struct HasOpNewDelSize {
294
- std::uint32_t i;
295
- static void *operator new(size_t s) {
296
- py::print("B new", s);
297
- return ::operator new(s);
298
- }
299
- static void *operator new(size_t s, void *ptr) {
300
- py::print("B placement-new", s);
301
- return ptr;
302
- }
303
- static void operator delete(void *p, size_t s) {
304
- py::print("B delete", s);
305
- return ::operator delete(p);
306
- }
307
- };
308
- struct AliasedHasOpNewDelSize {
309
- std::uint64_t i;
310
- static void *operator new(size_t s) {
311
- py::print("C new", s);
312
- return ::operator new(s);
313
- }
314
- static void *operator new(size_t s, void *ptr) {
315
- py::print("C placement-new", s);
316
- return ptr;
317
- }
318
- static void operator delete(void *p, size_t s) {
319
- py::print("C delete", s);
320
- return ::operator delete(p);
321
- }
322
- virtual ~AliasedHasOpNewDelSize() = default;
323
- AliasedHasOpNewDelSize() = default;
324
- AliasedHasOpNewDelSize(const AliasedHasOpNewDelSize &) = delete;
325
- };
326
- struct PyAliasedHasOpNewDelSize : AliasedHasOpNewDelSize {
327
- PyAliasedHasOpNewDelSize() = default;
328
- explicit PyAliasedHasOpNewDelSize(int) {}
329
- std::uint64_t j;
330
- };
331
- struct HasOpNewDelBoth {
332
- std::uint32_t i[8];
333
- static void *operator new(size_t s) {
334
- py::print("D new", s);
335
- return ::operator new(s);
336
- }
337
- static void *operator new(size_t s, void *ptr) {
338
- py::print("D placement-new", s);
339
- return ptr;
340
- }
341
- static void operator delete(void *p) {
342
- py::print("D delete");
343
- return ::operator delete(p);
344
- }
345
- static void operator delete(void *p, size_t s) {
346
- py::print("D wrong delete", s);
347
- return ::operator delete(p);
348
- }
349
- };
350
- py::class_<HasOpNewDel>(m, "HasOpNewDel").def(py::init<>());
351
- py::class_<HasOpNewDelSize>(m, "HasOpNewDelSize").def(py::init<>());
352
- py::class_<HasOpNewDelBoth>(m, "HasOpNewDelBoth").def(py::init<>());
353
- py::class_<AliasedHasOpNewDelSize, PyAliasedHasOpNewDelSize> aliased(m,
354
- "AliasedHasOpNewDelSize");
355
- aliased.def(py::init<>());
356
- aliased.attr("size_noalias") = py::int_(sizeof(AliasedHasOpNewDelSize));
357
- aliased.attr("size_alias") = py::int_(sizeof(PyAliasedHasOpNewDelSize));
358
-
359
- // This test is actually part of test_local_bindings (test_duplicate_local), but we need a
360
- // definition in a different compilation unit within the same module:
361
- bind_local<LocalExternal, 17>(m, "LocalExternal", py::module_local());
362
-
363
- // test_bind_protected_functions
364
- class ProtectedA {
365
- protected:
366
- int foo() const { return value; }
367
-
368
- private:
369
- int value = 42;
370
- };
371
-
372
- class PublicistA : public ProtectedA {
373
- public:
374
- using ProtectedA::foo;
375
- };
376
-
377
- py::class_<ProtectedA>(m, "ProtectedA").def(py::init<>()).def("foo", &PublicistA::foo);
378
-
379
- class ProtectedB {
380
- public:
381
- virtual ~ProtectedB() = default;
382
- ProtectedB() = default;
383
- ProtectedB(const ProtectedB &) = delete;
384
-
385
- protected:
386
- virtual int foo() const { return value; }
387
- virtual void *void_foo() { return static_cast<void *>(&value); }
388
- virtual void *get_self() { return static_cast<void *>(this); }
389
-
390
- private:
391
- int value = 42;
392
- };
393
-
394
- class TrampolineB : public ProtectedB {
395
- public:
396
- int foo() const override { PYBIND11_OVERRIDE(int, ProtectedB, foo, ); }
397
- void *void_foo() override { PYBIND11_OVERRIDE(void *, ProtectedB, void_foo, ); }
398
- void *get_self() override { PYBIND11_OVERRIDE(void *, ProtectedB, get_self, ); }
399
- };
400
-
401
- class PublicistB : public ProtectedB {
402
- public:
403
- // [workaround(intel)] = default does not work here
404
- // Removing or defaulting this destructor results in linking errors with the Intel compiler
405
- // (in Debug builds only, tested with icpc (ICC) 2021.1 Beta 20200827)
406
- ~PublicistB() override{}; // NOLINT(modernize-use-equals-default)
407
- using ProtectedB::foo;
408
- using ProtectedB::get_self;
409
- using ProtectedB::void_foo;
410
- };
411
-
412
- m.def("read_foo", [](const void *original) {
413
- const int *ptr = reinterpret_cast<const int *>(original);
414
- return *ptr;
415
- });
416
-
417
- m.def("pointers_equal",
418
- [](const void *original, const void *comparison) { return original == comparison; });
419
-
420
- py::class_<ProtectedB, TrampolineB>(m, "ProtectedB")
421
- .def(py::init<>())
422
- .def("foo", &PublicistB::foo)
423
- .def("void_foo", &PublicistB::void_foo)
424
- .def("get_self", &PublicistB::get_self);
425
-
426
- // test_brace_initialization
427
- struct BraceInitialization {
428
- int field1;
429
- std::string field2;
430
- };
431
-
432
- py::class_<BraceInitialization>(m, "BraceInitialization")
433
- .def(py::init<int, const std::string &>())
434
- .def_readwrite("field1", &BraceInitialization::field1)
435
- .def_readwrite("field2", &BraceInitialization::field2);
436
- // We *don't* want to construct using braces when the given constructor argument maps to a
437
- // constructor, because brace initialization could go to the wrong place (in particular when
438
- // there is also an `initializer_list<T>`-accept constructor):
439
- py::class_<NoBraceInitialization>(m, "NoBraceInitialization")
440
- .def(py::init<std::vector<int>>())
441
- .def_readonly("vec", &NoBraceInitialization::vec);
442
-
443
- // test_reentrant_implicit_conversion_failure
444
- // #1035: issue with runaway reentrant implicit conversion
445
- struct BogusImplicitConversion {
446
- BogusImplicitConversion(const BogusImplicitConversion &) = default;
447
- };
448
-
449
- py::class_<BogusImplicitConversion>(m, "BogusImplicitConversion")
450
- .def(py::init<const BogusImplicitConversion &>());
451
-
452
- py::implicitly_convertible<int, BogusImplicitConversion>();
453
-
454
- // test_qualname
455
- // #1166: nested class docstring doesn't show nested name
456
- // Also related: tests that __qualname__ is set properly
457
- struct NestBase {};
458
- struct Nested {};
459
- py::class_<NestBase> base(m, "NestBase");
460
- base.def(py::init<>());
461
- py::class_<Nested>(base, "Nested")
462
- .def(py::init<>())
463
- .def("fn", [](Nested &, int, NestBase &, Nested &) {})
464
- .def(
465
- "fa", [](Nested &, int, NestBase &, Nested &) {}, "a"_a, "b"_a, "c"_a);
466
- base.def("g", [](NestBase &, Nested &) {});
467
- base.def("h", []() { return NestBase(); });
468
-
469
- // test_error_after_conversion
470
- // The second-pass path through dispatcher() previously didn't
471
- // remember which overload was used, and would crash trying to
472
- // generate a useful error message
473
-
474
- struct NotRegistered {};
475
- struct StringWrapper {
476
- std::string str;
477
- };
478
- m.def("test_error_after_conversions", [](int) {});
479
- m.def("test_error_after_conversions",
480
- [](const StringWrapper &) -> NotRegistered { return {}; });
481
- py::class_<StringWrapper>(m, "StringWrapper").def(py::init<std::string>());
482
- py::implicitly_convertible<std::string, StringWrapper>();
483
-
484
- #if defined(PYBIND11_CPP17)
485
- struct alignas(1024) Aligned {
486
- std::uintptr_t ptr() const { return (uintptr_t) this; }
487
- };
488
- py::class_<Aligned>(m, "Aligned").def(py::init<>()).def("ptr", &Aligned::ptr);
489
- #endif
490
-
491
- // test_final
492
- struct IsFinal final {};
493
- py::class_<IsFinal>(m, "IsFinal", py::is_final());
494
-
495
- // test_non_final_final
496
- struct IsNonFinalFinal {};
497
- py::class_<IsNonFinalFinal>(m, "IsNonFinalFinal", py::is_final());
498
-
499
- // test_exception_rvalue_abort
500
- struct PyPrintDestructor {
501
- PyPrintDestructor() = default;
502
- ~PyPrintDestructor() { py::print("Print from destructor"); }
503
- void throw_something() { throw std::runtime_error("error"); }
504
- };
505
- py::class_<PyPrintDestructor>(m, "PyPrintDestructor")
506
- .def(py::init<>())
507
- .def("throw_something", &PyPrintDestructor::throw_something);
508
-
509
- // test_multiple_instances_with_same_pointer
510
- struct SamePointer {};
511
- static SamePointer samePointer;
512
- py::class_<SamePointer, std::unique_ptr<SamePointer, py::nodelete>>(m, "SamePointer")
513
- .def(py::init([]() { return &samePointer; }));
514
-
515
- struct Empty {};
516
- py::class_<Empty>(m, "Empty").def(py::init<>());
517
-
518
- // test_base_and_derived_nested_scope
519
- struct BaseWithNested {
520
- struct Nested {};
521
- };
522
-
523
- struct DerivedWithNested : BaseWithNested {
524
- struct Nested {};
525
- };
526
-
527
- py::class_<BaseWithNested> baseWithNested_class(m, "BaseWithNested");
528
- py::class_<DerivedWithNested, BaseWithNested> derivedWithNested_class(m, "DerivedWithNested");
529
- py::class_<BaseWithNested::Nested>(baseWithNested_class, "Nested")
530
- .def_static("get_name", []() { return "BaseWithNested::Nested"; });
531
- py::class_<DerivedWithNested::Nested>(derivedWithNested_class, "Nested")
532
- .def_static("get_name", []() { return "DerivedWithNested::Nested"; });
533
-
534
- // test_register_duplicate_class
535
- struct Duplicate {};
536
- struct OtherDuplicate {};
537
- struct DuplicateNested {};
538
- struct OtherDuplicateNested {};
539
-
540
- m.def("register_duplicate_class_name", [](const py::module_ &m) {
541
- py::class_<Duplicate>(m, "Duplicate");
542
- py::class_<OtherDuplicate>(m, "Duplicate");
543
- });
544
- m.def("register_duplicate_class_type", [](const py::module_ &m) {
545
- py::class_<OtherDuplicate>(m, "OtherDuplicate");
546
- py::class_<OtherDuplicate>(m, "YetAnotherDuplicate");
547
- });
548
- m.def("register_duplicate_nested_class_name", [](const py::object &gt) {
549
- py::class_<DuplicateNested>(gt, "DuplicateNested");
550
- py::class_<OtherDuplicateNested>(gt, "DuplicateNested");
551
- });
552
- m.def("register_duplicate_nested_class_type", [](const py::object &gt) {
553
- py::class_<OtherDuplicateNested>(gt, "OtherDuplicateNested");
554
- py::class_<OtherDuplicateNested>(gt, "YetAnotherDuplicateNested");
555
- });
556
-
557
- test_class::pr4220_tripped_over_this::bind_empty0(m);
558
- }
559
-
560
- template <int N>
561
- class BreaksBase {
562
- public:
563
- virtual ~BreaksBase() = default;
564
- BreaksBase() = default;
565
- BreaksBase(const BreaksBase &) = delete;
566
- };
567
- template <int N>
568
- class BreaksTramp : public BreaksBase<N> {};
569
- // These should all compile just fine:
570
- using DoesntBreak1 = py::class_<BreaksBase<1>, std::unique_ptr<BreaksBase<1>>, BreaksTramp<1>>;
571
- using DoesntBreak2 = py::class_<BreaksBase<2>, BreaksTramp<2>, std::unique_ptr<BreaksBase<2>>>;
572
- using DoesntBreak3 = py::class_<BreaksBase<3>, std::unique_ptr<BreaksBase<3>>>;
573
- using DoesntBreak4 = py::class_<BreaksBase<4>, BreaksTramp<4>>;
574
- using DoesntBreak5 = py::class_<BreaksBase<5>>;
575
- using DoesntBreak6 = py::class_<BreaksBase<6>, std::shared_ptr<BreaksBase<6>>, BreaksTramp<6>>;
576
- using DoesntBreak7 = py::class_<BreaksBase<7>, BreaksTramp<7>, std::shared_ptr<BreaksBase<7>>>;
577
- using DoesntBreak8 = py::class_<BreaksBase<8>, std::shared_ptr<BreaksBase<8>>>;
578
- #define CHECK_BASE(N) \
579
- static_assert(std::is_same<typename DoesntBreak##N::type, BreaksBase<(N)>>::value, \
580
- "DoesntBreak" #N " has wrong type!")
581
- CHECK_BASE(1);
582
- CHECK_BASE(2);
583
- CHECK_BASE(3);
584
- CHECK_BASE(4);
585
- CHECK_BASE(5);
586
- CHECK_BASE(6);
587
- CHECK_BASE(7);
588
- CHECK_BASE(8);
589
- #define CHECK_ALIAS(N) \
590
- static_assert( \
591
- DoesntBreak##N::has_alias \
592
- && std::is_same<typename DoesntBreak##N::type_alias, BreaksTramp<(N)>>::value, \
593
- "DoesntBreak" #N " has wrong type_alias!")
594
- #define CHECK_NOALIAS(N) \
595
- static_assert(!DoesntBreak##N::has_alias \
596
- && std::is_void<typename DoesntBreak##N::type_alias>::value, \
597
- "DoesntBreak" #N " has type alias, but shouldn't!")
598
- CHECK_ALIAS(1);
599
- CHECK_ALIAS(2);
600
- CHECK_NOALIAS(3);
601
- CHECK_ALIAS(4);
602
- CHECK_NOALIAS(5);
603
- CHECK_ALIAS(6);
604
- CHECK_ALIAS(7);
605
- CHECK_NOALIAS(8);
606
- #define CHECK_HOLDER(N, TYPE) \
607
- static_assert(std::is_same<typename DoesntBreak##N::holder_type, \
608
- std::TYPE##_ptr<BreaksBase<(N)>>>::value, \
609
- "DoesntBreak" #N " has wrong holder_type!")
610
- CHECK_HOLDER(1, unique);
611
- CHECK_HOLDER(2, unique);
612
- CHECK_HOLDER(3, unique);
613
- CHECK_HOLDER(4, unique);
614
- CHECK_HOLDER(5, unique);
615
- CHECK_HOLDER(6, shared);
616
- CHECK_HOLDER(7, shared);
617
- CHECK_HOLDER(8, shared);
618
-
619
- // There's no nice way to test that these fail because they fail to compile; leave them here,
620
- // though, so that they can be manually tested by uncommenting them (and seeing that compilation
621
- // failures occurs).
622
-
623
- // We have to actually look into the type: the typedef alone isn't enough to instantiate the type:
624
- #define CHECK_BROKEN(N) \
625
- static_assert(std::is_same<typename Breaks##N::type, BreaksBase<-(N)>>::value, \
626
- "Breaks1 has wrong type!");
627
-
628
- #ifdef PYBIND11_NEVER_DEFINED_EVER
629
- // Two holder classes:
630
- typedef py::
631
- class_<BreaksBase<-1>, std::unique_ptr<BreaksBase<-1>>, std::unique_ptr<BreaksBase<-1>>>
632
- Breaks1;
633
- CHECK_BROKEN(1);
634
- // Two aliases:
635
- typedef py::class_<BreaksBase<-2>, BreaksTramp<-2>, BreaksTramp<-2>> Breaks2;
636
- CHECK_BROKEN(2);
637
- // Holder + 2 aliases
638
- typedef py::
639
- class_<BreaksBase<-3>, std::unique_ptr<BreaksBase<-3>>, BreaksTramp<-3>, BreaksTramp<-3>>
640
- Breaks3;
641
- CHECK_BROKEN(3);
642
- // Alias + 2 holders
643
- typedef py::class_<BreaksBase<-4>,
644
- std::unique_ptr<BreaksBase<-4>>,
645
- BreaksTramp<-4>,
646
- std::shared_ptr<BreaksBase<-4>>>
647
- Breaks4;
648
- CHECK_BROKEN(4);
649
- // Invalid option (not a subclass or holder)
650
- typedef py::class_<BreaksBase<-5>, BreaksTramp<-4>> Breaks5;
651
- CHECK_BROKEN(5);
652
- // Invalid option: multiple inheritance not supported:
653
- template <>
654
- struct BreaksBase<-8> : BreaksBase<-6>, BreaksBase<-7> {};
655
- typedef py::class_<BreaksBase<-8>, BreaksBase<-6>, BreaksBase<-7>> Breaks8;
656
- CHECK_BROKEN(8);
657
- #endif
 
1
+ /*
2
+ tests/test_class.cpp -- test py::class_ definitions and basic functionality
3
+
4
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #if defined(__INTEL_COMPILER) && __cplusplus >= 201703L
11
+ // Intel compiler requires a separate header file to support aligned new operators
12
+ // and does not set the __cpp_aligned_new feature macro.
13
+ // This header needs to be included before pybind11.
14
+ # include <aligned_new>
15
+ #endif
16
+
17
+ #include <pybind11/stl.h>
18
+
19
+ #include "constructor_stats.h"
20
+ #include "local_bindings.h"
21
+ #include "pybind11_tests.h"
22
+
23
+ #include <utility>
24
+
25
+ PYBIND11_WARNING_DISABLE_MSVC(4324)
26
+ // warning C4324: structure was padded due to alignment specifier
27
+
28
+ // test_brace_initialization
29
+ struct NoBraceInitialization {
30
+ explicit NoBraceInitialization(std::vector<int> v) : vec{std::move(v)} {}
31
+ template <typename T>
32
+ NoBraceInitialization(std::initializer_list<T> l) : vec(l) {}
33
+
34
+ std::vector<int> vec;
35
+ };
36
+
37
+ namespace test_class {
38
+ namespace pr4220_tripped_over_this { // PR #4227
39
+
40
+ template <int>
41
+ struct SoEmpty {};
42
+
43
+ template <typename T>
44
+ std::string get_msg(const T &) {
45
+ return "This is really only meant to exercise successful compilation.";
46
+ }
47
+
48
+ using Empty0 = SoEmpty<0x0>;
49
+
50
+ void bind_empty0(py::module_ &m) {
51
+ py::class_<Empty0>(m, "Empty0").def(py::init<>()).def("get_msg", get_msg<Empty0>);
52
+ }
53
+
54
+ } // namespace pr4220_tripped_over_this
55
+ } // namespace test_class
56
+
57
+ TEST_SUBMODULE(class_, m) {
58
+ m.def("obj_class_name", [](py::handle obj) { return py::detail::obj_class_name(obj.ptr()); });
59
+
60
+ // test_instance
61
+ struct NoConstructor {
62
+ NoConstructor() = default;
63
+ NoConstructor(const NoConstructor &) = default;
64
+ NoConstructor(NoConstructor &&) = default;
65
+ static NoConstructor *new_instance() {
66
+ auto *ptr = new NoConstructor();
67
+ print_created(ptr, "via new_instance");
68
+ return ptr;
69
+ }
70
+ ~NoConstructor() { print_destroyed(this); }
71
+ };
72
+ struct NoConstructorNew {
73
+ NoConstructorNew() = default;
74
+ NoConstructorNew(const NoConstructorNew &) = default;
75
+ NoConstructorNew(NoConstructorNew &&) = default;
76
+ static NoConstructorNew *new_instance() {
77
+ auto *ptr = new NoConstructorNew();
78
+ print_created(ptr, "via new_instance");
79
+ return ptr;
80
+ }
81
+ ~NoConstructorNew() { print_destroyed(this); }
82
+ };
83
+
84
+ py::class_<NoConstructor>(m, "NoConstructor")
85
+ .def_static("new_instance", &NoConstructor::new_instance, "Return an instance");
86
+
87
+ py::class_<NoConstructorNew>(m, "NoConstructorNew")
88
+ .def(py::init([]() { return nullptr; })) // Need a NOOP __init__
89
+ .def_static("__new__",
90
+ [](const py::object &) { return NoConstructorNew::new_instance(); });
91
+
92
+ // test_inheritance
93
+ class Pet {
94
+ public:
95
+ Pet(const std::string &name, const std::string &species)
96
+ : m_name(name), m_species(species) {}
97
+ std::string name() const { return m_name; }
98
+ std::string species() const { return m_species; }
99
+
100
+ private:
101
+ std::string m_name;
102
+ std::string m_species;
103
+ };
104
+
105
+ class Dog : public Pet {
106
+ public:
107
+ explicit Dog(const std::string &name) : Pet(name, "dog") {}
108
+ std::string bark() const { return "Woof!"; }
109
+ };
110
+
111
+ class Rabbit : public Pet {
112
+ public:
113
+ explicit Rabbit(const std::string &name) : Pet(name, "parrot") {}
114
+ };
115
+
116
+ class Hamster : public Pet {
117
+ public:
118
+ explicit Hamster(const std::string &name) : Pet(name, "rodent") {}
119
+ };
120
+
121
+ class Chimera : public Pet {
122
+ Chimera() : Pet("Kimmy", "chimera") {}
123
+ };
124
+
125
+ py::class_<Pet> pet_class(m, "Pet");
126
+ pet_class.def(py::init<std::string, std::string>())
127
+ .def("name", &Pet::name)
128
+ .def("species", &Pet::species);
129
+
130
+ /* One way of declaring a subclass relationship: reference parent's class_ object */
131
+ py::class_<Dog>(m, "Dog", pet_class).def(py::init<std::string>());
132
+
133
+ /* Another way of declaring a subclass relationship: reference parent's C++ type */
134
+ py::class_<Rabbit, Pet>(m, "Rabbit").def(py::init<std::string>());
135
+
136
+ /* And another: list parent in class template arguments */
137
+ py::class_<Hamster, Pet>(m, "Hamster").def(py::init<std::string>());
138
+
139
+ /* Constructors are not inherited by default */
140
+ py::class_<Chimera, Pet>(m, "Chimera");
141
+
142
+ m.def("pet_name_species",
143
+ [](const Pet &pet) { return pet.name() + " is a " + pet.species(); });
144
+ m.def("dog_bark", [](const Dog &dog) { return dog.bark(); });
145
+
146
+ // test_automatic_upcasting
147
+ struct BaseClass {
148
+ BaseClass() = default;
149
+ BaseClass(const BaseClass &) = default;
150
+ BaseClass(BaseClass &&) = default;
151
+ virtual ~BaseClass() = default;
152
+ };
153
+ struct DerivedClass1 : BaseClass {};
154
+ struct DerivedClass2 : BaseClass {};
155
+
156
+ py::class_<BaseClass>(m, "BaseClass").def(py::init<>());
157
+ py::class_<DerivedClass1>(m, "DerivedClass1").def(py::init<>());
158
+ py::class_<DerivedClass2>(m, "DerivedClass2").def(py::init<>());
159
+
160
+ m.def("return_class_1", []() -> BaseClass * { return new DerivedClass1(); });
161
+ m.def("return_class_2", []() -> BaseClass * { return new DerivedClass2(); });
162
+ m.def("return_class_n", [](int n) -> BaseClass * {
163
+ if (n == 1) {
164
+ return new DerivedClass1();
165
+ }
166
+ if (n == 2) {
167
+ return new DerivedClass2();
168
+ }
169
+ return new BaseClass();
170
+ });
171
+ m.def("return_none", []() -> BaseClass * { return nullptr; });
172
+
173
+ // test_isinstance
174
+ m.def("check_instances", [](const py::list &l) {
175
+ return py::make_tuple(py::isinstance<py::tuple>(l[0]),
176
+ py::isinstance<py::dict>(l[1]),
177
+ py::isinstance<Pet>(l[2]),
178
+ py::isinstance<Pet>(l[3]),
179
+ py::isinstance<Dog>(l[4]),
180
+ py::isinstance<Rabbit>(l[5]),
181
+ py::isinstance<UnregisteredType>(l[6]));
182
+ });
183
+
184
+ struct Invalid {};
185
+
186
+ // test_type
187
+ m.def("check_type", [](int category) {
188
+ // Currently not supported (via a fail at compile time)
189
+ // See https://github.com/pybind/pybind11/issues/2486
190
+ // if (category == 2)
191
+ // return py::type::of<int>();
192
+ if (category == 1) {
193
+ return py::type::of<DerivedClass1>();
194
+ }
195
+ return py::type::of<Invalid>();
196
+ });
197
+
198
+ m.def("get_type_of", [](py::object ob) { return py::type::of(std::move(ob)); });
199
+
200
+ m.def("get_type_classic", [](py::handle h) { return h.get_type(); });
201
+
202
+ m.def("as_type", [](const py::object &ob) { return py::type(ob); });
203
+
204
+ // test_mismatched_holder
205
+ struct MismatchBase1 {};
206
+ struct MismatchDerived1 : MismatchBase1 {};
207
+
208
+ struct MismatchBase2 {};
209
+ struct MismatchDerived2 : MismatchBase2 {};
210
+
211
+ m.def("mismatched_holder_1", []() {
212
+ auto mod = py::module_::import("__main__");
213
+ py::class_<MismatchBase1, std::shared_ptr<MismatchBase1>>(mod, "MismatchBase1");
214
+ py::class_<MismatchDerived1, MismatchBase1>(mod, "MismatchDerived1");
215
+ });
216
+ m.def("mismatched_holder_2", []() {
217
+ auto mod = py::module_::import("__main__");
218
+ py::class_<MismatchBase2>(mod, "MismatchBase2");
219
+ py::class_<MismatchDerived2, std::shared_ptr<MismatchDerived2>, MismatchBase2>(
220
+ mod, "MismatchDerived2");
221
+ });
222
+
223
+ // test_override_static
224
+ // #511: problem with inheritance + overwritten def_static
225
+ struct MyBase {
226
+ static std::unique_ptr<MyBase> make() { return std::unique_ptr<MyBase>(new MyBase()); }
227
+ };
228
+
229
+ struct MyDerived : MyBase {
230
+ static std::unique_ptr<MyDerived> make() {
231
+ return std::unique_ptr<MyDerived>(new MyDerived());
232
+ }
233
+ };
234
+
235
+ py::class_<MyBase>(m, "MyBase").def_static("make", &MyBase::make);
236
+
237
+ py::class_<MyDerived, MyBase>(m, "MyDerived")
238
+ .def_static("make", &MyDerived::make)
239
+ .def_static("make2", &MyDerived::make);
240
+
241
+ // test_implicit_conversion_life_support
242
+ struct ConvertibleFromUserType {
243
+ int i;
244
+
245
+ explicit ConvertibleFromUserType(UserType u) : i(u.value()) {}
246
+ };
247
+
248
+ py::class_<ConvertibleFromUserType>(m, "AcceptsUserType").def(py::init<UserType>());
249
+ py::implicitly_convertible<UserType, ConvertibleFromUserType>();
250
+
251
+ m.def("implicitly_convert_argument", [](const ConvertibleFromUserType &r) { return r.i; });
252
+ m.def("implicitly_convert_variable", [](const py::object &o) {
253
+ // `o` is `UserType` and `r` is a reference to a temporary created by implicit
254
+ // conversion. This is valid when called inside a bound function because the temp
255
+ // object is attached to the same life support system as the arguments.
256
+ const auto &r = o.cast<const ConvertibleFromUserType &>();
257
+ return r.i;
258
+ });
259
+ m.add_object("implicitly_convert_variable_fail", [&] {
260
+ auto f = [](PyObject *, PyObject *args) -> PyObject * {
261
+ auto o = py::reinterpret_borrow<py::tuple>(args)[0];
262
+ try { // It should fail here because there is no life support.
263
+ o.cast<const ConvertibleFromUserType &>();
264
+ } catch (const py::cast_error &e) {
265
+ return py::str(e.what()).release().ptr();
266
+ }
267
+ return py::str().release().ptr();
268
+ };
269
+
270
+ auto *def = new PyMethodDef{"f", f, METH_VARARGS, nullptr};
271
+ py::capsule def_capsule(def,
272
+ [](void *ptr) { delete reinterpret_cast<PyMethodDef *>(ptr); });
273
+ return py::reinterpret_steal<py::object>(
274
+ PyCFunction_NewEx(def, def_capsule.ptr(), m.ptr()));
275
+ }());
276
+
277
+ // test_operator_new_delete
278
+ struct HasOpNewDel {
279
+ std::uint64_t i;
280
+ static void *operator new(size_t s) {
281
+ py::print("A new", s);
282
+ return ::operator new(s);
283
+ }
284
+ static void *operator new(size_t s, void *ptr) {
285
+ py::print("A placement-new", s);
286
+ return ptr;
287
+ }
288
+ static void operator delete(void *p) {
289
+ py::print("A delete");
290
+ return ::operator delete(p);
291
+ }
292
+ };
293
+ struct HasOpNewDelSize {
294
+ std::uint32_t i;
295
+ static void *operator new(size_t s) {
296
+ py::print("B new", s);
297
+ return ::operator new(s);
298
+ }
299
+ static void *operator new(size_t s, void *ptr) {
300
+ py::print("B placement-new", s);
301
+ return ptr;
302
+ }
303
+ static void operator delete(void *p, size_t s) {
304
+ py::print("B delete", s);
305
+ return ::operator delete(p);
306
+ }
307
+ };
308
+ struct AliasedHasOpNewDelSize {
309
+ std::uint64_t i;
310
+ static void *operator new(size_t s) {
311
+ py::print("C new", s);
312
+ return ::operator new(s);
313
+ }
314
+ static void *operator new(size_t s, void *ptr) {
315
+ py::print("C placement-new", s);
316
+ return ptr;
317
+ }
318
+ static void operator delete(void *p, size_t s) {
319
+ py::print("C delete", s);
320
+ return ::operator delete(p);
321
+ }
322
+ virtual ~AliasedHasOpNewDelSize() = default;
323
+ AliasedHasOpNewDelSize() = default;
324
+ AliasedHasOpNewDelSize(const AliasedHasOpNewDelSize &) = delete;
325
+ };
326
+ struct PyAliasedHasOpNewDelSize : AliasedHasOpNewDelSize {
327
+ PyAliasedHasOpNewDelSize() = default;
328
+ explicit PyAliasedHasOpNewDelSize(int) {}
329
+ std::uint64_t j;
330
+ };
331
+ struct HasOpNewDelBoth {
332
+ std::uint32_t i[8];
333
+ static void *operator new(size_t s) {
334
+ py::print("D new", s);
335
+ return ::operator new(s);
336
+ }
337
+ static void *operator new(size_t s, void *ptr) {
338
+ py::print("D placement-new", s);
339
+ return ptr;
340
+ }
341
+ static void operator delete(void *p) {
342
+ py::print("D delete");
343
+ return ::operator delete(p);
344
+ }
345
+ static void operator delete(void *p, size_t s) {
346
+ py::print("D wrong delete", s);
347
+ return ::operator delete(p);
348
+ }
349
+ };
350
+ py::class_<HasOpNewDel>(m, "HasOpNewDel").def(py::init<>());
351
+ py::class_<HasOpNewDelSize>(m, "HasOpNewDelSize").def(py::init<>());
352
+ py::class_<HasOpNewDelBoth>(m, "HasOpNewDelBoth").def(py::init<>());
353
+ py::class_<AliasedHasOpNewDelSize, PyAliasedHasOpNewDelSize> aliased(m,
354
+ "AliasedHasOpNewDelSize");
355
+ aliased.def(py::init<>());
356
+ aliased.attr("size_noalias") = py::int_(sizeof(AliasedHasOpNewDelSize));
357
+ aliased.attr("size_alias") = py::int_(sizeof(PyAliasedHasOpNewDelSize));
358
+
359
+ // This test is actually part of test_local_bindings (test_duplicate_local), but we need a
360
+ // definition in a different compilation unit within the same module:
361
+ bind_local<LocalExternal, 17>(m, "LocalExternal", py::module_local());
362
+
363
+ // test_bind_protected_functions
364
+ class ProtectedA {
365
+ protected:
366
+ int foo() const { return value; }
367
+
368
+ private:
369
+ int value = 42;
370
+ };
371
+
372
+ class PublicistA : public ProtectedA {
373
+ public:
374
+ using ProtectedA::foo;
375
+ };
376
+
377
+ py::class_<ProtectedA>(m, "ProtectedA").def(py::init<>()).def("foo", &PublicistA::foo);
378
+
379
+ class ProtectedB {
380
+ public:
381
+ virtual ~ProtectedB() = default;
382
+ ProtectedB() = default;
383
+ ProtectedB(const ProtectedB &) = delete;
384
+
385
+ protected:
386
+ virtual int foo() const { return value; }
387
+ virtual void *void_foo() { return static_cast<void *>(&value); }
388
+ virtual void *get_self() { return static_cast<void *>(this); }
389
+
390
+ private:
391
+ int value = 42;
392
+ };
393
+
394
+ class TrampolineB : public ProtectedB {
395
+ public:
396
+ int foo() const override { PYBIND11_OVERRIDE(int, ProtectedB, foo, ); }
397
+ void *void_foo() override { PYBIND11_OVERRIDE(void *, ProtectedB, void_foo, ); }
398
+ void *get_self() override { PYBIND11_OVERRIDE(void *, ProtectedB, get_self, ); }
399
+ };
400
+
401
+ class PublicistB : public ProtectedB {
402
+ public:
403
+ // [workaround(intel)] = default does not work here
404
+ // Removing or defaulting this destructor results in linking errors with the Intel compiler
405
+ // (in Debug builds only, tested with icpc (ICC) 2021.1 Beta 20200827)
406
+ ~PublicistB() override{}; // NOLINT(modernize-use-equals-default)
407
+ using ProtectedB::foo;
408
+ using ProtectedB::get_self;
409
+ using ProtectedB::void_foo;
410
+ };
411
+
412
+ m.def("read_foo", [](const void *original) {
413
+ const int *ptr = reinterpret_cast<const int *>(original);
414
+ return *ptr;
415
+ });
416
+
417
+ m.def("pointers_equal",
418
+ [](const void *original, const void *comparison) { return original == comparison; });
419
+
420
+ py::class_<ProtectedB, TrampolineB>(m, "ProtectedB")
421
+ .def(py::init<>())
422
+ .def("foo", &PublicistB::foo)
423
+ .def("void_foo", &PublicistB::void_foo)
424
+ .def("get_self", &PublicistB::get_self);
425
+
426
+ // test_brace_initialization
427
+ struct BraceInitialization {
428
+ int field1;
429
+ std::string field2;
430
+ };
431
+
432
+ py::class_<BraceInitialization>(m, "BraceInitialization")
433
+ .def(py::init<int, const std::string &>())
434
+ .def_readwrite("field1", &BraceInitialization::field1)
435
+ .def_readwrite("field2", &BraceInitialization::field2);
436
+ // We *don't* want to construct using braces when the given constructor argument maps to a
437
+ // constructor, because brace initialization could go to the wrong place (in particular when
438
+ // there is also an `initializer_list<T>`-accept constructor):
439
+ py::class_<NoBraceInitialization>(m, "NoBraceInitialization")
440
+ .def(py::init<std::vector<int>>())
441
+ .def_readonly("vec", &NoBraceInitialization::vec);
442
+
443
+ // test_reentrant_implicit_conversion_failure
444
+ // #1035: issue with runaway reentrant implicit conversion
445
+ struct BogusImplicitConversion {
446
+ BogusImplicitConversion(const BogusImplicitConversion &) = default;
447
+ };
448
+
449
+ py::class_<BogusImplicitConversion>(m, "BogusImplicitConversion")
450
+ .def(py::init<const BogusImplicitConversion &>());
451
+
452
+ py::implicitly_convertible<int, BogusImplicitConversion>();
453
+
454
+ // test_qualname
455
+ // #1166: nested class docstring doesn't show nested name
456
+ // Also related: tests that __qualname__ is set properly
457
+ struct NestBase {};
458
+ struct Nested {};
459
+ py::class_<NestBase> base(m, "NestBase");
460
+ base.def(py::init<>());
461
+ py::class_<Nested>(base, "Nested")
462
+ .def(py::init<>())
463
+ .def("fn", [](Nested &, int, NestBase &, Nested &) {})
464
+ .def(
465
+ "fa", [](Nested &, int, NestBase &, Nested &) {}, "a"_a, "b"_a, "c"_a);
466
+ base.def("g", [](NestBase &, Nested &) {});
467
+ base.def("h", []() { return NestBase(); });
468
+
469
+ // test_error_after_conversion
470
+ // The second-pass path through dispatcher() previously didn't
471
+ // remember which overload was used, and would crash trying to
472
+ // generate a useful error message
473
+
474
+ struct NotRegistered {};
475
+ struct StringWrapper {
476
+ std::string str;
477
+ };
478
+ m.def("test_error_after_conversions", [](int) {});
479
+ m.def("test_error_after_conversions",
480
+ [](const StringWrapper &) -> NotRegistered { return {}; });
481
+ py::class_<StringWrapper>(m, "StringWrapper").def(py::init<std::string>());
482
+ py::implicitly_convertible<std::string, StringWrapper>();
483
+
484
+ #if defined(PYBIND11_CPP17)
485
+ struct alignas(1024) Aligned {
486
+ std::uintptr_t ptr() const { return (uintptr_t) this; }
487
+ };
488
+ py::class_<Aligned>(m, "Aligned").def(py::init<>()).def("ptr", &Aligned::ptr);
489
+ #endif
490
+
491
+ // test_final
492
+ struct IsFinal final {};
493
+ py::class_<IsFinal>(m, "IsFinal", py::is_final());
494
+
495
+ // test_non_final_final
496
+ struct IsNonFinalFinal {};
497
+ py::class_<IsNonFinalFinal>(m, "IsNonFinalFinal", py::is_final());
498
+
499
+ // test_exception_rvalue_abort
500
+ struct PyPrintDestructor {
501
+ PyPrintDestructor() = default;
502
+ ~PyPrintDestructor() { py::print("Print from destructor"); }
503
+ void throw_something() { throw std::runtime_error("error"); }
504
+ };
505
+ py::class_<PyPrintDestructor>(m, "PyPrintDestructor")
506
+ .def(py::init<>())
507
+ .def("throw_something", &PyPrintDestructor::throw_something);
508
+
509
+ // test_multiple_instances_with_same_pointer
510
+ struct SamePointer {};
511
+ static SamePointer samePointer;
512
+ py::class_<SamePointer, std::unique_ptr<SamePointer, py::nodelete>>(m, "SamePointer")
513
+ .def(py::init([]() { return &samePointer; }));
514
+
515
+ struct Empty {};
516
+ py::class_<Empty>(m, "Empty").def(py::init<>());
517
+
518
+ // test_base_and_derived_nested_scope
519
+ struct BaseWithNested {
520
+ struct Nested {};
521
+ };
522
+
523
+ struct DerivedWithNested : BaseWithNested {
524
+ struct Nested {};
525
+ };
526
+
527
+ py::class_<BaseWithNested> baseWithNested_class(m, "BaseWithNested");
528
+ py::class_<DerivedWithNested, BaseWithNested> derivedWithNested_class(m, "DerivedWithNested");
529
+ py::class_<BaseWithNested::Nested>(baseWithNested_class, "Nested")
530
+ .def_static("get_name", []() { return "BaseWithNested::Nested"; });
531
+ py::class_<DerivedWithNested::Nested>(derivedWithNested_class, "Nested")
532
+ .def_static("get_name", []() { return "DerivedWithNested::Nested"; });
533
+
534
+ // test_register_duplicate_class
535
+ struct Duplicate {};
536
+ struct OtherDuplicate {};
537
+ struct DuplicateNested {};
538
+ struct OtherDuplicateNested {};
539
+
540
+ m.def("register_duplicate_class_name", [](const py::module_ &m) {
541
+ py::class_<Duplicate>(m, "Duplicate");
542
+ py::class_<OtherDuplicate>(m, "Duplicate");
543
+ });
544
+ m.def("register_duplicate_class_type", [](const py::module_ &m) {
545
+ py::class_<OtherDuplicate>(m, "OtherDuplicate");
546
+ py::class_<OtherDuplicate>(m, "YetAnotherDuplicate");
547
+ });
548
+ m.def("register_duplicate_nested_class_name", [](const py::object &gt) {
549
+ py::class_<DuplicateNested>(gt, "DuplicateNested");
550
+ py::class_<OtherDuplicateNested>(gt, "DuplicateNested");
551
+ });
552
+ m.def("register_duplicate_nested_class_type", [](const py::object &gt) {
553
+ py::class_<OtherDuplicateNested>(gt, "OtherDuplicateNested");
554
+ py::class_<OtherDuplicateNested>(gt, "YetAnotherDuplicateNested");
555
+ });
556
+
557
+ test_class::pr4220_tripped_over_this::bind_empty0(m);
558
+ }
559
+
560
+ template <int N>
561
+ class BreaksBase {
562
+ public:
563
+ virtual ~BreaksBase() = default;
564
+ BreaksBase() = default;
565
+ BreaksBase(const BreaksBase &) = delete;
566
+ };
567
+ template <int N>
568
+ class BreaksTramp : public BreaksBase<N> {};
569
+ // These should all compile just fine:
570
+ using DoesntBreak1 = py::class_<BreaksBase<1>, std::unique_ptr<BreaksBase<1>>, BreaksTramp<1>>;
571
+ using DoesntBreak2 = py::class_<BreaksBase<2>, BreaksTramp<2>, std::unique_ptr<BreaksBase<2>>>;
572
+ using DoesntBreak3 = py::class_<BreaksBase<3>, std::unique_ptr<BreaksBase<3>>>;
573
+ using DoesntBreak4 = py::class_<BreaksBase<4>, BreaksTramp<4>>;
574
+ using DoesntBreak5 = py::class_<BreaksBase<5>>;
575
+ using DoesntBreak6 = py::class_<BreaksBase<6>, std::shared_ptr<BreaksBase<6>>, BreaksTramp<6>>;
576
+ using DoesntBreak7 = py::class_<BreaksBase<7>, BreaksTramp<7>, std::shared_ptr<BreaksBase<7>>>;
577
+ using DoesntBreak8 = py::class_<BreaksBase<8>, std::shared_ptr<BreaksBase<8>>>;
578
+ #define CHECK_BASE(N) \
579
+ static_assert(std::is_same<typename DoesntBreak##N::type, BreaksBase<(N)>>::value, \
580
+ "DoesntBreak" #N " has wrong type!")
581
+ CHECK_BASE(1);
582
+ CHECK_BASE(2);
583
+ CHECK_BASE(3);
584
+ CHECK_BASE(4);
585
+ CHECK_BASE(5);
586
+ CHECK_BASE(6);
587
+ CHECK_BASE(7);
588
+ CHECK_BASE(8);
589
+ #define CHECK_ALIAS(N) \
590
+ static_assert( \
591
+ DoesntBreak##N::has_alias \
592
+ && std::is_same<typename DoesntBreak##N::type_alias, BreaksTramp<(N)>>::value, \
593
+ "DoesntBreak" #N " has wrong type_alias!")
594
+ #define CHECK_NOALIAS(N) \
595
+ static_assert(!DoesntBreak##N::has_alias \
596
+ && std::is_void<typename DoesntBreak##N::type_alias>::value, \
597
+ "DoesntBreak" #N " has type alias, but shouldn't!")
598
+ CHECK_ALIAS(1);
599
+ CHECK_ALIAS(2);
600
+ CHECK_NOALIAS(3);
601
+ CHECK_ALIAS(4);
602
+ CHECK_NOALIAS(5);
603
+ CHECK_ALIAS(6);
604
+ CHECK_ALIAS(7);
605
+ CHECK_NOALIAS(8);
606
+ #define CHECK_HOLDER(N, TYPE) \
607
+ static_assert(std::is_same<typename DoesntBreak##N::holder_type, \
608
+ std::TYPE##_ptr<BreaksBase<(N)>>>::value, \
609
+ "DoesntBreak" #N " has wrong holder_type!")
610
+ CHECK_HOLDER(1, unique);
611
+ CHECK_HOLDER(2, unique);
612
+ CHECK_HOLDER(3, unique);
613
+ CHECK_HOLDER(4, unique);
614
+ CHECK_HOLDER(5, unique);
615
+ CHECK_HOLDER(6, shared);
616
+ CHECK_HOLDER(7, shared);
617
+ CHECK_HOLDER(8, shared);
618
+
619
+ // There's no nice way to test that these fail because they fail to compile; leave them here,
620
+ // though, so that they can be manually tested by uncommenting them (and seeing that compilation
621
+ // failures occurs).
622
+
623
+ // We have to actually look into the type: the typedef alone isn't enough to instantiate the type:
624
+ #define CHECK_BROKEN(N) \
625
+ static_assert(std::is_same<typename Breaks##N::type, BreaksBase<-(N)>>::value, \
626
+ "Breaks1 has wrong type!");
627
+
628
+ #ifdef PYBIND11_NEVER_DEFINED_EVER
629
+ // Two holder classes:
630
+ typedef py::
631
+ class_<BreaksBase<-1>, std::unique_ptr<BreaksBase<-1>>, std::unique_ptr<BreaksBase<-1>>>
632
+ Breaks1;
633
+ CHECK_BROKEN(1);
634
+ // Two aliases:
635
+ typedef py::class_<BreaksBase<-2>, BreaksTramp<-2>, BreaksTramp<-2>> Breaks2;
636
+ CHECK_BROKEN(2);
637
+ // Holder + 2 aliases
638
+ typedef py::
639
+ class_<BreaksBase<-3>, std::unique_ptr<BreaksBase<-3>>, BreaksTramp<-3>, BreaksTramp<-3>>
640
+ Breaks3;
641
+ CHECK_BROKEN(3);
642
+ // Alias + 2 holders
643
+ typedef py::class_<BreaksBase<-4>,
644
+ std::unique_ptr<BreaksBase<-4>>,
645
+ BreaksTramp<-4>,
646
+ std::shared_ptr<BreaksBase<-4>>>
647
+ Breaks4;
648
+ CHECK_BROKEN(4);
649
+ // Invalid option (not a subclass or holder)
650
+ typedef py::class_<BreaksBase<-5>, BreaksTramp<-4>> Breaks5;
651
+ CHECK_BROKEN(5);
652
+ // Invalid option: multiple inheritance not supported:
653
+ template <>
654
+ struct BreaksBase<-8> : BreaksBase<-6>, BreaksBase<-7> {};
655
+ typedef py::class_<BreaksBase<-8>, BreaksBase<-6>, BreaksBase<-7>> Breaks8;
656
+ CHECK_BROKEN(8);
657
+ #endif
third_party/CityFlow/extern/pybind11/tests/test_class.py CHANGED
@@ -1,499 +1,499 @@
1
- from unittest import mock
2
-
3
- import pytest
4
-
5
- import env
6
- from pybind11_tests import ConstructorStats, UserType
7
- from pybind11_tests import class_ as m
8
-
9
-
10
- def test_obj_class_name():
11
- expected_name = "UserType" if env.PYPY else "pybind11_tests.UserType"
12
- assert m.obj_class_name(UserType(1)) == expected_name
13
- assert m.obj_class_name(UserType) == expected_name
14
-
15
-
16
- def test_repr():
17
- assert "pybind11_type" in repr(type(UserType))
18
- assert "UserType" in repr(UserType)
19
-
20
-
21
- def test_instance(msg):
22
- with pytest.raises(TypeError) as excinfo:
23
- m.NoConstructor()
24
- assert msg(excinfo.value) == "m.class_.NoConstructor: No constructor defined!"
25
-
26
- instance = m.NoConstructor.new_instance()
27
-
28
- cstats = ConstructorStats.get(m.NoConstructor)
29
- assert cstats.alive() == 1
30
- del instance
31
- assert cstats.alive() == 0
32
-
33
-
34
- def test_instance_new():
35
- instance = m.NoConstructorNew() # .__new__(m.NoConstructor.__class__)
36
- cstats = ConstructorStats.get(m.NoConstructorNew)
37
- assert cstats.alive() == 1
38
- del instance
39
- assert cstats.alive() == 0
40
-
41
-
42
- def test_type():
43
- assert m.check_type(1) == m.DerivedClass1
44
- with pytest.raises(RuntimeError) as execinfo:
45
- m.check_type(0)
46
-
47
- assert "pybind11::detail::get_type_info: unable to find type info" in str(
48
- execinfo.value
49
- )
50
- assert "Invalid" in str(execinfo.value)
51
-
52
- # Currently not supported
53
- # See https://github.com/pybind/pybind11/issues/2486
54
- # assert m.check_type(2) == int
55
-
56
-
57
- def test_type_of_py():
58
- assert m.get_type_of(1) == int
59
- assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
60
- assert m.get_type_of(int) == type
61
-
62
-
63
- def test_type_of_classic():
64
- assert m.get_type_classic(1) == int
65
- assert m.get_type_classic(m.DerivedClass1()) == m.DerivedClass1
66
- assert m.get_type_classic(int) == type
67
-
68
-
69
- def test_type_of_py_nodelete():
70
- # If the above test deleted the class, this will segfault
71
- assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
72
-
73
-
74
- def test_as_type_py():
75
- assert m.as_type(int) == int
76
-
77
- with pytest.raises(TypeError):
78
- assert m.as_type(1) == int
79
-
80
- with pytest.raises(TypeError):
81
- assert m.as_type(m.DerivedClass1()) == m.DerivedClass1
82
-
83
-
84
- def test_docstrings(doc):
85
- assert doc(UserType) == "A `py::class_` type for testing"
86
- assert UserType.__name__ == "UserType"
87
- assert UserType.__module__ == "pybind11_tests"
88
- assert UserType.get_value.__name__ == "get_value"
89
- assert UserType.get_value.__module__ == "pybind11_tests"
90
-
91
- assert (
92
- doc(UserType.get_value)
93
- == """
94
- get_value(self: m.UserType) -> int
95
-
96
- Get value using a method
97
- """
98
- )
99
- assert doc(UserType.value) == "Get/set value using a property"
100
-
101
- assert (
102
- doc(m.NoConstructor.new_instance)
103
- == """
104
- new_instance() -> m.class_.NoConstructor
105
-
106
- Return an instance
107
- """
108
- )
109
-
110
-
111
- def test_qualname(doc):
112
- """Tests that a properly qualified name is set in __qualname__ and that
113
- generated docstrings properly use it and the module name"""
114
- assert m.NestBase.__qualname__ == "NestBase"
115
- assert m.NestBase.Nested.__qualname__ == "NestBase.Nested"
116
-
117
- assert (
118
- doc(m.NestBase.__init__)
119
- == """
120
- __init__(self: m.class_.NestBase) -> None
121
- """
122
- )
123
- assert (
124
- doc(m.NestBase.g)
125
- == """
126
- g(self: m.class_.NestBase, arg0: m.class_.NestBase.Nested) -> None
127
- """
128
- )
129
- assert (
130
- doc(m.NestBase.Nested.__init__)
131
- == """
132
- __init__(self: m.class_.NestBase.Nested) -> None
133
- """
134
- )
135
- assert (
136
- doc(m.NestBase.Nested.fn)
137
- == """
138
- fn(self: m.class_.NestBase.Nested, arg0: int, arg1: m.class_.NestBase, arg2: m.class_.NestBase.Nested) -> None
139
- """
140
- )
141
- assert (
142
- doc(m.NestBase.Nested.fa)
143
- == """
144
- fa(self: m.class_.NestBase.Nested, a: int, b: m.class_.NestBase, c: m.class_.NestBase.Nested) -> None
145
- """
146
- )
147
- assert m.NestBase.__module__ == "pybind11_tests.class_"
148
- assert m.NestBase.Nested.__module__ == "pybind11_tests.class_"
149
-
150
-
151
- def test_inheritance(msg):
152
- roger = m.Rabbit("Rabbit")
153
- assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot"
154
- assert m.pet_name_species(roger) == "Rabbit is a parrot"
155
-
156
- polly = m.Pet("Polly", "parrot")
157
- assert polly.name() + " is a " + polly.species() == "Polly is a parrot"
158
- assert m.pet_name_species(polly) == "Polly is a parrot"
159
-
160
- molly = m.Dog("Molly")
161
- assert molly.name() + " is a " + molly.species() == "Molly is a dog"
162
- assert m.pet_name_species(molly) == "Molly is a dog"
163
-
164
- fred = m.Hamster("Fred")
165
- assert fred.name() + " is a " + fred.species() == "Fred is a rodent"
166
-
167
- assert m.dog_bark(molly) == "Woof!"
168
-
169
- with pytest.raises(TypeError) as excinfo:
170
- m.dog_bark(polly)
171
- assert (
172
- msg(excinfo.value)
173
- == """
174
- dog_bark(): incompatible function arguments. The following argument types are supported:
175
- 1. (arg0: m.class_.Dog) -> str
176
-
177
- Invoked with: <m.class_.Pet object at 0>
178
- """
179
- )
180
-
181
- with pytest.raises(TypeError) as excinfo:
182
- m.Chimera("lion", "goat")
183
- assert "No constructor defined!" in str(excinfo.value)
184
-
185
-
186
- def test_inheritance_init(msg):
187
- # Single base
188
- class Python(m.Pet):
189
- def __init__(self):
190
- pass
191
-
192
- with pytest.raises(TypeError) as exc_info:
193
- Python()
194
- expected = "m.class_.Pet.__init__() must be called when overriding __init__"
195
- assert msg(exc_info.value) == expected
196
-
197
- # Multiple bases
198
- class RabbitHamster(m.Rabbit, m.Hamster):
199
- def __init__(self):
200
- m.Rabbit.__init__(self, "RabbitHamster")
201
-
202
- with pytest.raises(TypeError) as exc_info:
203
- RabbitHamster()
204
- expected = "m.class_.Hamster.__init__() must be called when overriding __init__"
205
- assert msg(exc_info.value) == expected
206
-
207
-
208
- @pytest.mark.parametrize(
209
- "mock_return_value", [None, (1, 2, 3), m.Pet("Polly", "parrot"), m.Dog("Molly")]
210
- )
211
- def test_mock_new(mock_return_value):
212
- with mock.patch.object(
213
- m.Pet, "__new__", return_value=mock_return_value
214
- ) as mock_new:
215
- obj = m.Pet("Noname", "Nospecies")
216
- assert obj is mock_return_value
217
- mock_new.assert_called_once_with(m.Pet, "Noname", "Nospecies")
218
-
219
-
220
- def test_automatic_upcasting():
221
- assert type(m.return_class_1()).__name__ == "DerivedClass1"
222
- assert type(m.return_class_2()).__name__ == "DerivedClass2"
223
- assert type(m.return_none()).__name__ == "NoneType"
224
- # Repeat these a few times in a random order to ensure no invalid caching is applied
225
- assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
226
- assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
227
- assert type(m.return_class_n(0)).__name__ == "BaseClass"
228
- assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
229
- assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
230
- assert type(m.return_class_n(0)).__name__ == "BaseClass"
231
- assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
232
-
233
-
234
- def test_isinstance():
235
- objects = [(), {}, m.Pet("Polly", "parrot")] + [m.Dog("Molly")] * 4
236
- expected = (True, True, True, True, True, False, False)
237
- assert m.check_instances(objects) == expected
238
-
239
-
240
- def test_mismatched_holder():
241
- import re
242
-
243
- with pytest.raises(RuntimeError) as excinfo:
244
- m.mismatched_holder_1()
245
- assert re.match(
246
- 'generic_type: type ".*MismatchDerived1" does not have a non-default '
247
- 'holder type while its base ".*MismatchBase1" does',
248
- str(excinfo.value),
249
- )
250
-
251
- with pytest.raises(RuntimeError) as excinfo:
252
- m.mismatched_holder_2()
253
- assert re.match(
254
- 'generic_type: type ".*MismatchDerived2" has a non-default holder type '
255
- 'while its base ".*MismatchBase2" does not',
256
- str(excinfo.value),
257
- )
258
-
259
-
260
- def test_override_static():
261
- """#511: problem with inheritance + overwritten def_static"""
262
- b = m.MyBase.make()
263
- d1 = m.MyDerived.make2()
264
- d2 = m.MyDerived.make()
265
-
266
- assert isinstance(b, m.MyBase)
267
- assert isinstance(d1, m.MyDerived)
268
- assert isinstance(d2, m.MyDerived)
269
-
270
-
271
- def test_implicit_conversion_life_support():
272
- """Ensure the lifetime of temporary objects created for implicit conversions"""
273
- assert m.implicitly_convert_argument(UserType(5)) == 5
274
- assert m.implicitly_convert_variable(UserType(5)) == 5
275
-
276
- assert "outside a bound function" in m.implicitly_convert_variable_fail(UserType(5))
277
-
278
-
279
- def test_operator_new_delete(capture):
280
- """Tests that class-specific operator new/delete functions are invoked"""
281
-
282
- class SubAliased(m.AliasedHasOpNewDelSize):
283
- pass
284
-
285
- with capture:
286
- a = m.HasOpNewDel()
287
- b = m.HasOpNewDelSize()
288
- d = m.HasOpNewDelBoth()
289
- assert (
290
- capture
291
- == """
292
- A new 8
293
- B new 4
294
- D new 32
295
- """
296
- )
297
- sz_alias = str(m.AliasedHasOpNewDelSize.size_alias)
298
- sz_noalias = str(m.AliasedHasOpNewDelSize.size_noalias)
299
- with capture:
300
- c = m.AliasedHasOpNewDelSize()
301
- c2 = SubAliased()
302
- assert capture == ("C new " + sz_noalias + "\n" + "C new " + sz_alias + "\n")
303
-
304
- with capture:
305
- del a
306
- pytest.gc_collect()
307
- del b
308
- pytest.gc_collect()
309
- del d
310
- pytest.gc_collect()
311
- assert (
312
- capture
313
- == """
314
- A delete
315
- B delete 4
316
- D delete
317
- """
318
- )
319
-
320
- with capture:
321
- del c
322
- pytest.gc_collect()
323
- del c2
324
- pytest.gc_collect()
325
- assert capture == ("C delete " + sz_noalias + "\n" + "C delete " + sz_alias + "\n")
326
-
327
-
328
- def test_bind_protected_functions():
329
- """Expose protected member functions to Python using a helper class"""
330
- a = m.ProtectedA()
331
- assert a.foo() == 42
332
-
333
- b = m.ProtectedB()
334
- assert b.foo() == 42
335
- assert m.read_foo(b.void_foo()) == 42
336
- assert m.pointers_equal(b.get_self(), b)
337
-
338
- class C(m.ProtectedB):
339
- def __init__(self):
340
- m.ProtectedB.__init__(self)
341
-
342
- def foo(self):
343
- return 0
344
-
345
- c = C()
346
- assert c.foo() == 0
347
-
348
-
349
- def test_brace_initialization():
350
- """Tests that simple POD classes can be constructed using C++11 brace initialization"""
351
- a = m.BraceInitialization(123, "test")
352
- assert a.field1 == 123
353
- assert a.field2 == "test"
354
-
355
- # Tests that a non-simple class doesn't get brace initialization (if the
356
- # class defines an initializer_list constructor, in particular, it would
357
- # win over the expected constructor).
358
- b = m.NoBraceInitialization([123, 456])
359
- assert b.vec == [123, 456]
360
-
361
-
362
- @pytest.mark.xfail("env.PYPY")
363
- def test_class_refcount():
364
- """Instances must correctly increase/decrease the reference count of their types (#1029)"""
365
- from sys import getrefcount
366
-
367
- class PyDog(m.Dog):
368
- pass
369
-
370
- for cls in m.Dog, PyDog:
371
- refcount_1 = getrefcount(cls)
372
- molly = [cls("Molly") for _ in range(10)]
373
- refcount_2 = getrefcount(cls)
374
-
375
- del molly
376
- pytest.gc_collect()
377
- refcount_3 = getrefcount(cls)
378
-
379
- assert refcount_1 == refcount_3
380
- assert refcount_2 > refcount_1
381
-
382
-
383
- def test_reentrant_implicit_conversion_failure(msg):
384
- # ensure that there is no runaway reentrant implicit conversion (#1035)
385
- with pytest.raises(TypeError) as excinfo:
386
- m.BogusImplicitConversion(0)
387
- assert (
388
- msg(excinfo.value)
389
- == """
390
- __init__(): incompatible constructor arguments. The following argument types are supported:
391
- 1. m.class_.BogusImplicitConversion(arg0: m.class_.BogusImplicitConversion)
392
-
393
- Invoked with: 0
394
- """
395
- )
396
-
397
-
398
- def test_error_after_conversions():
399
- with pytest.raises(TypeError) as exc_info:
400
- m.test_error_after_conversions("hello")
401
- assert str(exc_info.value).startswith(
402
- "Unable to convert function return value to a Python type!"
403
- )
404
-
405
-
406
- def test_aligned():
407
- if hasattr(m, "Aligned"):
408
- p = m.Aligned().ptr()
409
- assert p % 1024 == 0
410
-
411
-
412
- # https://foss.heptapod.net/pypy/pypy/-/issues/2742
413
- @pytest.mark.xfail("env.PYPY")
414
- def test_final():
415
- with pytest.raises(TypeError) as exc_info:
416
-
417
- class PyFinalChild(m.IsFinal):
418
- pass
419
-
420
- assert str(exc_info.value).endswith("is not an acceptable base type")
421
-
422
-
423
- # https://foss.heptapod.net/pypy/pypy/-/issues/2742
424
- @pytest.mark.xfail("env.PYPY")
425
- def test_non_final_final():
426
- with pytest.raises(TypeError) as exc_info:
427
-
428
- class PyNonFinalFinalChild(m.IsNonFinalFinal):
429
- pass
430
-
431
- assert str(exc_info.value).endswith("is not an acceptable base type")
432
-
433
-
434
- # https://github.com/pybind/pybind11/issues/1878
435
- def test_exception_rvalue_abort():
436
- with pytest.raises(RuntimeError):
437
- m.PyPrintDestructor().throw_something()
438
-
439
-
440
- # https://github.com/pybind/pybind11/issues/1568
441
- def test_multiple_instances_with_same_pointer():
442
- n = 100
443
- instances = [m.SamePointer() for _ in range(n)]
444
- for i in range(n):
445
- # We need to reuse the same allocated memory for with a different type,
446
- # to ensure the bug in `deregister_instance_impl` is detected. Otherwise
447
- # `Py_TYPE(self) == Py_TYPE(it->second)` will still succeed, even though
448
- # the `instance` is already deleted.
449
- instances[i] = m.Empty()
450
- # No assert: if this does not trigger the error
451
- # pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
452
- # and just completes without crashing, we're good.
453
-
454
-
455
- # https://github.com/pybind/pybind11/issues/1624
456
- def test_base_and_derived_nested_scope():
457
- assert issubclass(m.DerivedWithNested, m.BaseWithNested)
458
- assert m.BaseWithNested.Nested != m.DerivedWithNested.Nested
459
- assert m.BaseWithNested.Nested.get_name() == "BaseWithNested::Nested"
460
- assert m.DerivedWithNested.Nested.get_name() == "DerivedWithNested::Nested"
461
-
462
-
463
- def test_register_duplicate_class():
464
- import types
465
-
466
- module_scope = types.ModuleType("module_scope")
467
- with pytest.raises(RuntimeError) as exc_info:
468
- m.register_duplicate_class_name(module_scope)
469
- expected = (
470
- 'generic_type: cannot initialize type "Duplicate": '
471
- "an object with that name is already defined"
472
- )
473
- assert str(exc_info.value) == expected
474
- with pytest.raises(RuntimeError) as exc_info:
475
- m.register_duplicate_class_type(module_scope)
476
- expected = 'generic_type: type "YetAnotherDuplicate" is already registered!'
477
- assert str(exc_info.value) == expected
478
-
479
- class ClassScope:
480
- pass
481
-
482
- with pytest.raises(RuntimeError) as exc_info:
483
- m.register_duplicate_nested_class_name(ClassScope)
484
- expected = (
485
- 'generic_type: cannot initialize type "DuplicateNested": '
486
- "an object with that name is already defined"
487
- )
488
- assert str(exc_info.value) == expected
489
- with pytest.raises(RuntimeError) as exc_info:
490
- m.register_duplicate_nested_class_type(ClassScope)
491
- expected = 'generic_type: type "YetAnotherDuplicateNested" is already registered!'
492
- assert str(exc_info.value) == expected
493
-
494
-
495
- def test_pr4220_tripped_over_this():
496
- assert (
497
- m.Empty0().get_msg()
498
- == "This is really only meant to exercise successful compilation."
499
- )
 
1
+ from unittest import mock
2
+
3
+ import pytest
4
+
5
+ import env
6
+ from pybind11_tests import ConstructorStats, UserType
7
+ from pybind11_tests import class_ as m
8
+
9
+
10
+ def test_obj_class_name():
11
+ expected_name = "UserType" if env.PYPY else "pybind11_tests.UserType"
12
+ assert m.obj_class_name(UserType(1)) == expected_name
13
+ assert m.obj_class_name(UserType) == expected_name
14
+
15
+
16
+ def test_repr():
17
+ assert "pybind11_type" in repr(type(UserType))
18
+ assert "UserType" in repr(UserType)
19
+
20
+
21
+ def test_instance(msg):
22
+ with pytest.raises(TypeError) as excinfo:
23
+ m.NoConstructor()
24
+ assert msg(excinfo.value) == "m.class_.NoConstructor: No constructor defined!"
25
+
26
+ instance = m.NoConstructor.new_instance()
27
+
28
+ cstats = ConstructorStats.get(m.NoConstructor)
29
+ assert cstats.alive() == 1
30
+ del instance
31
+ assert cstats.alive() == 0
32
+
33
+
34
+ def test_instance_new():
35
+ instance = m.NoConstructorNew() # .__new__(m.NoConstructor.__class__)
36
+ cstats = ConstructorStats.get(m.NoConstructorNew)
37
+ assert cstats.alive() == 1
38
+ del instance
39
+ assert cstats.alive() == 0
40
+
41
+
42
+ def test_type():
43
+ assert m.check_type(1) == m.DerivedClass1
44
+ with pytest.raises(RuntimeError) as execinfo:
45
+ m.check_type(0)
46
+
47
+ assert "pybind11::detail::get_type_info: unable to find type info" in str(
48
+ execinfo.value
49
+ )
50
+ assert "Invalid" in str(execinfo.value)
51
+
52
+ # Currently not supported
53
+ # See https://github.com/pybind/pybind11/issues/2486
54
+ # assert m.check_type(2) == int
55
+
56
+
57
+ def test_type_of_py():
58
+ assert m.get_type_of(1) == int
59
+ assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
60
+ assert m.get_type_of(int) == type
61
+
62
+
63
+ def test_type_of_classic():
64
+ assert m.get_type_classic(1) == int
65
+ assert m.get_type_classic(m.DerivedClass1()) == m.DerivedClass1
66
+ assert m.get_type_classic(int) == type
67
+
68
+
69
+ def test_type_of_py_nodelete():
70
+ # If the above test deleted the class, this will segfault
71
+ assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
72
+
73
+
74
+ def test_as_type_py():
75
+ assert m.as_type(int) == int
76
+
77
+ with pytest.raises(TypeError):
78
+ assert m.as_type(1) == int
79
+
80
+ with pytest.raises(TypeError):
81
+ assert m.as_type(m.DerivedClass1()) == m.DerivedClass1
82
+
83
+
84
+ def test_docstrings(doc):
85
+ assert doc(UserType) == "A `py::class_` type for testing"
86
+ assert UserType.__name__ == "UserType"
87
+ assert UserType.__module__ == "pybind11_tests"
88
+ assert UserType.get_value.__name__ == "get_value"
89
+ assert UserType.get_value.__module__ == "pybind11_tests"
90
+
91
+ assert (
92
+ doc(UserType.get_value)
93
+ == """
94
+ get_value(self: m.UserType) -> int
95
+
96
+ Get value using a method
97
+ """
98
+ )
99
+ assert doc(UserType.value) == "Get/set value using a property"
100
+
101
+ assert (
102
+ doc(m.NoConstructor.new_instance)
103
+ == """
104
+ new_instance() -> m.class_.NoConstructor
105
+
106
+ Return an instance
107
+ """
108
+ )
109
+
110
+
111
+ def test_qualname(doc):
112
+ """Tests that a properly qualified name is set in __qualname__ and that
113
+ generated docstrings properly use it and the module name"""
114
+ assert m.NestBase.__qualname__ == "NestBase"
115
+ assert m.NestBase.Nested.__qualname__ == "NestBase.Nested"
116
+
117
+ assert (
118
+ doc(m.NestBase.__init__)
119
+ == """
120
+ __init__(self: m.class_.NestBase) -> None
121
+ """
122
+ )
123
+ assert (
124
+ doc(m.NestBase.g)
125
+ == """
126
+ g(self: m.class_.NestBase, arg0: m.class_.NestBase.Nested) -> None
127
+ """
128
+ )
129
+ assert (
130
+ doc(m.NestBase.Nested.__init__)
131
+ == """
132
+ __init__(self: m.class_.NestBase.Nested) -> None
133
+ """
134
+ )
135
+ assert (
136
+ doc(m.NestBase.Nested.fn)
137
+ == """
138
+ fn(self: m.class_.NestBase.Nested, arg0: int, arg1: m.class_.NestBase, arg2: m.class_.NestBase.Nested) -> None
139
+ """
140
+ )
141
+ assert (
142
+ doc(m.NestBase.Nested.fa)
143
+ == """
144
+ fa(self: m.class_.NestBase.Nested, a: int, b: m.class_.NestBase, c: m.class_.NestBase.Nested) -> None
145
+ """
146
+ )
147
+ assert m.NestBase.__module__ == "pybind11_tests.class_"
148
+ assert m.NestBase.Nested.__module__ == "pybind11_tests.class_"
149
+
150
+
151
+ def test_inheritance(msg):
152
+ roger = m.Rabbit("Rabbit")
153
+ assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot"
154
+ assert m.pet_name_species(roger) == "Rabbit is a parrot"
155
+
156
+ polly = m.Pet("Polly", "parrot")
157
+ assert polly.name() + " is a " + polly.species() == "Polly is a parrot"
158
+ assert m.pet_name_species(polly) == "Polly is a parrot"
159
+
160
+ molly = m.Dog("Molly")
161
+ assert molly.name() + " is a " + molly.species() == "Molly is a dog"
162
+ assert m.pet_name_species(molly) == "Molly is a dog"
163
+
164
+ fred = m.Hamster("Fred")
165
+ assert fred.name() + " is a " + fred.species() == "Fred is a rodent"
166
+
167
+ assert m.dog_bark(molly) == "Woof!"
168
+
169
+ with pytest.raises(TypeError) as excinfo:
170
+ m.dog_bark(polly)
171
+ assert (
172
+ msg(excinfo.value)
173
+ == """
174
+ dog_bark(): incompatible function arguments. The following argument types are supported:
175
+ 1. (arg0: m.class_.Dog) -> str
176
+
177
+ Invoked with: <m.class_.Pet object at 0>
178
+ """
179
+ )
180
+
181
+ with pytest.raises(TypeError) as excinfo:
182
+ m.Chimera("lion", "goat")
183
+ assert "No constructor defined!" in str(excinfo.value)
184
+
185
+
186
+ def test_inheritance_init(msg):
187
+ # Single base
188
+ class Python(m.Pet):
189
+ def __init__(self):
190
+ pass
191
+
192
+ with pytest.raises(TypeError) as exc_info:
193
+ Python()
194
+ expected = "m.class_.Pet.__init__() must be called when overriding __init__"
195
+ assert msg(exc_info.value) == expected
196
+
197
+ # Multiple bases
198
+ class RabbitHamster(m.Rabbit, m.Hamster):
199
+ def __init__(self):
200
+ m.Rabbit.__init__(self, "RabbitHamster")
201
+
202
+ with pytest.raises(TypeError) as exc_info:
203
+ RabbitHamster()
204
+ expected = "m.class_.Hamster.__init__() must be called when overriding __init__"
205
+ assert msg(exc_info.value) == expected
206
+
207
+
208
+ @pytest.mark.parametrize(
209
+ "mock_return_value", [None, (1, 2, 3), m.Pet("Polly", "parrot"), m.Dog("Molly")]
210
+ )
211
+ def test_mock_new(mock_return_value):
212
+ with mock.patch.object(
213
+ m.Pet, "__new__", return_value=mock_return_value
214
+ ) as mock_new:
215
+ obj = m.Pet("Noname", "Nospecies")
216
+ assert obj is mock_return_value
217
+ mock_new.assert_called_once_with(m.Pet, "Noname", "Nospecies")
218
+
219
+
220
+ def test_automatic_upcasting():
221
+ assert type(m.return_class_1()).__name__ == "DerivedClass1"
222
+ assert type(m.return_class_2()).__name__ == "DerivedClass2"
223
+ assert type(m.return_none()).__name__ == "NoneType"
224
+ # Repeat these a few times in a random order to ensure no invalid caching is applied
225
+ assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
226
+ assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
227
+ assert type(m.return_class_n(0)).__name__ == "BaseClass"
228
+ assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
229
+ assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
230
+ assert type(m.return_class_n(0)).__name__ == "BaseClass"
231
+ assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
232
+
233
+
234
+ def test_isinstance():
235
+ objects = [(), {}, m.Pet("Polly", "parrot")] + [m.Dog("Molly")] * 4
236
+ expected = (True, True, True, True, True, False, False)
237
+ assert m.check_instances(objects) == expected
238
+
239
+
240
+ def test_mismatched_holder():
241
+ import re
242
+
243
+ with pytest.raises(RuntimeError) as excinfo:
244
+ m.mismatched_holder_1()
245
+ assert re.match(
246
+ 'generic_type: type ".*MismatchDerived1" does not have a non-default '
247
+ 'holder type while its base ".*MismatchBase1" does',
248
+ str(excinfo.value),
249
+ )
250
+
251
+ with pytest.raises(RuntimeError) as excinfo:
252
+ m.mismatched_holder_2()
253
+ assert re.match(
254
+ 'generic_type: type ".*MismatchDerived2" has a non-default holder type '
255
+ 'while its base ".*MismatchBase2" does not',
256
+ str(excinfo.value),
257
+ )
258
+
259
+
260
+ def test_override_static():
261
+ """#511: problem with inheritance + overwritten def_static"""
262
+ b = m.MyBase.make()
263
+ d1 = m.MyDerived.make2()
264
+ d2 = m.MyDerived.make()
265
+
266
+ assert isinstance(b, m.MyBase)
267
+ assert isinstance(d1, m.MyDerived)
268
+ assert isinstance(d2, m.MyDerived)
269
+
270
+
271
+ def test_implicit_conversion_life_support():
272
+ """Ensure the lifetime of temporary objects created for implicit conversions"""
273
+ assert m.implicitly_convert_argument(UserType(5)) == 5
274
+ assert m.implicitly_convert_variable(UserType(5)) == 5
275
+
276
+ assert "outside a bound function" in m.implicitly_convert_variable_fail(UserType(5))
277
+
278
+
279
+ def test_operator_new_delete(capture):
280
+ """Tests that class-specific operator new/delete functions are invoked"""
281
+
282
+ class SubAliased(m.AliasedHasOpNewDelSize):
283
+ pass
284
+
285
+ with capture:
286
+ a = m.HasOpNewDel()
287
+ b = m.HasOpNewDelSize()
288
+ d = m.HasOpNewDelBoth()
289
+ assert (
290
+ capture
291
+ == """
292
+ A new 8
293
+ B new 4
294
+ D new 32
295
+ """
296
+ )
297
+ sz_alias = str(m.AliasedHasOpNewDelSize.size_alias)
298
+ sz_noalias = str(m.AliasedHasOpNewDelSize.size_noalias)
299
+ with capture:
300
+ c = m.AliasedHasOpNewDelSize()
301
+ c2 = SubAliased()
302
+ assert capture == ("C new " + sz_noalias + "\n" + "C new " + sz_alias + "\n")
303
+
304
+ with capture:
305
+ del a
306
+ pytest.gc_collect()
307
+ del b
308
+ pytest.gc_collect()
309
+ del d
310
+ pytest.gc_collect()
311
+ assert (
312
+ capture
313
+ == """
314
+ A delete
315
+ B delete 4
316
+ D delete
317
+ """
318
+ )
319
+
320
+ with capture:
321
+ del c
322
+ pytest.gc_collect()
323
+ del c2
324
+ pytest.gc_collect()
325
+ assert capture == ("C delete " + sz_noalias + "\n" + "C delete " + sz_alias + "\n")
326
+
327
+
328
+ def test_bind_protected_functions():
329
+ """Expose protected member functions to Python using a helper class"""
330
+ a = m.ProtectedA()
331
+ assert a.foo() == 42
332
+
333
+ b = m.ProtectedB()
334
+ assert b.foo() == 42
335
+ assert m.read_foo(b.void_foo()) == 42
336
+ assert m.pointers_equal(b.get_self(), b)
337
+
338
+ class C(m.ProtectedB):
339
+ def __init__(self):
340
+ m.ProtectedB.__init__(self)
341
+
342
+ def foo(self):
343
+ return 0
344
+
345
+ c = C()
346
+ assert c.foo() == 0
347
+
348
+
349
+ def test_brace_initialization():
350
+ """Tests that simple POD classes can be constructed using C++11 brace initialization"""
351
+ a = m.BraceInitialization(123, "test")
352
+ assert a.field1 == 123
353
+ assert a.field2 == "test"
354
+
355
+ # Tests that a non-simple class doesn't get brace initialization (if the
356
+ # class defines an initializer_list constructor, in particular, it would
357
+ # win over the expected constructor).
358
+ b = m.NoBraceInitialization([123, 456])
359
+ assert b.vec == [123, 456]
360
+
361
+
362
+ @pytest.mark.xfail("env.PYPY")
363
+ def test_class_refcount():
364
+ """Instances must correctly increase/decrease the reference count of their types (#1029)"""
365
+ from sys import getrefcount
366
+
367
+ class PyDog(m.Dog):
368
+ pass
369
+
370
+ for cls in m.Dog, PyDog:
371
+ refcount_1 = getrefcount(cls)
372
+ molly = [cls("Molly") for _ in range(10)]
373
+ refcount_2 = getrefcount(cls)
374
+
375
+ del molly
376
+ pytest.gc_collect()
377
+ refcount_3 = getrefcount(cls)
378
+
379
+ assert refcount_1 == refcount_3
380
+ assert refcount_2 > refcount_1
381
+
382
+
383
+ def test_reentrant_implicit_conversion_failure(msg):
384
+ # ensure that there is no runaway reentrant implicit conversion (#1035)
385
+ with pytest.raises(TypeError) as excinfo:
386
+ m.BogusImplicitConversion(0)
387
+ assert (
388
+ msg(excinfo.value)
389
+ == """
390
+ __init__(): incompatible constructor arguments. The following argument types are supported:
391
+ 1. m.class_.BogusImplicitConversion(arg0: m.class_.BogusImplicitConversion)
392
+
393
+ Invoked with: 0
394
+ """
395
+ )
396
+
397
+
398
+ def test_error_after_conversions():
399
+ with pytest.raises(TypeError) as exc_info:
400
+ m.test_error_after_conversions("hello")
401
+ assert str(exc_info.value).startswith(
402
+ "Unable to convert function return value to a Python type!"
403
+ )
404
+
405
+
406
+ def test_aligned():
407
+ if hasattr(m, "Aligned"):
408
+ p = m.Aligned().ptr()
409
+ assert p % 1024 == 0
410
+
411
+
412
+ # https://foss.heptapod.net/pypy/pypy/-/issues/2742
413
+ @pytest.mark.xfail("env.PYPY")
414
+ def test_final():
415
+ with pytest.raises(TypeError) as exc_info:
416
+
417
+ class PyFinalChild(m.IsFinal):
418
+ pass
419
+
420
+ assert str(exc_info.value).endswith("is not an acceptable base type")
421
+
422
+
423
+ # https://foss.heptapod.net/pypy/pypy/-/issues/2742
424
+ @pytest.mark.xfail("env.PYPY")
425
+ def test_non_final_final():
426
+ with pytest.raises(TypeError) as exc_info:
427
+
428
+ class PyNonFinalFinalChild(m.IsNonFinalFinal):
429
+ pass
430
+
431
+ assert str(exc_info.value).endswith("is not an acceptable base type")
432
+
433
+
434
+ # https://github.com/pybind/pybind11/issues/1878
435
+ def test_exception_rvalue_abort():
436
+ with pytest.raises(RuntimeError):
437
+ m.PyPrintDestructor().throw_something()
438
+
439
+
440
+ # https://github.com/pybind/pybind11/issues/1568
441
+ def test_multiple_instances_with_same_pointer():
442
+ n = 100
443
+ instances = [m.SamePointer() for _ in range(n)]
444
+ for i in range(n):
445
+ # We need to reuse the same allocated memory for with a different type,
446
+ # to ensure the bug in `deregister_instance_impl` is detected. Otherwise
447
+ # `Py_TYPE(self) == Py_TYPE(it->second)` will still succeed, even though
448
+ # the `instance` is already deleted.
449
+ instances[i] = m.Empty()
450
+ # No assert: if this does not trigger the error
451
+ # pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
452
+ # and just completes without crashing, we're good.
453
+
454
+
455
+ # https://github.com/pybind/pybind11/issues/1624
456
+ def test_base_and_derived_nested_scope():
457
+ assert issubclass(m.DerivedWithNested, m.BaseWithNested)
458
+ assert m.BaseWithNested.Nested != m.DerivedWithNested.Nested
459
+ assert m.BaseWithNested.Nested.get_name() == "BaseWithNested::Nested"
460
+ assert m.DerivedWithNested.Nested.get_name() == "DerivedWithNested::Nested"
461
+
462
+
463
+ def test_register_duplicate_class():
464
+ import types
465
+
466
+ module_scope = types.ModuleType("module_scope")
467
+ with pytest.raises(RuntimeError) as exc_info:
468
+ m.register_duplicate_class_name(module_scope)
469
+ expected = (
470
+ 'generic_type: cannot initialize type "Duplicate": '
471
+ "an object with that name is already defined"
472
+ )
473
+ assert str(exc_info.value) == expected
474
+ with pytest.raises(RuntimeError) as exc_info:
475
+ m.register_duplicate_class_type(module_scope)
476
+ expected = 'generic_type: type "YetAnotherDuplicate" is already registered!'
477
+ assert str(exc_info.value) == expected
478
+
479
+ class ClassScope:
480
+ pass
481
+
482
+ with pytest.raises(RuntimeError) as exc_info:
483
+ m.register_duplicate_nested_class_name(ClassScope)
484
+ expected = (
485
+ 'generic_type: cannot initialize type "DuplicateNested": '
486
+ "an object with that name is already defined"
487
+ )
488
+ assert str(exc_info.value) == expected
489
+ with pytest.raises(RuntimeError) as exc_info:
490
+ m.register_duplicate_nested_class_type(ClassScope)
491
+ expected = 'generic_type: type "YetAnotherDuplicateNested" is already registered!'
492
+ assert str(exc_info.value) == expected
493
+
494
+
495
+ def test_pr4220_tripped_over_this():
496
+ assert (
497
+ m.Empty0().get_msg()
498
+ == "This is really only meant to exercise successful compilation."
499
+ )
third_party/CityFlow/extern/pybind11/tests/test_const_name.cpp CHANGED
@@ -1,55 +1,55 @@
1
- // Copyright (c) 2021 The Pybind Development Team.
2
- // All rights reserved. Use of this source code is governed by a
3
- // BSD-style license that can be found in the LICENSE file.
4
-
5
- #include "pybind11_tests.h"
6
-
7
- // IUT = Implementation Under Test
8
- #define CONST_NAME_TESTS(TEST_FUNC, IUT) \
9
- std::string TEST_FUNC(int selector) { \
10
- switch (selector) { \
11
- case 0: \
12
- return IUT("").text; \
13
- case 1: \
14
- return IUT("A").text; \
15
- case 2: \
16
- return IUT("Bd").text; \
17
- case 3: \
18
- return IUT("Cef").text; \
19
- case 4: \
20
- return IUT<int>().text; /*NOLINT(bugprone-macro-parentheses)*/ \
21
- case 5: \
22
- return IUT<std::string>().text; /*NOLINT(bugprone-macro-parentheses)*/ \
23
- case 6: \
24
- return IUT<true>("T1", "T2").text; /*NOLINT(bugprone-macro-parentheses)*/ \
25
- case 7: \
26
- return IUT<false>("U1", "U2").text; /*NOLINT(bugprone-macro-parentheses)*/ \
27
- case 8: \
28
- /*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
29
- return IUT<true>(IUT("D1"), IUT("D2")).text; \
30
- case 9: \
31
- /*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
32
- return IUT<false>(IUT("E1"), IUT("E2")).text; \
33
- case 10: \
34
- return IUT("KeepAtEnd").text; \
35
- default: \
36
- break; \
37
- } \
38
- throw std::runtime_error("Invalid selector value."); \
39
- }
40
-
41
- CONST_NAME_TESTS(const_name_tests, py::detail::const_name)
42
-
43
- #ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
44
- CONST_NAME_TESTS(underscore_tests, py::detail::_)
45
- #endif
46
-
47
- TEST_SUBMODULE(const_name, m) {
48
- m.def("const_name_tests", const_name_tests);
49
-
50
- #if defined(PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY)
51
- m.def("underscore_tests", underscore_tests);
52
- #else
53
- m.attr("underscore_tests") = "PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY not defined.";
54
- #endif
55
- }
 
1
+ // Copyright (c) 2021 The Pybind Development Team.
2
+ // All rights reserved. Use of this source code is governed by a
3
+ // BSD-style license that can be found in the LICENSE file.
4
+
5
+ #include "pybind11_tests.h"
6
+
7
+ // IUT = Implementation Under Test
8
+ #define CONST_NAME_TESTS(TEST_FUNC, IUT) \
9
+ std::string TEST_FUNC(int selector) { \
10
+ switch (selector) { \
11
+ case 0: \
12
+ return IUT("").text; \
13
+ case 1: \
14
+ return IUT("A").text; \
15
+ case 2: \
16
+ return IUT("Bd").text; \
17
+ case 3: \
18
+ return IUT("Cef").text; \
19
+ case 4: \
20
+ return IUT<int>().text; /*NOLINT(bugprone-macro-parentheses)*/ \
21
+ case 5: \
22
+ return IUT<std::string>().text; /*NOLINT(bugprone-macro-parentheses)*/ \
23
+ case 6: \
24
+ return IUT<true>("T1", "T2").text; /*NOLINT(bugprone-macro-parentheses)*/ \
25
+ case 7: \
26
+ return IUT<false>("U1", "U2").text; /*NOLINT(bugprone-macro-parentheses)*/ \
27
+ case 8: \
28
+ /*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
29
+ return IUT<true>(IUT("D1"), IUT("D2")).text; \
30
+ case 9: \
31
+ /*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
32
+ return IUT<false>(IUT("E1"), IUT("E2")).text; \
33
+ case 10: \
34
+ return IUT("KeepAtEnd").text; \
35
+ default: \
36
+ break; \
37
+ } \
38
+ throw std::runtime_error("Invalid selector value."); \
39
+ }
40
+
41
+ CONST_NAME_TESTS(const_name_tests, py::detail::const_name)
42
+
43
+ #ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
44
+ CONST_NAME_TESTS(underscore_tests, py::detail::_)
45
+ #endif
46
+
47
+ TEST_SUBMODULE(const_name, m) {
48
+ m.def("const_name_tests", const_name_tests);
49
+
50
+ #if defined(PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY)
51
+ m.def("underscore_tests", underscore_tests);
52
+ #else
53
+ m.attr("underscore_tests") = "PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY not defined.";
54
+ #endif
55
+ }
third_party/CityFlow/extern/pybind11/tests/test_const_name.py CHANGED
@@ -1,29 +1,29 @@
1
- import pytest
2
-
3
- from pybind11_tests import const_name as m
4
-
5
-
6
- @pytest.mark.parametrize("func", [m.const_name_tests, m.underscore_tests])
7
- @pytest.mark.parametrize(
8
- ("selector", "expected"),
9
- enumerate(
10
- (
11
- "",
12
- "A",
13
- "Bd",
14
- "Cef",
15
- "%",
16
- "%",
17
- "T1",
18
- "U2",
19
- "D1",
20
- "E2",
21
- "KeepAtEnd",
22
- )
23
- ),
24
- )
25
- def test_const_name(func, selector, expected):
26
- if isinstance(func, str):
27
- pytest.skip(func)
28
- text = func(selector)
29
- assert text == expected
 
1
+ import pytest
2
+
3
+ from pybind11_tests import const_name as m
4
+
5
+
6
+ @pytest.mark.parametrize("func", [m.const_name_tests, m.underscore_tests])
7
+ @pytest.mark.parametrize(
8
+ ("selector", "expected"),
9
+ enumerate(
10
+ (
11
+ "",
12
+ "A",
13
+ "Bd",
14
+ "Cef",
15
+ "%",
16
+ "%",
17
+ "T1",
18
+ "U2",
19
+ "D1",
20
+ "E2",
21
+ "KeepAtEnd",
22
+ )
23
+ ),
24
+ )
25
+ def test_const_name(func, selector, expected):
26
+ if isinstance(func, str):
27
+ pytest.skip(func)
28
+ text = func(selector)
29
+ assert text == expected
third_party/CityFlow/extern/pybind11/tests/test_constants_and_functions.cpp CHANGED
@@ -1,158 +1,158 @@
1
- /*
2
- tests/test_constants_and_functions.cpp -- global constants and functions, enumerations, raw
3
- byte strings
4
-
5
- Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
6
-
7
- All rights reserved. Use of this source code is governed by a
8
- BSD-style license that can be found in the LICENSE file.
9
- */
10
-
11
- #include "pybind11_tests.h"
12
-
13
- enum MyEnum { EFirstEntry = 1, ESecondEntry };
14
-
15
- std::string test_function1() { return "test_function()"; }
16
-
17
- std::string test_function2(MyEnum k) { return "test_function(enum=" + std::to_string(k) + ")"; }
18
-
19
- std::string test_function3(int i) { return "test_function(" + std::to_string(i) + ")"; }
20
-
21
- py::str test_function4() { return "test_function()"; }
22
- py::str test_function4(char *) { return "test_function(char *)"; }
23
- py::str test_function4(int, float) { return "test_function(int, float)"; }
24
- py::str test_function4(float, int) { return "test_function(float, int)"; }
25
-
26
- py::bytes return_bytes() {
27
- const char *data = "\x01\x00\x02\x00";
28
- return std::string(data, 4);
29
- }
30
-
31
- std::string print_bytes(const py::bytes &bytes) {
32
- std::string ret = "bytes[";
33
- const auto value = static_cast<std::string>(bytes);
34
- for (char c : value) {
35
- ret += std::to_string(static_cast<int>(c)) + ' ';
36
- }
37
- ret.back() = ']';
38
- return ret;
39
- }
40
-
41
- // Test that we properly handle C++17 exception specifiers (which are part of the function
42
- // signature in C++17). These should all still work before C++17, but don't affect the function
43
- // signature.
44
- namespace test_exc_sp {
45
- // [workaround(intel)] Unable to use noexcept instead of noexcept(true)
46
- // Make the f1 test basically the same as the f2 test in C++17 mode for the Intel compiler as
47
- // it fails to compile with a plain noexcept (tested with icc (ICC) 2021.1 Beta 20200827).
48
- #if defined(__INTEL_COMPILER) && defined(PYBIND11_CPP17)
49
- int f1(int x) noexcept(true) { return x + 1; }
50
- #else
51
- int f1(int x) noexcept { return x + 1; }
52
- #endif
53
- int f2(int x) noexcept(true) { return x + 2; }
54
- int f3(int x) noexcept(false) { return x + 3; }
55
- PYBIND11_WARNING_PUSH
56
- PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated")
57
- #if defined(__clang_major__) && __clang_major__ >= 5
58
- PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-dynamic-exception-spec")
59
- #else
60
- PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated")
61
- #endif
62
- // NOLINTNEXTLINE(modernize-use-noexcept)
63
- int f4(int x) throw() { return x + 4; } // Deprecated equivalent to noexcept(true)
64
- PYBIND11_WARNING_POP
65
- struct C {
66
- int m1(int x) noexcept { return x - 1; }
67
- int m2(int x) const noexcept { return x - 2; }
68
- int m3(int x) noexcept(true) { return x - 3; }
69
- int m4(int x) const noexcept(true) { return x - 4; }
70
- int m5(int x) noexcept(false) { return x - 5; }
71
- int m6(int x) const noexcept(false) { return x - 6; }
72
- PYBIND11_WARNING_PUSH
73
- PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated")
74
- PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated")
75
- // NOLINTNEXTLINE(modernize-use-noexcept)
76
- int m7(int x) throw() { return x - 7; }
77
- // NOLINTNEXTLINE(modernize-use-noexcept)
78
- int m8(int x) const throw() { return x - 8; }
79
- PYBIND11_WARNING_POP
80
- };
81
- } // namespace test_exc_sp
82
-
83
- TEST_SUBMODULE(constants_and_functions, m) {
84
- // test_constants
85
- m.attr("some_constant") = py::int_(14);
86
-
87
- // test_function_overloading
88
- m.def("test_function", &test_function1);
89
- m.def("test_function", &test_function2);
90
- m.def("test_function", &test_function3);
91
-
92
- #if defined(PYBIND11_OVERLOAD_CAST)
93
- m.def("test_function", py::overload_cast<>(&test_function4));
94
- m.def("test_function", py::overload_cast<char *>(&test_function4));
95
- m.def("test_function", py::overload_cast<int, float>(&test_function4));
96
- m.def("test_function", py::overload_cast<float, int>(&test_function4));
97
- #else
98
- m.def("test_function", static_cast<py::str (*)()>(&test_function4));
99
- m.def("test_function", static_cast<py::str (*)(char *)>(&test_function4));
100
- m.def("test_function", static_cast<py::str (*)(int, float)>(&test_function4));
101
- m.def("test_function", static_cast<py::str (*)(float, int)>(&test_function4));
102
- #endif
103
-
104
- py::enum_<MyEnum>(m, "MyEnum")
105
- .value("EFirstEntry", EFirstEntry)
106
- .value("ESecondEntry", ESecondEntry)
107
- .export_values();
108
-
109
- // test_bytes
110
- m.def("return_bytes", &return_bytes);
111
- m.def("print_bytes", &print_bytes);
112
-
113
- // test_exception_specifiers
114
- using namespace test_exc_sp;
115
- py::class_<C>(m, "C")
116
- .def(py::init<>())
117
- .def("m1", &C::m1)
118
- .def("m2", &C::m2)
119
- .def("m3", &C::m3)
120
- .def("m4", &C::m4)
121
- .def("m5", &C::m5)
122
- .def("m6", &C::m6)
123
- .def("m7", &C::m7)
124
- .def("m8", &C::m8);
125
- m.def("f1", f1);
126
- m.def("f2", f2);
127
-
128
- PYBIND11_WARNING_PUSH
129
- PYBIND11_WARNING_DISABLE_INTEL(878) // incompatible exception specifications
130
- m.def("f3", f3);
131
- PYBIND11_WARNING_POP
132
-
133
- m.def("f4", f4);
134
-
135
- // test_function_record_leaks
136
- m.def("register_large_capture_with_invalid_arguments", [](py::module_ m) {
137
- // This should always be enough to trigger the alternative branch
138
- // where `sizeof(capture) > sizeof(rec->data)`
139
- uint64_t capture[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
140
- #if defined(__GNUC__) && __GNUC__ == 4 // CentOS7
141
- py::detail::silence_unused_warnings(capture);
142
- #endif
143
- m.def(
144
- "should_raise", [capture](int) { return capture[9] + 33; }, py::kw_only(), py::arg());
145
- });
146
- m.def("register_with_raising_repr", [](py::module_ m, const py::object &default_value) {
147
- m.def(
148
- "should_raise",
149
- [](int, int, const py::object &) { return 42; },
150
- "some docstring",
151
- py::arg_v("x", 42),
152
- py::arg_v("y", 42, "<the answer>"),
153
- py::arg_v("z", default_value));
154
- });
155
-
156
- // test noexcept(true) lambda (#4565)
157
- m.def("l1", []() noexcept(true) { return 0; });
158
- }
 
1
+ /*
2
+ tests/test_constants_and_functions.cpp -- global constants and functions, enumerations, raw
3
+ byte strings
4
+
5
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
6
+
7
+ All rights reserved. Use of this source code is governed by a
8
+ BSD-style license that can be found in the LICENSE file.
9
+ */
10
+
11
+ #include "pybind11_tests.h"
12
+
13
+ enum MyEnum { EFirstEntry = 1, ESecondEntry };
14
+
15
+ std::string test_function1() { return "test_function()"; }
16
+
17
+ std::string test_function2(MyEnum k) { return "test_function(enum=" + std::to_string(k) + ")"; }
18
+
19
+ std::string test_function3(int i) { return "test_function(" + std::to_string(i) + ")"; }
20
+
21
+ py::str test_function4() { return "test_function()"; }
22
+ py::str test_function4(char *) { return "test_function(char *)"; }
23
+ py::str test_function4(int, float) { return "test_function(int, float)"; }
24
+ py::str test_function4(float, int) { return "test_function(float, int)"; }
25
+
26
+ py::bytes return_bytes() {
27
+ const char *data = "\x01\x00\x02\x00";
28
+ return std::string(data, 4);
29
+ }
30
+
31
+ std::string print_bytes(const py::bytes &bytes) {
32
+ std::string ret = "bytes[";
33
+ const auto value = static_cast<std::string>(bytes);
34
+ for (char c : value) {
35
+ ret += std::to_string(static_cast<int>(c)) + ' ';
36
+ }
37
+ ret.back() = ']';
38
+ return ret;
39
+ }
40
+
41
+ // Test that we properly handle C++17 exception specifiers (which are part of the function
42
+ // signature in C++17). These should all still work before C++17, but don't affect the function
43
+ // signature.
44
+ namespace test_exc_sp {
45
+ // [workaround(intel)] Unable to use noexcept instead of noexcept(true)
46
+ // Make the f1 test basically the same as the f2 test in C++17 mode for the Intel compiler as
47
+ // it fails to compile with a plain noexcept (tested with icc (ICC) 2021.1 Beta 20200827).
48
+ #if defined(__INTEL_COMPILER) && defined(PYBIND11_CPP17)
49
+ int f1(int x) noexcept(true) { return x + 1; }
50
+ #else
51
+ int f1(int x) noexcept { return x + 1; }
52
+ #endif
53
+ int f2(int x) noexcept(true) { return x + 2; }
54
+ int f3(int x) noexcept(false) { return x + 3; }
55
+ PYBIND11_WARNING_PUSH
56
+ PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated")
57
+ #if defined(__clang_major__) && __clang_major__ >= 5
58
+ PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-dynamic-exception-spec")
59
+ #else
60
+ PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated")
61
+ #endif
62
+ // NOLINTNEXTLINE(modernize-use-noexcept)
63
+ int f4(int x) throw() { return x + 4; } // Deprecated equivalent to noexcept(true)
64
+ PYBIND11_WARNING_POP
65
+ struct C {
66
+ int m1(int x) noexcept { return x - 1; }
67
+ int m2(int x) const noexcept { return x - 2; }
68
+ int m3(int x) noexcept(true) { return x - 3; }
69
+ int m4(int x) const noexcept(true) { return x - 4; }
70
+ int m5(int x) noexcept(false) { return x - 5; }
71
+ int m6(int x) const noexcept(false) { return x - 6; }
72
+ PYBIND11_WARNING_PUSH
73
+ PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated")
74
+ PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated")
75
+ // NOLINTNEXTLINE(modernize-use-noexcept)
76
+ int m7(int x) throw() { return x - 7; }
77
+ // NOLINTNEXTLINE(modernize-use-noexcept)
78
+ int m8(int x) const throw() { return x - 8; }
79
+ PYBIND11_WARNING_POP
80
+ };
81
+ } // namespace test_exc_sp
82
+
83
+ TEST_SUBMODULE(constants_and_functions, m) {
84
+ // test_constants
85
+ m.attr("some_constant") = py::int_(14);
86
+
87
+ // test_function_overloading
88
+ m.def("test_function", &test_function1);
89
+ m.def("test_function", &test_function2);
90
+ m.def("test_function", &test_function3);
91
+
92
+ #if defined(PYBIND11_OVERLOAD_CAST)
93
+ m.def("test_function", py::overload_cast<>(&test_function4));
94
+ m.def("test_function", py::overload_cast<char *>(&test_function4));
95
+ m.def("test_function", py::overload_cast<int, float>(&test_function4));
96
+ m.def("test_function", py::overload_cast<float, int>(&test_function4));
97
+ #else
98
+ m.def("test_function", static_cast<py::str (*)()>(&test_function4));
99
+ m.def("test_function", static_cast<py::str (*)(char *)>(&test_function4));
100
+ m.def("test_function", static_cast<py::str (*)(int, float)>(&test_function4));
101
+ m.def("test_function", static_cast<py::str (*)(float, int)>(&test_function4));
102
+ #endif
103
+
104
+ py::enum_<MyEnum>(m, "MyEnum")
105
+ .value("EFirstEntry", EFirstEntry)
106
+ .value("ESecondEntry", ESecondEntry)
107
+ .export_values();
108
+
109
+ // test_bytes
110
+ m.def("return_bytes", &return_bytes);
111
+ m.def("print_bytes", &print_bytes);
112
+
113
+ // test_exception_specifiers
114
+ using namespace test_exc_sp;
115
+ py::class_<C>(m, "C")
116
+ .def(py::init<>())
117
+ .def("m1", &C::m1)
118
+ .def("m2", &C::m2)
119
+ .def("m3", &C::m3)
120
+ .def("m4", &C::m4)
121
+ .def("m5", &C::m5)
122
+ .def("m6", &C::m6)
123
+ .def("m7", &C::m7)
124
+ .def("m8", &C::m8);
125
+ m.def("f1", f1);
126
+ m.def("f2", f2);
127
+
128
+ PYBIND11_WARNING_PUSH
129
+ PYBIND11_WARNING_DISABLE_INTEL(878) // incompatible exception specifications
130
+ m.def("f3", f3);
131
+ PYBIND11_WARNING_POP
132
+
133
+ m.def("f4", f4);
134
+
135
+ // test_function_record_leaks
136
+ m.def("register_large_capture_with_invalid_arguments", [](py::module_ m) {
137
+ // This should always be enough to trigger the alternative branch
138
+ // where `sizeof(capture) > sizeof(rec->data)`
139
+ uint64_t capture[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
140
+ #if defined(__GNUC__) && __GNUC__ == 4 // CentOS7
141
+ py::detail::silence_unused_warnings(capture);
142
+ #endif
143
+ m.def(
144
+ "should_raise", [capture](int) { return capture[9] + 33; }, py::kw_only(), py::arg());
145
+ });
146
+ m.def("register_with_raising_repr", [](py::module_ m, const py::object &default_value) {
147
+ m.def(
148
+ "should_raise",
149
+ [](int, int, const py::object &) { return 42; },
150
+ "some docstring",
151
+ py::arg_v("x", 42),
152
+ py::arg_v("y", 42, "<the answer>"),
153
+ py::arg_v("z", default_value));
154
+ });
155
+
156
+ // test noexcept(true) lambda (#4565)
157
+ m.def("l1", []() noexcept(true) { return 0; });
158
+ }
third_party/CityFlow/extern/pybind11/tests/test_constants_and_functions.py CHANGED
@@ -1,56 +1,56 @@
1
- import pytest
2
-
3
- m = pytest.importorskip("pybind11_tests.constants_and_functions")
4
-
5
-
6
- def test_constants():
7
- assert m.some_constant == 14
8
-
9
-
10
- def test_function_overloading():
11
- assert m.test_function() == "test_function()"
12
- assert m.test_function(7) == "test_function(7)"
13
- assert m.test_function(m.MyEnum.EFirstEntry) == "test_function(enum=1)"
14
- assert m.test_function(m.MyEnum.ESecondEntry) == "test_function(enum=2)"
15
-
16
- assert m.test_function() == "test_function()"
17
- assert m.test_function("abcd") == "test_function(char *)"
18
- assert m.test_function(1, 1.0) == "test_function(int, float)"
19
- assert m.test_function(1, 1.0) == "test_function(int, float)"
20
- assert m.test_function(2.0, 2) == "test_function(float, int)"
21
-
22
-
23
- def test_bytes():
24
- assert m.print_bytes(m.return_bytes()) == "bytes[1 0 2 0]"
25
-
26
-
27
- def test_exception_specifiers():
28
- c = m.C()
29
- assert c.m1(2) == 1
30
- assert c.m2(3) == 1
31
- assert c.m3(5) == 2
32
- assert c.m4(7) == 3
33
- assert c.m5(10) == 5
34
- assert c.m6(14) == 8
35
- assert c.m7(20) == 13
36
- assert c.m8(29) == 21
37
-
38
- assert m.f1(33) == 34
39
- assert m.f2(53) == 55
40
- assert m.f3(86) == 89
41
- assert m.f4(140) == 144
42
-
43
-
44
- def test_function_record_leaks():
45
- class RaisingRepr:
46
- def __repr__(self):
47
- raise RuntimeError("Surprise!")
48
-
49
- with pytest.raises(RuntimeError):
50
- m.register_large_capture_with_invalid_arguments(m)
51
- with pytest.raises(RuntimeError):
52
- m.register_with_raising_repr(m, RaisingRepr())
53
-
54
-
55
- def test_noexcept_lambda():
56
- assert m.l1() == 0
 
1
+ import pytest
2
+
3
+ m = pytest.importorskip("pybind11_tests.constants_and_functions")
4
+
5
+
6
+ def test_constants():
7
+ assert m.some_constant == 14
8
+
9
+
10
+ def test_function_overloading():
11
+ assert m.test_function() == "test_function()"
12
+ assert m.test_function(7) == "test_function(7)"
13
+ assert m.test_function(m.MyEnum.EFirstEntry) == "test_function(enum=1)"
14
+ assert m.test_function(m.MyEnum.ESecondEntry) == "test_function(enum=2)"
15
+
16
+ assert m.test_function() == "test_function()"
17
+ assert m.test_function("abcd") == "test_function(char *)"
18
+ assert m.test_function(1, 1.0) == "test_function(int, float)"
19
+ assert m.test_function(1, 1.0) == "test_function(int, float)"
20
+ assert m.test_function(2.0, 2) == "test_function(float, int)"
21
+
22
+
23
+ def test_bytes():
24
+ assert m.print_bytes(m.return_bytes()) == "bytes[1 0 2 0]"
25
+
26
+
27
+ def test_exception_specifiers():
28
+ c = m.C()
29
+ assert c.m1(2) == 1
30
+ assert c.m2(3) == 1
31
+ assert c.m3(5) == 2
32
+ assert c.m4(7) == 3
33
+ assert c.m5(10) == 5
34
+ assert c.m6(14) == 8
35
+ assert c.m7(20) == 13
36
+ assert c.m8(29) == 21
37
+
38
+ assert m.f1(33) == 34
39
+ assert m.f2(53) == 55
40
+ assert m.f3(86) == 89
41
+ assert m.f4(140) == 144
42
+
43
+
44
+ def test_function_record_leaks():
45
+ class RaisingRepr:
46
+ def __repr__(self):
47
+ raise RuntimeError("Surprise!")
48
+
49
+ with pytest.raises(RuntimeError):
50
+ m.register_large_capture_with_invalid_arguments(m)
51
+ with pytest.raises(RuntimeError):
52
+ m.register_with_raising_repr(m, RaisingRepr())
53
+
54
+
55
+ def test_noexcept_lambda():
56
+ assert m.l1() == 0
third_party/CityFlow/extern/pybind11/tests/test_copy_move.cpp CHANGED
@@ -1,533 +1,533 @@
1
- /*
2
- tests/test_copy_move_policies.cpp -- 'copy' and 'move' return value policies
3
- and related tests
4
-
5
- Copyright (c) 2016 Ben North <ben@redfrontdoor.org>
6
-
7
- All rights reserved. Use of this source code is governed by a
8
- BSD-style license that can be found in the LICENSE file.
9
- */
10
-
11
- #include <pybind11/stl.h>
12
-
13
- #include "constructor_stats.h"
14
- #include "pybind11_tests.h"
15
-
16
- #include <type_traits>
17
-
18
- template <typename derived>
19
- struct empty {
20
- static const derived &get_one() { return instance_; }
21
- static derived instance_;
22
- };
23
-
24
- struct lacking_copy_ctor : public empty<lacking_copy_ctor> {
25
- lacking_copy_ctor() = default;
26
- lacking_copy_ctor(const lacking_copy_ctor &other) = delete;
27
- };
28
-
29
- template <>
30
- lacking_copy_ctor empty<lacking_copy_ctor>::instance_ = {};
31
-
32
- struct lacking_move_ctor : public empty<lacking_move_ctor> {
33
- lacking_move_ctor() = default;
34
- lacking_move_ctor(const lacking_move_ctor &other) = delete;
35
- lacking_move_ctor(lacking_move_ctor &&other) = delete;
36
- };
37
-
38
- template <>
39
- lacking_move_ctor empty<lacking_move_ctor>::instance_ = {};
40
-
41
- /* Custom type caster move/copy test classes */
42
- class MoveOnlyInt {
43
- public:
44
- MoveOnlyInt() { print_default_created(this); }
45
- explicit MoveOnlyInt(int v) : value{v} { print_created(this, value); }
46
- MoveOnlyInt(MoveOnlyInt &&m) noexcept {
47
- print_move_created(this, m.value);
48
- std::swap(value, m.value);
49
- }
50
- MoveOnlyInt &operator=(MoveOnlyInt &&m) noexcept {
51
- print_move_assigned(this, m.value);
52
- std::swap(value, m.value);
53
- return *this;
54
- }
55
- MoveOnlyInt(const MoveOnlyInt &) = delete;
56
- MoveOnlyInt &operator=(const MoveOnlyInt &) = delete;
57
- ~MoveOnlyInt() { print_destroyed(this); }
58
-
59
- int value;
60
- };
61
- class MoveOrCopyInt {
62
- public:
63
- MoveOrCopyInt() { print_default_created(this); }
64
- explicit MoveOrCopyInt(int v) : value{v} { print_created(this, value); }
65
- MoveOrCopyInt(MoveOrCopyInt &&m) noexcept {
66
- print_move_created(this, m.value);
67
- std::swap(value, m.value);
68
- }
69
- MoveOrCopyInt &operator=(MoveOrCopyInt &&m) noexcept {
70
- print_move_assigned(this, m.value);
71
- std::swap(value, m.value);
72
- return *this;
73
- }
74
- MoveOrCopyInt(const MoveOrCopyInt &c) {
75
- print_copy_created(this, c.value);
76
- // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
77
- value = c.value;
78
- }
79
- MoveOrCopyInt &operator=(const MoveOrCopyInt &c) {
80
- print_copy_assigned(this, c.value);
81
- value = c.value;
82
- return *this;
83
- }
84
- ~MoveOrCopyInt() { print_destroyed(this); }
85
-
86
- int value;
87
- };
88
- class CopyOnlyInt {
89
- public:
90
- CopyOnlyInt() { print_default_created(this); }
91
- explicit CopyOnlyInt(int v) : value{v} { print_created(this, value); }
92
- CopyOnlyInt(const CopyOnlyInt &c) {
93
- print_copy_created(this, c.value);
94
- // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
95
- value = c.value;
96
- }
97
- CopyOnlyInt &operator=(const CopyOnlyInt &c) {
98
- print_copy_assigned(this, c.value);
99
- value = c.value;
100
- return *this;
101
- }
102
- ~CopyOnlyInt() { print_destroyed(this); }
103
-
104
- int value;
105
- };
106
- PYBIND11_NAMESPACE_BEGIN(pybind11)
107
- PYBIND11_NAMESPACE_BEGIN(detail)
108
- template <>
109
- struct type_caster<MoveOnlyInt> {
110
- PYBIND11_TYPE_CASTER(MoveOnlyInt, const_name("MoveOnlyInt"));
111
- bool load(handle src, bool) {
112
- value = MoveOnlyInt(src.cast<int>());
113
- return true;
114
- }
115
- static handle cast(const MoveOnlyInt &m, return_value_policy r, handle p) {
116
- return pybind11::cast(m.value, r, p);
117
- }
118
- };
119
-
120
- template <>
121
- struct type_caster<MoveOrCopyInt> {
122
- PYBIND11_TYPE_CASTER(MoveOrCopyInt, const_name("MoveOrCopyInt"));
123
- bool load(handle src, bool) {
124
- value = MoveOrCopyInt(src.cast<int>());
125
- return true;
126
- }
127
- static handle cast(const MoveOrCopyInt &m, return_value_policy r, handle p) {
128
- return pybind11::cast(m.value, r, p);
129
- }
130
- };
131
-
132
- template <>
133
- struct type_caster<CopyOnlyInt> {
134
- protected:
135
- CopyOnlyInt value;
136
-
137
- public:
138
- static constexpr auto name = const_name("CopyOnlyInt");
139
- bool load(handle src, bool) {
140
- value = CopyOnlyInt(src.cast<int>());
141
- return true;
142
- }
143
- static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) {
144
- return pybind11::cast(m.value, r, p);
145
- }
146
- static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) {
147
- if (!src) {
148
- return none().release();
149
- }
150
- return cast(*src, policy, parent);
151
- }
152
- explicit operator CopyOnlyInt *() { return &value; }
153
- explicit operator CopyOnlyInt &() { return value; }
154
- template <typename T>
155
- using cast_op_type = pybind11::detail::cast_op_type<T>;
156
- };
157
- PYBIND11_NAMESPACE_END(detail)
158
- PYBIND11_NAMESPACE_END(pybind11)
159
-
160
- TEST_SUBMODULE(copy_move_policies, m) {
161
- // test_lacking_copy_ctor
162
- py::class_<lacking_copy_ctor>(m, "lacking_copy_ctor")
163
- .def_static("get_one", &lacking_copy_ctor::get_one, py::return_value_policy::copy);
164
- // test_lacking_move_ctor
165
- py::class_<lacking_move_ctor>(m, "lacking_move_ctor")
166
- .def_static("get_one", &lacking_move_ctor::get_one, py::return_value_policy::move);
167
-
168
- // test_move_and_copy_casts
169
- // NOLINTNEXTLINE(performance-unnecessary-value-param)
170
- m.def("move_and_copy_casts", [](const py::object &o) {
171
- int r = 0;
172
- r += py::cast<MoveOrCopyInt>(o).value; /* moves */
173
- r += py::cast<MoveOnlyInt>(o).value; /* moves */
174
- r += py::cast<CopyOnlyInt>(o).value; /* copies */
175
- auto m1(py::cast<MoveOrCopyInt>(o)); /* moves */
176
- auto m2(py::cast<MoveOnlyInt>(o)); /* moves */
177
- auto m3(py::cast<CopyOnlyInt>(o)); /* copies */
178
- r += m1.value + m2.value + m3.value;
179
-
180
- return r;
181
- });
182
-
183
- // test_move_and_copy_loads
184
- m.def("move_only", [](MoveOnlyInt m) { return m.value; });
185
- // Changing this breaks the existing test: needs careful review.
186
- // NOLINTNEXTLINE(performance-unnecessary-value-param)
187
- m.def("move_or_copy", [](MoveOrCopyInt m) { return m.value; });
188
- // Changing this breaks the existing test: needs careful review.
189
- // NOLINTNEXTLINE(performance-unnecessary-value-param)
190
- m.def("copy_only", [](CopyOnlyInt m) { return m.value; });
191
- m.def("move_pair",
192
- [](std::pair<MoveOnlyInt, MoveOrCopyInt> p) { return p.first.value + p.second.value; });
193
- m.def("move_tuple", [](std::tuple<MoveOnlyInt, MoveOrCopyInt, MoveOnlyInt> t) {
194
- return std::get<0>(t).value + std::get<1>(t).value + std::get<2>(t).value;
195
- });
196
- m.def("copy_tuple", [](std::tuple<CopyOnlyInt, CopyOnlyInt> t) {
197
- return std::get<0>(t).value + std::get<1>(t).value;
198
- });
199
- m.def("move_copy_nested",
200
- [](std::pair<MoveOnlyInt,
201
- std::pair<std::tuple<MoveOrCopyInt, CopyOnlyInt, std::tuple<MoveOnlyInt>>,
202
- MoveOrCopyInt>> x) {
203
- return x.first.value + std::get<0>(x.second.first).value
204
- + std::get<1>(x.second.first).value
205
- + std::get<0>(std::get<2>(x.second.first)).value + x.second.second.value;
206
- });
207
- m.def("move_and_copy_cstats", []() {
208
- ConstructorStats::gc();
209
- // Reset counts to 0 so that previous tests don't affect later ones:
210
- auto &mc = ConstructorStats::get<MoveOrCopyInt>();
211
- mc.move_assignments = mc.move_constructions = mc.copy_assignments = mc.copy_constructions
212
- = 0;
213
- auto &mo = ConstructorStats::get<MoveOnlyInt>();
214
- mo.move_assignments = mo.move_constructions = mo.copy_assignments = mo.copy_constructions
215
- = 0;
216
- auto &co = ConstructorStats::get<CopyOnlyInt>();
217
- co.move_assignments = co.move_constructions = co.copy_assignments = co.copy_constructions
218
- = 0;
219
- py::dict d;
220
- d["MoveOrCopyInt"] = py::cast(mc, py::return_value_policy::reference);
221
- d["MoveOnlyInt"] = py::cast(mo, py::return_value_policy::reference);
222
- d["CopyOnlyInt"] = py::cast(co, py::return_value_policy::reference);
223
- return d;
224
- });
225
- #ifdef PYBIND11_HAS_OPTIONAL
226
- // test_move_and_copy_load_optional
227
- m.attr("has_optional") = true;
228
- m.def("move_optional", [](std::optional<MoveOnlyInt> o) { return o->value; });
229
- m.def("move_or_copy_optional", [](std::optional<MoveOrCopyInt> o) { return o->value; });
230
- m.def("copy_optional", [](std::optional<CopyOnlyInt> o) { return o->value; });
231
- m.def("move_optional_tuple",
232
- [](std::optional<std::tuple<MoveOrCopyInt, MoveOnlyInt, CopyOnlyInt>> x) {
233
- return std::get<0>(*x).value + std::get<1>(*x).value + std::get<2>(*x).value;
234
- });
235
- #else
236
- m.attr("has_optional") = false;
237
- #endif
238
-
239
- // #70 compilation issue if operator new is not public - simple body added
240
- // but not needed on most compilers; MSVC and nvcc don't like a local
241
- // struct not having a method defined when declared, since it can not be
242
- // added later.
243
- struct PrivateOpNew {
244
- int value = 1;
245
-
246
- private:
247
- void *operator new(size_t bytes) {
248
- void *ptr = std::malloc(bytes);
249
- if (ptr) {
250
- return ptr;
251
- }
252
- throw std::bad_alloc{};
253
- }
254
- };
255
- py::class_<PrivateOpNew>(m, "PrivateOpNew").def_readonly("value", &PrivateOpNew::value);
256
- m.def("private_op_new_value", []() { return PrivateOpNew(); });
257
- m.def(
258
- "private_op_new_reference",
259
- []() -> const PrivateOpNew & {
260
- static PrivateOpNew x{};
261
- return x;
262
- },
263
- py::return_value_policy::reference);
264
-
265
- // test_move_fallback
266
- // #389: rvp::move should fall-through to copy on non-movable objects
267
- struct MoveIssue1 {
268
- int v;
269
- explicit MoveIssue1(int v) : v{v} {}
270
- MoveIssue1(const MoveIssue1 &c) = default;
271
- MoveIssue1(MoveIssue1 &&) = delete;
272
- };
273
- py::class_<MoveIssue1>(m, "MoveIssue1")
274
- .def(py::init<int>())
275
- .def_readwrite("value", &MoveIssue1::v);
276
-
277
- struct MoveIssue2 {
278
- int v;
279
- explicit MoveIssue2(int v) : v{v} {}
280
- MoveIssue2(MoveIssue2 &&) = default;
281
- };
282
- py::class_<MoveIssue2>(m, "MoveIssue2")
283
- .def(py::init<int>())
284
- .def_readwrite("value", &MoveIssue2::v);
285
-
286
- // #2742: Don't expect ownership of raw pointer to `new`ed object to be transferred with
287
- // `py::return_value_policy::move`
288
- m.def(
289
- "get_moveissue1",
290
- [](int i) { return std::unique_ptr<MoveIssue1>(new MoveIssue1(i)); },
291
- py::return_value_policy::move);
292
- m.def(
293
- "get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move);
294
-
295
- // Make sure that cast from pytype rvalue to other pytype works
296
- m.def("get_pytype_rvalue_castissue", [](double i) { return py::float_(i).cast<py::int_>(); });
297
- }
298
-
299
- /*
300
- * Rest of the file:
301
- * static_assert based tests for pybind11 adaptations of
302
- * std::is_move_constructible, std::is_copy_constructible and
303
- * std::is_copy_assignable (no adaptation of std::is_move_assignable).
304
- * Difference between pybind11 and std traits: pybind11 traits will also check
305
- * the contained value_types.
306
- */
307
-
308
- struct NotMovable {
309
- NotMovable() = default;
310
- NotMovable(NotMovable const &) = default;
311
- NotMovable(NotMovable &&) = delete;
312
- NotMovable &operator=(NotMovable const &) = default;
313
- NotMovable &operator=(NotMovable &&) = delete;
314
- };
315
- static_assert(!std::is_move_constructible<NotMovable>::value,
316
- "!std::is_move_constructible<NotMovable>::value");
317
- static_assert(std::is_copy_constructible<NotMovable>::value,
318
- "std::is_copy_constructible<NotMovable>::value");
319
- static_assert(!pybind11::detail::is_move_constructible<NotMovable>::value,
320
- "!pybind11::detail::is_move_constructible<NotMovable>::value");
321
- static_assert(pybind11::detail::is_copy_constructible<NotMovable>::value,
322
- "pybind11::detail::is_copy_constructible<NotMovable>::value");
323
- static_assert(!std::is_move_assignable<NotMovable>::value,
324
- "!std::is_move_assignable<NotMovable>::value");
325
- static_assert(std::is_copy_assignable<NotMovable>::value,
326
- "std::is_copy_assignable<NotMovable>::value");
327
- // pybind11 does not have this
328
- // static_assert(!pybind11::detail::is_move_assignable<NotMovable>::value,
329
- // "!pybind11::detail::is_move_assignable<NotMovable>::value");
330
- static_assert(pybind11::detail::is_copy_assignable<NotMovable>::value,
331
- "pybind11::detail::is_copy_assignable<NotMovable>::value");
332
-
333
- struct NotCopyable {
334
- NotCopyable() = default;
335
- NotCopyable(NotCopyable const &) = delete;
336
- NotCopyable(NotCopyable &&) = default;
337
- NotCopyable &operator=(NotCopyable const &) = delete;
338
- NotCopyable &operator=(NotCopyable &&) = default;
339
- };
340
- static_assert(std::is_move_constructible<NotCopyable>::value,
341
- "std::is_move_constructible<NotCopyable>::value");
342
- static_assert(!std::is_copy_constructible<NotCopyable>::value,
343
- "!std::is_copy_constructible<NotCopyable>::value");
344
- static_assert(pybind11::detail::is_move_constructible<NotCopyable>::value,
345
- "pybind11::detail::is_move_constructible<NotCopyable>::value");
346
- static_assert(!pybind11::detail::is_copy_constructible<NotCopyable>::value,
347
- "!pybind11::detail::is_copy_constructible<NotCopyable>::value");
348
- static_assert(std::is_move_assignable<NotCopyable>::value,
349
- "std::is_move_assignable<NotCopyable>::value");
350
- static_assert(!std::is_copy_assignable<NotCopyable>::value,
351
- "!std::is_copy_assignable<NotCopyable>::value");
352
- // pybind11 does not have this
353
- // static_assert(!pybind11::detail::is_move_assignable<NotCopyable>::value,
354
- // "!pybind11::detail::is_move_assignable<NotCopyable>::value");
355
- static_assert(!pybind11::detail::is_copy_assignable<NotCopyable>::value,
356
- "!pybind11::detail::is_copy_assignable<NotCopyable>::value");
357
-
358
- struct NotCopyableNotMovable {
359
- NotCopyableNotMovable() = default;
360
- NotCopyableNotMovable(NotCopyableNotMovable const &) = delete;
361
- NotCopyableNotMovable(NotCopyableNotMovable &&) = delete;
362
- NotCopyableNotMovable &operator=(NotCopyableNotMovable const &) = delete;
363
- NotCopyableNotMovable &operator=(NotCopyableNotMovable &&) = delete;
364
- };
365
- static_assert(!std::is_move_constructible<NotCopyableNotMovable>::value,
366
- "!std::is_move_constructible<NotCopyableNotMovable>::value");
367
- static_assert(!std::is_copy_constructible<NotCopyableNotMovable>::value,
368
- "!std::is_copy_constructible<NotCopyableNotMovable>::value");
369
- static_assert(!pybind11::detail::is_move_constructible<NotCopyableNotMovable>::value,
370
- "!pybind11::detail::is_move_constructible<NotCopyableNotMovable>::value");
371
- static_assert(!pybind11::detail::is_copy_constructible<NotCopyableNotMovable>::value,
372
- "!pybind11::detail::is_copy_constructible<NotCopyableNotMovable>::value");
373
- static_assert(!std::is_move_assignable<NotCopyableNotMovable>::value,
374
- "!std::is_move_assignable<NotCopyableNotMovable>::value");
375
- static_assert(!std::is_copy_assignable<NotCopyableNotMovable>::value,
376
- "!std::is_copy_assignable<NotCopyableNotMovable>::value");
377
- // pybind11 does not have this
378
- // static_assert(!pybind11::detail::is_move_assignable<NotCopyableNotMovable>::value,
379
- // "!pybind11::detail::is_move_assignable<NotCopyableNotMovable>::value");
380
- static_assert(!pybind11::detail::is_copy_assignable<NotCopyableNotMovable>::value,
381
- "!pybind11::detail::is_copy_assignable<NotCopyableNotMovable>::value");
382
-
383
- struct NotMovableVector : std::vector<NotMovable> {};
384
- static_assert(std::is_move_constructible<NotMovableVector>::value,
385
- "std::is_move_constructible<NotMovableVector>::value");
386
- static_assert(std::is_copy_constructible<NotMovableVector>::value,
387
- "std::is_copy_constructible<NotMovableVector>::value");
388
- static_assert(!pybind11::detail::is_move_constructible<NotMovableVector>::value,
389
- "!pybind11::detail::is_move_constructible<NotMovableVector>::value");
390
- static_assert(pybind11::detail::is_copy_constructible<NotMovableVector>::value,
391
- "pybind11::detail::is_copy_constructible<NotMovableVector>::value");
392
- static_assert(std::is_move_assignable<NotMovableVector>::value,
393
- "std::is_move_assignable<NotMovableVector>::value");
394
- static_assert(std::is_copy_assignable<NotMovableVector>::value,
395
- "std::is_copy_assignable<NotMovableVector>::value");
396
- // pybind11 does not have this
397
- // static_assert(!pybind11::detail::is_move_assignable<NotMovableVector>::value,
398
- // "!pybind11::detail::is_move_assignable<NotMovableVector>::value");
399
- static_assert(pybind11::detail::is_copy_assignable<NotMovableVector>::value,
400
- "pybind11::detail::is_copy_assignable<NotMovableVector>::value");
401
-
402
- struct NotCopyableVector : std::vector<NotCopyable> {};
403
- static_assert(std::is_move_constructible<NotCopyableVector>::value,
404
- "std::is_move_constructible<NotCopyableVector>::value");
405
- static_assert(std::is_copy_constructible<NotCopyableVector>::value,
406
- "std::is_copy_constructible<NotCopyableVector>::value");
407
- static_assert(pybind11::detail::is_move_constructible<NotCopyableVector>::value,
408
- "pybind11::detail::is_move_constructible<NotCopyableVector>::value");
409
- static_assert(!pybind11::detail::is_copy_constructible<NotCopyableVector>::value,
410
- "!pybind11::detail::is_copy_constructible<NotCopyableVector>::value");
411
- static_assert(std::is_move_assignable<NotCopyableVector>::value,
412
- "std::is_move_assignable<NotCopyableVector>::value");
413
- static_assert(std::is_copy_assignable<NotCopyableVector>::value,
414
- "std::is_copy_assignable<NotCopyableVector>::value");
415
- // pybind11 does not have this
416
- // static_assert(!pybind11::detail::is_move_assignable<NotCopyableVector>::value,
417
- // "!pybind11::detail::is_move_assignable<NotCopyableVector>::value");
418
- static_assert(!pybind11::detail::is_copy_assignable<NotCopyableVector>::value,
419
- "!pybind11::detail::is_copy_assignable<NotCopyableVector>::value");
420
-
421
- struct NotCopyableNotMovableVector : std::vector<NotCopyableNotMovable> {};
422
- static_assert(std::is_move_constructible<NotCopyableNotMovableVector>::value,
423
- "std::is_move_constructible<NotCopyableNotMovableVector>::value");
424
- static_assert(std::is_copy_constructible<NotCopyableNotMovableVector>::value,
425
- "std::is_copy_constructible<NotCopyableNotMovableVector>::value");
426
- static_assert(!pybind11::detail::is_move_constructible<NotCopyableNotMovableVector>::value,
427
- "!pybind11::detail::is_move_constructible<NotCopyableNotMovableVector>::value");
428
- static_assert(!pybind11::detail::is_copy_constructible<NotCopyableNotMovableVector>::value,
429
- "!pybind11::detail::is_copy_constructible<NotCopyableNotMovableVector>::value");
430
- static_assert(std::is_move_assignable<NotCopyableNotMovableVector>::value,
431
- "std::is_move_assignable<NotCopyableNotMovableVector>::value");
432
- static_assert(std::is_copy_assignable<NotCopyableNotMovableVector>::value,
433
- "std::is_copy_assignable<NotCopyableNotMovableVector>::value");
434
- // pybind11 does not have this
435
- // static_assert(!pybind11::detail::is_move_assignable<NotCopyableNotMovableVector>::value,
436
- // "!pybind11::detail::is_move_assignable<NotCopyableNotMovableVector>::value");
437
- static_assert(!pybind11::detail::is_copy_assignable<NotCopyableNotMovableVector>::value,
438
- "!pybind11::detail::is_copy_assignable<NotCopyableNotMovableVector>::value");
439
-
440
- struct NotMovableMap : std::map<int, NotMovable> {};
441
- static_assert(std::is_move_constructible<NotMovableMap>::value,
442
- "std::is_move_constructible<NotMovableMap>::value");
443
- static_assert(std::is_copy_constructible<NotMovableMap>::value,
444
- "std::is_copy_constructible<NotMovableMap>::value");
445
- static_assert(!pybind11::detail::is_move_constructible<NotMovableMap>::value,
446
- "!pybind11::detail::is_move_constructible<NotMovableMap>::value");
447
- static_assert(pybind11::detail::is_copy_constructible<NotMovableMap>::value,
448
- "pybind11::detail::is_copy_constructible<NotMovableMap>::value");
449
- static_assert(std::is_move_assignable<NotMovableMap>::value,
450
- "std::is_move_assignable<NotMovableMap>::value");
451
- static_assert(std::is_copy_assignable<NotMovableMap>::value,
452
- "std::is_copy_assignable<NotMovableMap>::value");
453
- // pybind11 does not have this
454
- // static_assert(!pybind11::detail::is_move_assignable<NotMovableMap>::value,
455
- // "!pybind11::detail::is_move_assignable<NotMovableMap>::value");
456
- static_assert(pybind11::detail::is_copy_assignable<NotMovableMap>::value,
457
- "pybind11::detail::is_copy_assignable<NotMovableMap>::value");
458
-
459
- struct NotCopyableMap : std::map<int, NotCopyable> {};
460
- static_assert(std::is_move_constructible<NotCopyableMap>::value,
461
- "std::is_move_constructible<NotCopyableMap>::value");
462
- static_assert(std::is_copy_constructible<NotCopyableMap>::value,
463
- "std::is_copy_constructible<NotCopyableMap>::value");
464
- static_assert(pybind11::detail::is_move_constructible<NotCopyableMap>::value,
465
- "pybind11::detail::is_move_constructible<NotCopyableMap>::value");
466
- static_assert(!pybind11::detail::is_copy_constructible<NotCopyableMap>::value,
467
- "!pybind11::detail::is_copy_constructible<NotCopyableMap>::value");
468
- static_assert(std::is_move_assignable<NotCopyableMap>::value,
469
- "std::is_move_assignable<NotCopyableMap>::value");
470
- static_assert(std::is_copy_assignable<NotCopyableMap>::value,
471
- "std::is_copy_assignable<NotCopyableMap>::value");
472
- // pybind11 does not have this
473
- // static_assert(!pybind11::detail::is_move_assignable<NotCopyableMap>::value,
474
- // "!pybind11::detail::is_move_assignable<NotCopyableMap>::value");
475
- static_assert(!pybind11::detail::is_copy_assignable<NotCopyableMap>::value,
476
- "!pybind11::detail::is_copy_assignable<NotCopyableMap>::value");
477
-
478
- struct NotCopyableNotMovableMap : std::map<int, NotCopyableNotMovable> {};
479
- static_assert(std::is_move_constructible<NotCopyableNotMovableMap>::value,
480
- "std::is_move_constructible<NotCopyableNotMovableMap>::value");
481
- static_assert(std::is_copy_constructible<NotCopyableNotMovableMap>::value,
482
- "std::is_copy_constructible<NotCopyableNotMovableMap>::value");
483
- static_assert(!pybind11::detail::is_move_constructible<NotCopyableNotMovableMap>::value,
484
- "!pybind11::detail::is_move_constructible<NotCopyableNotMovableMap>::value");
485
- static_assert(!pybind11::detail::is_copy_constructible<NotCopyableNotMovableMap>::value,
486
- "!pybind11::detail::is_copy_constructible<NotCopyableNotMovableMap>::value");
487
- static_assert(std::is_move_assignable<NotCopyableNotMovableMap>::value,
488
- "std::is_move_assignable<NotCopyableNotMovableMap>::value");
489
- static_assert(std::is_copy_assignable<NotCopyableNotMovableMap>::value,
490
- "std::is_copy_assignable<NotCopyableNotMovableMap>::value");
491
- // pybind11 does not have this
492
- // static_assert(!pybind11::detail::is_move_assignable<NotCopyableNotMovableMap>::value,
493
- // "!pybind11::detail::is_move_assignable<NotCopyableNotMovableMap>::value");
494
- static_assert(!pybind11::detail::is_copy_assignable<NotCopyableNotMovableMap>::value,
495
- "!pybind11::detail::is_copy_assignable<NotCopyableNotMovableMap>::value");
496
-
497
- struct RecursiveVector : std::vector<RecursiveVector> {};
498
- static_assert(std::is_move_constructible<RecursiveVector>::value,
499
- "std::is_move_constructible<RecursiveVector>::value");
500
- static_assert(std::is_copy_constructible<RecursiveVector>::value,
501
- "std::is_copy_constructible<RecursiveVector>::value");
502
- static_assert(pybind11::detail::is_move_constructible<RecursiveVector>::value,
503
- "pybind11::detail::is_move_constructible<RecursiveVector>::value");
504
- static_assert(pybind11::detail::is_copy_constructible<RecursiveVector>::value,
505
- "pybind11::detail::is_copy_constructible<RecursiveVector>::value");
506
- static_assert(std::is_move_assignable<RecursiveVector>::value,
507
- "std::is_move_assignable<RecursiveVector>::value");
508
- static_assert(std::is_copy_assignable<RecursiveVector>::value,
509
- "std::is_copy_assignable<RecursiveVector>::value");
510
- // pybind11 does not have this
511
- // static_assert(!pybind11::detail::is_move_assignable<RecursiveVector>::value,
512
- // "!pybind11::detail::is_move_assignable<RecursiveVector>::value");
513
- static_assert(pybind11::detail::is_copy_assignable<RecursiveVector>::value,
514
- "pybind11::detail::is_copy_assignable<RecursiveVector>::value");
515
-
516
- struct RecursiveMap : std::map<int, RecursiveMap> {};
517
- static_assert(std::is_move_constructible<RecursiveMap>::value,
518
- "std::is_move_constructible<RecursiveMap>::value");
519
- static_assert(std::is_copy_constructible<RecursiveMap>::value,
520
- "std::is_copy_constructible<RecursiveMap>::value");
521
- static_assert(pybind11::detail::is_move_constructible<RecursiveMap>::value,
522
- "pybind11::detail::is_move_constructible<RecursiveMap>::value");
523
- static_assert(pybind11::detail::is_copy_constructible<RecursiveMap>::value,
524
- "pybind11::detail::is_copy_constructible<RecursiveMap>::value");
525
- static_assert(std::is_move_assignable<RecursiveMap>::value,
526
- "std::is_move_assignable<RecursiveMap>::value");
527
- static_assert(std::is_copy_assignable<RecursiveMap>::value,
528
- "std::is_copy_assignable<RecursiveMap>::value");
529
- // pybind11 does not have this
530
- // static_assert(!pybind11::detail::is_move_assignable<RecursiveMap>::value,
531
- // "!pybind11::detail::is_move_assignable<RecursiveMap>::value");
532
- static_assert(pybind11::detail::is_copy_assignable<RecursiveMap>::value,
533
- "pybind11::detail::is_copy_assignable<RecursiveMap>::value");
 
1
+ /*
2
+ tests/test_copy_move_policies.cpp -- 'copy' and 'move' return value policies
3
+ and related tests
4
+
5
+ Copyright (c) 2016 Ben North <ben@redfrontdoor.org>
6
+
7
+ All rights reserved. Use of this source code is governed by a
8
+ BSD-style license that can be found in the LICENSE file.
9
+ */
10
+
11
+ #include <pybind11/stl.h>
12
+
13
+ #include "constructor_stats.h"
14
+ #include "pybind11_tests.h"
15
+
16
+ #include <type_traits>
17
+
18
+ template <typename derived>
19
+ struct empty {
20
+ static const derived &get_one() { return instance_; }
21
+ static derived instance_;
22
+ };
23
+
24
+ struct lacking_copy_ctor : public empty<lacking_copy_ctor> {
25
+ lacking_copy_ctor() = default;
26
+ lacking_copy_ctor(const lacking_copy_ctor &other) = delete;
27
+ };
28
+
29
+ template <>
30
+ lacking_copy_ctor empty<lacking_copy_ctor>::instance_ = {};
31
+
32
+ struct lacking_move_ctor : public empty<lacking_move_ctor> {
33
+ lacking_move_ctor() = default;
34
+ lacking_move_ctor(const lacking_move_ctor &other) = delete;
35
+ lacking_move_ctor(lacking_move_ctor &&other) = delete;
36
+ };
37
+
38
+ template <>
39
+ lacking_move_ctor empty<lacking_move_ctor>::instance_ = {};
40
+
41
+ /* Custom type caster move/copy test classes */
42
+ class MoveOnlyInt {
43
+ public:
44
+ MoveOnlyInt() { print_default_created(this); }
45
+ explicit MoveOnlyInt(int v) : value{v} { print_created(this, value); }
46
+ MoveOnlyInt(MoveOnlyInt &&m) noexcept {
47
+ print_move_created(this, m.value);
48
+ std::swap(value, m.value);
49
+ }
50
+ MoveOnlyInt &operator=(MoveOnlyInt &&m) noexcept {
51
+ print_move_assigned(this, m.value);
52
+ std::swap(value, m.value);
53
+ return *this;
54
+ }
55
+ MoveOnlyInt(const MoveOnlyInt &) = delete;
56
+ MoveOnlyInt &operator=(const MoveOnlyInt &) = delete;
57
+ ~MoveOnlyInt() { print_destroyed(this); }
58
+
59
+ int value;
60
+ };
61
+ class MoveOrCopyInt {
62
+ public:
63
+ MoveOrCopyInt() { print_default_created(this); }
64
+ explicit MoveOrCopyInt(int v) : value{v} { print_created(this, value); }
65
+ MoveOrCopyInt(MoveOrCopyInt &&m) noexcept {
66
+ print_move_created(this, m.value);
67
+ std::swap(value, m.value);
68
+ }
69
+ MoveOrCopyInt &operator=(MoveOrCopyInt &&m) noexcept {
70
+ print_move_assigned(this, m.value);
71
+ std::swap(value, m.value);
72
+ return *this;
73
+ }
74
+ MoveOrCopyInt(const MoveOrCopyInt &c) {
75
+ print_copy_created(this, c.value);
76
+ // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
77
+ value = c.value;
78
+ }
79
+ MoveOrCopyInt &operator=(const MoveOrCopyInt &c) {
80
+ print_copy_assigned(this, c.value);
81
+ value = c.value;
82
+ return *this;
83
+ }
84
+ ~MoveOrCopyInt() { print_destroyed(this); }
85
+
86
+ int value;
87
+ };
88
+ class CopyOnlyInt {
89
+ public:
90
+ CopyOnlyInt() { print_default_created(this); }
91
+ explicit CopyOnlyInt(int v) : value{v} { print_created(this, value); }
92
+ CopyOnlyInt(const CopyOnlyInt &c) {
93
+ print_copy_created(this, c.value);
94
+ // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
95
+ value = c.value;
96
+ }
97
+ CopyOnlyInt &operator=(const CopyOnlyInt &c) {
98
+ print_copy_assigned(this, c.value);
99
+ value = c.value;
100
+ return *this;
101
+ }
102
+ ~CopyOnlyInt() { print_destroyed(this); }
103
+
104
+ int value;
105
+ };
106
+ PYBIND11_NAMESPACE_BEGIN(pybind11)
107
+ PYBIND11_NAMESPACE_BEGIN(detail)
108
+ template <>
109
+ struct type_caster<MoveOnlyInt> {
110
+ PYBIND11_TYPE_CASTER(MoveOnlyInt, const_name("MoveOnlyInt"));
111
+ bool load(handle src, bool) {
112
+ value = MoveOnlyInt(src.cast<int>());
113
+ return true;
114
+ }
115
+ static handle cast(const MoveOnlyInt &m, return_value_policy r, handle p) {
116
+ return pybind11::cast(m.value, r, p);
117
+ }
118
+ };
119
+
120
+ template <>
121
+ struct type_caster<MoveOrCopyInt> {
122
+ PYBIND11_TYPE_CASTER(MoveOrCopyInt, const_name("MoveOrCopyInt"));
123
+ bool load(handle src, bool) {
124
+ value = MoveOrCopyInt(src.cast<int>());
125
+ return true;
126
+ }
127
+ static handle cast(const MoveOrCopyInt &m, return_value_policy r, handle p) {
128
+ return pybind11::cast(m.value, r, p);
129
+ }
130
+ };
131
+
132
+ template <>
133
+ struct type_caster<CopyOnlyInt> {
134
+ protected:
135
+ CopyOnlyInt value;
136
+
137
+ public:
138
+ static constexpr auto name = const_name("CopyOnlyInt");
139
+ bool load(handle src, bool) {
140
+ value = CopyOnlyInt(src.cast<int>());
141
+ return true;
142
+ }
143
+ static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) {
144
+ return pybind11::cast(m.value, r, p);
145
+ }
146
+ static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) {
147
+ if (!src) {
148
+ return none().release();
149
+ }
150
+ return cast(*src, policy, parent);
151
+ }
152
+ explicit operator CopyOnlyInt *() { return &value; }
153
+ explicit operator CopyOnlyInt &() { return value; }
154
+ template <typename T>
155
+ using cast_op_type = pybind11::detail::cast_op_type<T>;
156
+ };
157
+ PYBIND11_NAMESPACE_END(detail)
158
+ PYBIND11_NAMESPACE_END(pybind11)
159
+
160
+ TEST_SUBMODULE(copy_move_policies, m) {
161
+ // test_lacking_copy_ctor
162
+ py::class_<lacking_copy_ctor>(m, "lacking_copy_ctor")
163
+ .def_static("get_one", &lacking_copy_ctor::get_one, py::return_value_policy::copy);
164
+ // test_lacking_move_ctor
165
+ py::class_<lacking_move_ctor>(m, "lacking_move_ctor")
166
+ .def_static("get_one", &lacking_move_ctor::get_one, py::return_value_policy::move);
167
+
168
+ // test_move_and_copy_casts
169
+ // NOLINTNEXTLINE(performance-unnecessary-value-param)
170
+ m.def("move_and_copy_casts", [](const py::object &o) {
171
+ int r = 0;
172
+ r += py::cast<MoveOrCopyInt>(o).value; /* moves */
173
+ r += py::cast<MoveOnlyInt>(o).value; /* moves */
174
+ r += py::cast<CopyOnlyInt>(o).value; /* copies */
175
+ auto m1(py::cast<MoveOrCopyInt>(o)); /* moves */
176
+ auto m2(py::cast<MoveOnlyInt>(o)); /* moves */
177
+ auto m3(py::cast<CopyOnlyInt>(o)); /* copies */
178
+ r += m1.value + m2.value + m3.value;
179
+
180
+ return r;
181
+ });
182
+
183
+ // test_move_and_copy_loads
184
+ m.def("move_only", [](MoveOnlyInt m) { return m.value; });
185
+ // Changing this breaks the existing test: needs careful review.
186
+ // NOLINTNEXTLINE(performance-unnecessary-value-param)
187
+ m.def("move_or_copy", [](MoveOrCopyInt m) { return m.value; });
188
+ // Changing this breaks the existing test: needs careful review.
189
+ // NOLINTNEXTLINE(performance-unnecessary-value-param)
190
+ m.def("copy_only", [](CopyOnlyInt m) { return m.value; });
191
+ m.def("move_pair",
192
+ [](std::pair<MoveOnlyInt, MoveOrCopyInt> p) { return p.first.value + p.second.value; });
193
+ m.def("move_tuple", [](std::tuple<MoveOnlyInt, MoveOrCopyInt, MoveOnlyInt> t) {
194
+ return std::get<0>(t).value + std::get<1>(t).value + std::get<2>(t).value;
195
+ });
196
+ m.def("copy_tuple", [](std::tuple<CopyOnlyInt, CopyOnlyInt> t) {
197
+ return std::get<0>(t).value + std::get<1>(t).value;
198
+ });
199
+ m.def("move_copy_nested",
200
+ [](std::pair<MoveOnlyInt,
201
+ std::pair<std::tuple<MoveOrCopyInt, CopyOnlyInt, std::tuple<MoveOnlyInt>>,
202
+ MoveOrCopyInt>> x) {
203
+ return x.first.value + std::get<0>(x.second.first).value
204
+ + std::get<1>(x.second.first).value
205
+ + std::get<0>(std::get<2>(x.second.first)).value + x.second.second.value;
206
+ });
207
+ m.def("move_and_copy_cstats", []() {
208
+ ConstructorStats::gc();
209
+ // Reset counts to 0 so that previous tests don't affect later ones:
210
+ auto &mc = ConstructorStats::get<MoveOrCopyInt>();
211
+ mc.move_assignments = mc.move_constructions = mc.copy_assignments = mc.copy_constructions
212
+ = 0;
213
+ auto &mo = ConstructorStats::get<MoveOnlyInt>();
214
+ mo.move_assignments = mo.move_constructions = mo.copy_assignments = mo.copy_constructions
215
+ = 0;
216
+ auto &co = ConstructorStats::get<CopyOnlyInt>();
217
+ co.move_assignments = co.move_constructions = co.copy_assignments = co.copy_constructions
218
+ = 0;
219
+ py::dict d;
220
+ d["MoveOrCopyInt"] = py::cast(mc, py::return_value_policy::reference);
221
+ d["MoveOnlyInt"] = py::cast(mo, py::return_value_policy::reference);
222
+ d["CopyOnlyInt"] = py::cast(co, py::return_value_policy::reference);
223
+ return d;
224
+ });
225
+ #ifdef PYBIND11_HAS_OPTIONAL
226
+ // test_move_and_copy_load_optional
227
+ m.attr("has_optional") = true;
228
+ m.def("move_optional", [](std::optional<MoveOnlyInt> o) { return o->value; });
229
+ m.def("move_or_copy_optional", [](std::optional<MoveOrCopyInt> o) { return o->value; });
230
+ m.def("copy_optional", [](std::optional<CopyOnlyInt> o) { return o->value; });
231
+ m.def("move_optional_tuple",
232
+ [](std::optional<std::tuple<MoveOrCopyInt, MoveOnlyInt, CopyOnlyInt>> x) {
233
+ return std::get<0>(*x).value + std::get<1>(*x).value + std::get<2>(*x).value;
234
+ });
235
+ #else
236
+ m.attr("has_optional") = false;
237
+ #endif
238
+
239
+ // #70 compilation issue if operator new is not public - simple body added
240
+ // but not needed on most compilers; MSVC and nvcc don't like a local
241
+ // struct not having a method defined when declared, since it can not be
242
+ // added later.
243
+ struct PrivateOpNew {
244
+ int value = 1;
245
+
246
+ private:
247
+ void *operator new(size_t bytes) {
248
+ void *ptr = std::malloc(bytes);
249
+ if (ptr) {
250
+ return ptr;
251
+ }
252
+ throw std::bad_alloc{};
253
+ }
254
+ };
255
+ py::class_<PrivateOpNew>(m, "PrivateOpNew").def_readonly("value", &PrivateOpNew::value);
256
+ m.def("private_op_new_value", []() { return PrivateOpNew(); });
257
+ m.def(
258
+ "private_op_new_reference",
259
+ []() -> const PrivateOpNew & {
260
+ static PrivateOpNew x{};
261
+ return x;
262
+ },
263
+ py::return_value_policy::reference);
264
+
265
+ // test_move_fallback
266
+ // #389: rvp::move should fall-through to copy on non-movable objects
267
+ struct MoveIssue1 {
268
+ int v;
269
+ explicit MoveIssue1(int v) : v{v} {}
270
+ MoveIssue1(const MoveIssue1 &c) = default;
271
+ MoveIssue1(MoveIssue1 &&) = delete;
272
+ };
273
+ py::class_<MoveIssue1>(m, "MoveIssue1")
274
+ .def(py::init<int>())
275
+ .def_readwrite("value", &MoveIssue1::v);
276
+
277
+ struct MoveIssue2 {
278
+ int v;
279
+ explicit MoveIssue2(int v) : v{v} {}
280
+ MoveIssue2(MoveIssue2 &&) = default;
281
+ };
282
+ py::class_<MoveIssue2>(m, "MoveIssue2")
283
+ .def(py::init<int>())
284
+ .def_readwrite("value", &MoveIssue2::v);
285
+
286
+ // #2742: Don't expect ownership of raw pointer to `new`ed object to be transferred with
287
+ // `py::return_value_policy::move`
288
+ m.def(
289
+ "get_moveissue1",
290
+ [](int i) { return std::unique_ptr<MoveIssue1>(new MoveIssue1(i)); },
291
+ py::return_value_policy::move);
292
+ m.def(
293
+ "get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move);
294
+
295
+ // Make sure that cast from pytype rvalue to other pytype works
296
+ m.def("get_pytype_rvalue_castissue", [](double i) { return py::float_(i).cast<py::int_>(); });
297
+ }
298
+
299
+ /*
300
+ * Rest of the file:
301
+ * static_assert based tests for pybind11 adaptations of
302
+ * std::is_move_constructible, std::is_copy_constructible and
303
+ * std::is_copy_assignable (no adaptation of std::is_move_assignable).
304
+ * Difference between pybind11 and std traits: pybind11 traits will also check
305
+ * the contained value_types.
306
+ */
307
+
308
+ struct NotMovable {
309
+ NotMovable() = default;
310
+ NotMovable(NotMovable const &) = default;
311
+ NotMovable(NotMovable &&) = delete;
312
+ NotMovable &operator=(NotMovable const &) = default;
313
+ NotMovable &operator=(NotMovable &&) = delete;
314
+ };
315
+ static_assert(!std::is_move_constructible<NotMovable>::value,
316
+ "!std::is_move_constructible<NotMovable>::value");
317
+ static_assert(std::is_copy_constructible<NotMovable>::value,
318
+ "std::is_copy_constructible<NotMovable>::value");
319
+ static_assert(!pybind11::detail::is_move_constructible<NotMovable>::value,
320
+ "!pybind11::detail::is_move_constructible<NotMovable>::value");
321
+ static_assert(pybind11::detail::is_copy_constructible<NotMovable>::value,
322
+ "pybind11::detail::is_copy_constructible<NotMovable>::value");
323
+ static_assert(!std::is_move_assignable<NotMovable>::value,
324
+ "!std::is_move_assignable<NotMovable>::value");
325
+ static_assert(std::is_copy_assignable<NotMovable>::value,
326
+ "std::is_copy_assignable<NotMovable>::value");
327
+ // pybind11 does not have this
328
+ // static_assert(!pybind11::detail::is_move_assignable<NotMovable>::value,
329
+ // "!pybind11::detail::is_move_assignable<NotMovable>::value");
330
+ static_assert(pybind11::detail::is_copy_assignable<NotMovable>::value,
331
+ "pybind11::detail::is_copy_assignable<NotMovable>::value");
332
+
333
+ struct NotCopyable {
334
+ NotCopyable() = default;
335
+ NotCopyable(NotCopyable const &) = delete;
336
+ NotCopyable(NotCopyable &&) = default;
337
+ NotCopyable &operator=(NotCopyable const &) = delete;
338
+ NotCopyable &operator=(NotCopyable &&) = default;
339
+ };
340
+ static_assert(std::is_move_constructible<NotCopyable>::value,
341
+ "std::is_move_constructible<NotCopyable>::value");
342
+ static_assert(!std::is_copy_constructible<NotCopyable>::value,
343
+ "!std::is_copy_constructible<NotCopyable>::value");
344
+ static_assert(pybind11::detail::is_move_constructible<NotCopyable>::value,
345
+ "pybind11::detail::is_move_constructible<NotCopyable>::value");
346
+ static_assert(!pybind11::detail::is_copy_constructible<NotCopyable>::value,
347
+ "!pybind11::detail::is_copy_constructible<NotCopyable>::value");
348
+ static_assert(std::is_move_assignable<NotCopyable>::value,
349
+ "std::is_move_assignable<NotCopyable>::value");
350
+ static_assert(!std::is_copy_assignable<NotCopyable>::value,
351
+ "!std::is_copy_assignable<NotCopyable>::value");
352
+ // pybind11 does not have this
353
+ // static_assert(!pybind11::detail::is_move_assignable<NotCopyable>::value,
354
+ // "!pybind11::detail::is_move_assignable<NotCopyable>::value");
355
+ static_assert(!pybind11::detail::is_copy_assignable<NotCopyable>::value,
356
+ "!pybind11::detail::is_copy_assignable<NotCopyable>::value");
357
+
358
+ struct NotCopyableNotMovable {
359
+ NotCopyableNotMovable() = default;
360
+ NotCopyableNotMovable(NotCopyableNotMovable const &) = delete;
361
+ NotCopyableNotMovable(NotCopyableNotMovable &&) = delete;
362
+ NotCopyableNotMovable &operator=(NotCopyableNotMovable const &) = delete;
363
+ NotCopyableNotMovable &operator=(NotCopyableNotMovable &&) = delete;
364
+ };
365
+ static_assert(!std::is_move_constructible<NotCopyableNotMovable>::value,
366
+ "!std::is_move_constructible<NotCopyableNotMovable>::value");
367
+ static_assert(!std::is_copy_constructible<NotCopyableNotMovable>::value,
368
+ "!std::is_copy_constructible<NotCopyableNotMovable>::value");
369
+ static_assert(!pybind11::detail::is_move_constructible<NotCopyableNotMovable>::value,
370
+ "!pybind11::detail::is_move_constructible<NotCopyableNotMovable>::value");
371
+ static_assert(!pybind11::detail::is_copy_constructible<NotCopyableNotMovable>::value,
372
+ "!pybind11::detail::is_copy_constructible<NotCopyableNotMovable>::value");
373
+ static_assert(!std::is_move_assignable<NotCopyableNotMovable>::value,
374
+ "!std::is_move_assignable<NotCopyableNotMovable>::value");
375
+ static_assert(!std::is_copy_assignable<NotCopyableNotMovable>::value,
376
+ "!std::is_copy_assignable<NotCopyableNotMovable>::value");
377
+ // pybind11 does not have this
378
+ // static_assert(!pybind11::detail::is_move_assignable<NotCopyableNotMovable>::value,
379
+ // "!pybind11::detail::is_move_assignable<NotCopyableNotMovable>::value");
380
+ static_assert(!pybind11::detail::is_copy_assignable<NotCopyableNotMovable>::value,
381
+ "!pybind11::detail::is_copy_assignable<NotCopyableNotMovable>::value");
382
+
383
+ struct NotMovableVector : std::vector<NotMovable> {};
384
+ static_assert(std::is_move_constructible<NotMovableVector>::value,
385
+ "std::is_move_constructible<NotMovableVector>::value");
386
+ static_assert(std::is_copy_constructible<NotMovableVector>::value,
387
+ "std::is_copy_constructible<NotMovableVector>::value");
388
+ static_assert(!pybind11::detail::is_move_constructible<NotMovableVector>::value,
389
+ "!pybind11::detail::is_move_constructible<NotMovableVector>::value");
390
+ static_assert(pybind11::detail::is_copy_constructible<NotMovableVector>::value,
391
+ "pybind11::detail::is_copy_constructible<NotMovableVector>::value");
392
+ static_assert(std::is_move_assignable<NotMovableVector>::value,
393
+ "std::is_move_assignable<NotMovableVector>::value");
394
+ static_assert(std::is_copy_assignable<NotMovableVector>::value,
395
+ "std::is_copy_assignable<NotMovableVector>::value");
396
+ // pybind11 does not have this
397
+ // static_assert(!pybind11::detail::is_move_assignable<NotMovableVector>::value,
398
+ // "!pybind11::detail::is_move_assignable<NotMovableVector>::value");
399
+ static_assert(pybind11::detail::is_copy_assignable<NotMovableVector>::value,
400
+ "pybind11::detail::is_copy_assignable<NotMovableVector>::value");
401
+
402
+ struct NotCopyableVector : std::vector<NotCopyable> {};
403
+ static_assert(std::is_move_constructible<NotCopyableVector>::value,
404
+ "std::is_move_constructible<NotCopyableVector>::value");
405
+ static_assert(std::is_copy_constructible<NotCopyableVector>::value,
406
+ "std::is_copy_constructible<NotCopyableVector>::value");
407
+ static_assert(pybind11::detail::is_move_constructible<NotCopyableVector>::value,
408
+ "pybind11::detail::is_move_constructible<NotCopyableVector>::value");
409
+ static_assert(!pybind11::detail::is_copy_constructible<NotCopyableVector>::value,
410
+ "!pybind11::detail::is_copy_constructible<NotCopyableVector>::value");
411
+ static_assert(std::is_move_assignable<NotCopyableVector>::value,
412
+ "std::is_move_assignable<NotCopyableVector>::value");
413
+ static_assert(std::is_copy_assignable<NotCopyableVector>::value,
414
+ "std::is_copy_assignable<NotCopyableVector>::value");
415
+ // pybind11 does not have this
416
+ // static_assert(!pybind11::detail::is_move_assignable<NotCopyableVector>::value,
417
+ // "!pybind11::detail::is_move_assignable<NotCopyableVector>::value");
418
+ static_assert(!pybind11::detail::is_copy_assignable<NotCopyableVector>::value,
419
+ "!pybind11::detail::is_copy_assignable<NotCopyableVector>::value");
420
+
421
+ struct NotCopyableNotMovableVector : std::vector<NotCopyableNotMovable> {};
422
+ static_assert(std::is_move_constructible<NotCopyableNotMovableVector>::value,
423
+ "std::is_move_constructible<NotCopyableNotMovableVector>::value");
424
+ static_assert(std::is_copy_constructible<NotCopyableNotMovableVector>::value,
425
+ "std::is_copy_constructible<NotCopyableNotMovableVector>::value");
426
+ static_assert(!pybind11::detail::is_move_constructible<NotCopyableNotMovableVector>::value,
427
+ "!pybind11::detail::is_move_constructible<NotCopyableNotMovableVector>::value");
428
+ static_assert(!pybind11::detail::is_copy_constructible<NotCopyableNotMovableVector>::value,
429
+ "!pybind11::detail::is_copy_constructible<NotCopyableNotMovableVector>::value");
430
+ static_assert(std::is_move_assignable<NotCopyableNotMovableVector>::value,
431
+ "std::is_move_assignable<NotCopyableNotMovableVector>::value");
432
+ static_assert(std::is_copy_assignable<NotCopyableNotMovableVector>::value,
433
+ "std::is_copy_assignable<NotCopyableNotMovableVector>::value");
434
+ // pybind11 does not have this
435
+ // static_assert(!pybind11::detail::is_move_assignable<NotCopyableNotMovableVector>::value,
436
+ // "!pybind11::detail::is_move_assignable<NotCopyableNotMovableVector>::value");
437
+ static_assert(!pybind11::detail::is_copy_assignable<NotCopyableNotMovableVector>::value,
438
+ "!pybind11::detail::is_copy_assignable<NotCopyableNotMovableVector>::value");
439
+
440
+ struct NotMovableMap : std::map<int, NotMovable> {};
441
+ static_assert(std::is_move_constructible<NotMovableMap>::value,
442
+ "std::is_move_constructible<NotMovableMap>::value");
443
+ static_assert(std::is_copy_constructible<NotMovableMap>::value,
444
+ "std::is_copy_constructible<NotMovableMap>::value");
445
+ static_assert(!pybind11::detail::is_move_constructible<NotMovableMap>::value,
446
+ "!pybind11::detail::is_move_constructible<NotMovableMap>::value");
447
+ static_assert(pybind11::detail::is_copy_constructible<NotMovableMap>::value,
448
+ "pybind11::detail::is_copy_constructible<NotMovableMap>::value");
449
+ static_assert(std::is_move_assignable<NotMovableMap>::value,
450
+ "std::is_move_assignable<NotMovableMap>::value");
451
+ static_assert(std::is_copy_assignable<NotMovableMap>::value,
452
+ "std::is_copy_assignable<NotMovableMap>::value");
453
+ // pybind11 does not have this
454
+ // static_assert(!pybind11::detail::is_move_assignable<NotMovableMap>::value,
455
+ // "!pybind11::detail::is_move_assignable<NotMovableMap>::value");
456
+ static_assert(pybind11::detail::is_copy_assignable<NotMovableMap>::value,
457
+ "pybind11::detail::is_copy_assignable<NotMovableMap>::value");
458
+
459
+ struct NotCopyableMap : std::map<int, NotCopyable> {};
460
+ static_assert(std::is_move_constructible<NotCopyableMap>::value,
461
+ "std::is_move_constructible<NotCopyableMap>::value");
462
+ static_assert(std::is_copy_constructible<NotCopyableMap>::value,
463
+ "std::is_copy_constructible<NotCopyableMap>::value");
464
+ static_assert(pybind11::detail::is_move_constructible<NotCopyableMap>::value,
465
+ "pybind11::detail::is_move_constructible<NotCopyableMap>::value");
466
+ static_assert(!pybind11::detail::is_copy_constructible<NotCopyableMap>::value,
467
+ "!pybind11::detail::is_copy_constructible<NotCopyableMap>::value");
468
+ static_assert(std::is_move_assignable<NotCopyableMap>::value,
469
+ "std::is_move_assignable<NotCopyableMap>::value");
470
+ static_assert(std::is_copy_assignable<NotCopyableMap>::value,
471
+ "std::is_copy_assignable<NotCopyableMap>::value");
472
+ // pybind11 does not have this
473
+ // static_assert(!pybind11::detail::is_move_assignable<NotCopyableMap>::value,
474
+ // "!pybind11::detail::is_move_assignable<NotCopyableMap>::value");
475
+ static_assert(!pybind11::detail::is_copy_assignable<NotCopyableMap>::value,
476
+ "!pybind11::detail::is_copy_assignable<NotCopyableMap>::value");
477
+
478
+ struct NotCopyableNotMovableMap : std::map<int, NotCopyableNotMovable> {};
479
+ static_assert(std::is_move_constructible<NotCopyableNotMovableMap>::value,
480
+ "std::is_move_constructible<NotCopyableNotMovableMap>::value");
481
+ static_assert(std::is_copy_constructible<NotCopyableNotMovableMap>::value,
482
+ "std::is_copy_constructible<NotCopyableNotMovableMap>::value");
483
+ static_assert(!pybind11::detail::is_move_constructible<NotCopyableNotMovableMap>::value,
484
+ "!pybind11::detail::is_move_constructible<NotCopyableNotMovableMap>::value");
485
+ static_assert(!pybind11::detail::is_copy_constructible<NotCopyableNotMovableMap>::value,
486
+ "!pybind11::detail::is_copy_constructible<NotCopyableNotMovableMap>::value");
487
+ static_assert(std::is_move_assignable<NotCopyableNotMovableMap>::value,
488
+ "std::is_move_assignable<NotCopyableNotMovableMap>::value");
489
+ static_assert(std::is_copy_assignable<NotCopyableNotMovableMap>::value,
490
+ "std::is_copy_assignable<NotCopyableNotMovableMap>::value");
491
+ // pybind11 does not have this
492
+ // static_assert(!pybind11::detail::is_move_assignable<NotCopyableNotMovableMap>::value,
493
+ // "!pybind11::detail::is_move_assignable<NotCopyableNotMovableMap>::value");
494
+ static_assert(!pybind11::detail::is_copy_assignable<NotCopyableNotMovableMap>::value,
495
+ "!pybind11::detail::is_copy_assignable<NotCopyableNotMovableMap>::value");
496
+
497
+ struct RecursiveVector : std::vector<RecursiveVector> {};
498
+ static_assert(std::is_move_constructible<RecursiveVector>::value,
499
+ "std::is_move_constructible<RecursiveVector>::value");
500
+ static_assert(std::is_copy_constructible<RecursiveVector>::value,
501
+ "std::is_copy_constructible<RecursiveVector>::value");
502
+ static_assert(pybind11::detail::is_move_constructible<RecursiveVector>::value,
503
+ "pybind11::detail::is_move_constructible<RecursiveVector>::value");
504
+ static_assert(pybind11::detail::is_copy_constructible<RecursiveVector>::value,
505
+ "pybind11::detail::is_copy_constructible<RecursiveVector>::value");
506
+ static_assert(std::is_move_assignable<RecursiveVector>::value,
507
+ "std::is_move_assignable<RecursiveVector>::value");
508
+ static_assert(std::is_copy_assignable<RecursiveVector>::value,
509
+ "std::is_copy_assignable<RecursiveVector>::value");
510
+ // pybind11 does not have this
511
+ // static_assert(!pybind11::detail::is_move_assignable<RecursiveVector>::value,
512
+ // "!pybind11::detail::is_move_assignable<RecursiveVector>::value");
513
+ static_assert(pybind11::detail::is_copy_assignable<RecursiveVector>::value,
514
+ "pybind11::detail::is_copy_assignable<RecursiveVector>::value");
515
+
516
+ struct RecursiveMap : std::map<int, RecursiveMap> {};
517
+ static_assert(std::is_move_constructible<RecursiveMap>::value,
518
+ "std::is_move_constructible<RecursiveMap>::value");
519
+ static_assert(std::is_copy_constructible<RecursiveMap>::value,
520
+ "std::is_copy_constructible<RecursiveMap>::value");
521
+ static_assert(pybind11::detail::is_move_constructible<RecursiveMap>::value,
522
+ "pybind11::detail::is_move_constructible<RecursiveMap>::value");
523
+ static_assert(pybind11::detail::is_copy_constructible<RecursiveMap>::value,
524
+ "pybind11::detail::is_copy_constructible<RecursiveMap>::value");
525
+ static_assert(std::is_move_assignable<RecursiveMap>::value,
526
+ "std::is_move_assignable<RecursiveMap>::value");
527
+ static_assert(std::is_copy_assignable<RecursiveMap>::value,
528
+ "std::is_copy_assignable<RecursiveMap>::value");
529
+ // pybind11 does not have this
530
+ // static_assert(!pybind11::detail::is_move_assignable<RecursiveMap>::value,
531
+ // "!pybind11::detail::is_move_assignable<RecursiveMap>::value");
532
+ static_assert(pybind11::detail::is_copy_assignable<RecursiveMap>::value,
533
+ "pybind11::detail::is_copy_assignable<RecursiveMap>::value");
third_party/CityFlow/extern/pybind11/tests/test_copy_move.py CHANGED
@@ -1,132 +1,132 @@
1
- import pytest
2
-
3
- from pybind11_tests import copy_move_policies as m
4
-
5
-
6
- def test_lacking_copy_ctor():
7
- with pytest.raises(RuntimeError) as excinfo:
8
- m.lacking_copy_ctor.get_one()
9
- assert "is non-copyable!" in str(excinfo.value)
10
-
11
-
12
- def test_lacking_move_ctor():
13
- with pytest.raises(RuntimeError) as excinfo:
14
- m.lacking_move_ctor.get_one()
15
- assert "is neither movable nor copyable!" in str(excinfo.value)
16
-
17
-
18
- def test_move_and_copy_casts():
19
- """Cast some values in C++ via custom type casters and count the number of moves/copies."""
20
-
21
- cstats = m.move_and_copy_cstats()
22
- c_m, c_mc, c_c = (
23
- cstats["MoveOnlyInt"],
24
- cstats["MoveOrCopyInt"],
25
- cstats["CopyOnlyInt"],
26
- )
27
-
28
- # The type move constructions/assignments below each get incremented: the move assignment comes
29
- # from the type_caster load; the move construction happens when extracting that via a cast or
30
- # loading into an argument.
31
- assert m.move_and_copy_casts(3) == 18
32
- assert c_m.copy_assignments + c_m.copy_constructions == 0
33
- assert c_m.move_assignments == 2
34
- assert c_m.move_constructions >= 2
35
- assert c_mc.alive() == 0
36
- assert c_mc.copy_assignments + c_mc.copy_constructions == 0
37
- assert c_mc.move_assignments == 2
38
- assert c_mc.move_constructions >= 2
39
- assert c_c.alive() == 0
40
- assert c_c.copy_assignments == 2
41
- assert c_c.copy_constructions >= 2
42
- assert c_m.alive() + c_mc.alive() + c_c.alive() == 0
43
-
44
-
45
- def test_move_and_copy_loads():
46
- """Call some functions that load arguments via custom type casters and count the number of
47
- moves/copies."""
48
-
49
- cstats = m.move_and_copy_cstats()
50
- c_m, c_mc, c_c = (
51
- cstats["MoveOnlyInt"],
52
- cstats["MoveOrCopyInt"],
53
- cstats["CopyOnlyInt"],
54
- )
55
-
56
- assert m.move_only(10) == 10 # 1 move, c_m
57
- assert m.move_or_copy(11) == 11 # 1 move, c_mc
58
- assert m.copy_only(12) == 12 # 1 copy, c_c
59
- assert m.move_pair((13, 14)) == 27 # 1 c_m move, 1 c_mc move
60
- assert m.move_tuple((15, 16, 17)) == 48 # 2 c_m moves, 1 c_mc move
61
- assert m.copy_tuple((18, 19)) == 37 # 2 c_c copies
62
- # Direct constructions: 2 c_m moves, 2 c_mc moves, 1 c_c copy
63
- # Extra moves/copies when moving pairs/tuples: 3 c_m, 3 c_mc, 2 c_c
64
- assert m.move_copy_nested((1, ((2, 3, (4,)), 5))) == 15
65
-
66
- assert c_m.copy_assignments + c_m.copy_constructions == 0
67
- assert c_m.move_assignments == 6
68
- assert c_m.move_constructions == 9
69
- assert c_mc.copy_assignments + c_mc.copy_constructions == 0
70
- assert c_mc.move_assignments == 5
71
- assert c_mc.move_constructions == 8
72
- assert c_c.copy_assignments == 4
73
- assert c_c.copy_constructions == 6
74
- assert c_m.alive() + c_mc.alive() + c_c.alive() == 0
75
-
76
-
77
- @pytest.mark.skipif(not m.has_optional, reason="no <optional>")
78
- def test_move_and_copy_load_optional():
79
- """Tests move/copy loads of std::optional arguments"""
80
-
81
- cstats = m.move_and_copy_cstats()
82
- c_m, c_mc, c_c = (
83
- cstats["MoveOnlyInt"],
84
- cstats["MoveOrCopyInt"],
85
- cstats["CopyOnlyInt"],
86
- )
87
-
88
- # The extra move/copy constructions below come from the std::optional move (which has to move
89
- # its arguments):
90
- assert m.move_optional(10) == 10 # c_m: 1 move assign, 2 move construct
91
- assert m.move_or_copy_optional(11) == 11 # c_mc: 1 move assign, 2 move construct
92
- assert m.copy_optional(12) == 12 # c_c: 1 copy assign, 2 copy construct
93
- # 1 move assign + move construct moves each of c_m, c_mc, 1 c_c copy
94
- # +1 move/copy construct each from moving the tuple
95
- # +1 move/copy construct each from moving the optional (which moves the tuple again)
96
- assert m.move_optional_tuple((3, 4, 5)) == 12
97
-
98
- assert c_m.copy_assignments + c_m.copy_constructions == 0
99
- assert c_m.move_assignments == 2
100
- assert c_m.move_constructions == 5
101
- assert c_mc.copy_assignments + c_mc.copy_constructions == 0
102
- assert c_mc.move_assignments == 2
103
- assert c_mc.move_constructions == 5
104
- assert c_c.copy_assignments == 2
105
- assert c_c.copy_constructions == 5
106
- assert c_m.alive() + c_mc.alive() + c_c.alive() == 0
107
-
108
-
109
- def test_private_op_new():
110
- """An object with a private `operator new` cannot be returned by value"""
111
-
112
- with pytest.raises(RuntimeError) as excinfo:
113
- m.private_op_new_value()
114
- assert "is neither movable nor copyable" in str(excinfo.value)
115
-
116
- assert m.private_op_new_reference().value == 1
117
-
118
-
119
- def test_move_fallback():
120
- """#389: rvp::move should fall-through to copy on non-movable objects"""
121
-
122
- m1 = m.get_moveissue1(1)
123
- assert m1.value == 1
124
- m2 = m.get_moveissue2(2)
125
- assert m2.value == 2
126
-
127
-
128
- def test_pytype_rvalue_cast():
129
- """Make sure that cast from pytype rvalue to other pytype works"""
130
-
131
- value = m.get_pytype_rvalue_castissue(1.0)
132
- assert value == 1
 
1
+ import pytest
2
+
3
+ from pybind11_tests import copy_move_policies as m
4
+
5
+
6
+ def test_lacking_copy_ctor():
7
+ with pytest.raises(RuntimeError) as excinfo:
8
+ m.lacking_copy_ctor.get_one()
9
+ assert "is non-copyable!" in str(excinfo.value)
10
+
11
+
12
+ def test_lacking_move_ctor():
13
+ with pytest.raises(RuntimeError) as excinfo:
14
+ m.lacking_move_ctor.get_one()
15
+ assert "is neither movable nor copyable!" in str(excinfo.value)
16
+
17
+
18
+ def test_move_and_copy_casts():
19
+ """Cast some values in C++ via custom type casters and count the number of moves/copies."""
20
+
21
+ cstats = m.move_and_copy_cstats()
22
+ c_m, c_mc, c_c = (
23
+ cstats["MoveOnlyInt"],
24
+ cstats["MoveOrCopyInt"],
25
+ cstats["CopyOnlyInt"],
26
+ )
27
+
28
+ # The type move constructions/assignments below each get incremented: the move assignment comes
29
+ # from the type_caster load; the move construction happens when extracting that via a cast or
30
+ # loading into an argument.
31
+ assert m.move_and_copy_casts(3) == 18
32
+ assert c_m.copy_assignments + c_m.copy_constructions == 0
33
+ assert c_m.move_assignments == 2
34
+ assert c_m.move_constructions >= 2
35
+ assert c_mc.alive() == 0
36
+ assert c_mc.copy_assignments + c_mc.copy_constructions == 0
37
+ assert c_mc.move_assignments == 2
38
+ assert c_mc.move_constructions >= 2
39
+ assert c_c.alive() == 0
40
+ assert c_c.copy_assignments == 2
41
+ assert c_c.copy_constructions >= 2
42
+ assert c_m.alive() + c_mc.alive() + c_c.alive() == 0
43
+
44
+
45
+ def test_move_and_copy_loads():
46
+ """Call some functions that load arguments via custom type casters and count the number of
47
+ moves/copies."""
48
+
49
+ cstats = m.move_and_copy_cstats()
50
+ c_m, c_mc, c_c = (
51
+ cstats["MoveOnlyInt"],
52
+ cstats["MoveOrCopyInt"],
53
+ cstats["CopyOnlyInt"],
54
+ )
55
+
56
+ assert m.move_only(10) == 10 # 1 move, c_m
57
+ assert m.move_or_copy(11) == 11 # 1 move, c_mc
58
+ assert m.copy_only(12) == 12 # 1 copy, c_c
59
+ assert m.move_pair((13, 14)) == 27 # 1 c_m move, 1 c_mc move
60
+ assert m.move_tuple((15, 16, 17)) == 48 # 2 c_m moves, 1 c_mc move
61
+ assert m.copy_tuple((18, 19)) == 37 # 2 c_c copies
62
+ # Direct constructions: 2 c_m moves, 2 c_mc moves, 1 c_c copy
63
+ # Extra moves/copies when moving pairs/tuples: 3 c_m, 3 c_mc, 2 c_c
64
+ assert m.move_copy_nested((1, ((2, 3, (4,)), 5))) == 15
65
+
66
+ assert c_m.copy_assignments + c_m.copy_constructions == 0
67
+ assert c_m.move_assignments == 6
68
+ assert c_m.move_constructions == 9
69
+ assert c_mc.copy_assignments + c_mc.copy_constructions == 0
70
+ assert c_mc.move_assignments == 5
71
+ assert c_mc.move_constructions == 8
72
+ assert c_c.copy_assignments == 4
73
+ assert c_c.copy_constructions == 6
74
+ assert c_m.alive() + c_mc.alive() + c_c.alive() == 0
75
+
76
+
77
+ @pytest.mark.skipif(not m.has_optional, reason="no <optional>")
78
+ def test_move_and_copy_load_optional():
79
+ """Tests move/copy loads of std::optional arguments"""
80
+
81
+ cstats = m.move_and_copy_cstats()
82
+ c_m, c_mc, c_c = (
83
+ cstats["MoveOnlyInt"],
84
+ cstats["MoveOrCopyInt"],
85
+ cstats["CopyOnlyInt"],
86
+ )
87
+
88
+ # The extra move/copy constructions below come from the std::optional move (which has to move
89
+ # its arguments):
90
+ assert m.move_optional(10) == 10 # c_m: 1 move assign, 2 move construct
91
+ assert m.move_or_copy_optional(11) == 11 # c_mc: 1 move assign, 2 move construct
92
+ assert m.copy_optional(12) == 12 # c_c: 1 copy assign, 2 copy construct
93
+ # 1 move assign + move construct moves each of c_m, c_mc, 1 c_c copy
94
+ # +1 move/copy construct each from moving the tuple
95
+ # +1 move/copy construct each from moving the optional (which moves the tuple again)
96
+ assert m.move_optional_tuple((3, 4, 5)) == 12
97
+
98
+ assert c_m.copy_assignments + c_m.copy_constructions == 0
99
+ assert c_m.move_assignments == 2
100
+ assert c_m.move_constructions == 5
101
+ assert c_mc.copy_assignments + c_mc.copy_constructions == 0
102
+ assert c_mc.move_assignments == 2
103
+ assert c_mc.move_constructions == 5
104
+ assert c_c.copy_assignments == 2
105
+ assert c_c.copy_constructions == 5
106
+ assert c_m.alive() + c_mc.alive() + c_c.alive() == 0
107
+
108
+
109
+ def test_private_op_new():
110
+ """An object with a private `operator new` cannot be returned by value"""
111
+
112
+ with pytest.raises(RuntimeError) as excinfo:
113
+ m.private_op_new_value()
114
+ assert "is neither movable nor copyable" in str(excinfo.value)
115
+
116
+ assert m.private_op_new_reference().value == 1
117
+
118
+
119
+ def test_move_fallback():
120
+ """#389: rvp::move should fall-through to copy on non-movable objects"""
121
+
122
+ m1 = m.get_moveissue1(1)
123
+ assert m1.value == 1
124
+ m2 = m.get_moveissue2(2)
125
+ assert m2.value == 2
126
+
127
+
128
+ def test_pytype_rvalue_cast():
129
+ """Make sure that cast from pytype rvalue to other pytype works"""
130
+
131
+ value = m.get_pytype_rvalue_castissue(1.0)
132
+ assert value == 1
third_party/CityFlow/extern/pybind11/tests/test_custom_type_casters.cpp CHANGED
@@ -1,221 +1,221 @@
1
- /*
2
- tests/test_custom_type_casters.cpp -- tests type_caster<T>
3
-
4
- Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include "constructor_stats.h"
11
- #include "pybind11_tests.h"
12
-
13
- // py::arg/py::arg_v testing: these arguments just record their argument when invoked
14
- class ArgInspector1 {
15
- public:
16
- std::string arg = "(default arg inspector 1)";
17
- };
18
- class ArgInspector2 {
19
- public:
20
- std::string arg = "(default arg inspector 2)";
21
- };
22
- class ArgAlwaysConverts {};
23
-
24
- namespace PYBIND11_NAMESPACE {
25
- namespace detail {
26
- template <>
27
- struct type_caster<ArgInspector1> {
28
- public:
29
- // Classic
30
- #ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
31
- PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
32
- #else
33
- PYBIND11_TYPE_CASTER(ArgInspector1, const_name("ArgInspector1"));
34
- #endif
35
-
36
- bool load(handle src, bool convert) {
37
- value.arg = "loading ArgInspector1 argument " + std::string(convert ? "WITH" : "WITHOUT")
38
- + " conversion allowed. "
39
- "Argument value = "
40
- + (std::string) str(src);
41
- return true;
42
- }
43
-
44
- static handle cast(const ArgInspector1 &src, return_value_policy, handle) {
45
- return str(src.arg).release();
46
- }
47
- };
48
- template <>
49
- struct type_caster<ArgInspector2> {
50
- public:
51
- PYBIND11_TYPE_CASTER(ArgInspector2, const_name("ArgInspector2"));
52
-
53
- bool load(handle src, bool convert) {
54
- value.arg = "loading ArgInspector2 argument " + std::string(convert ? "WITH" : "WITHOUT")
55
- + " conversion allowed. "
56
- "Argument value = "
57
- + (std::string) str(src);
58
- return true;
59
- }
60
-
61
- static handle cast(const ArgInspector2 &src, return_value_policy, handle) {
62
- return str(src.arg).release();
63
- }
64
- };
65
- template <>
66
- struct type_caster<ArgAlwaysConverts> {
67
- public:
68
- PYBIND11_TYPE_CASTER(ArgAlwaysConverts, const_name("ArgAlwaysConverts"));
69
-
70
- bool load(handle, bool convert) { return convert; }
71
-
72
- static handle cast(const ArgAlwaysConverts &, return_value_policy, handle) {
73
- return py::none().release();
74
- }
75
- };
76
- } // namespace detail
77
- } // namespace PYBIND11_NAMESPACE
78
-
79
- // test_custom_caster_destruction
80
- class DestructionTester {
81
- public:
82
- DestructionTester() { print_default_created(this); }
83
- ~DestructionTester() { print_destroyed(this); }
84
- DestructionTester(const DestructionTester &) { print_copy_created(this); }
85
- DestructionTester(DestructionTester &&) noexcept { print_move_created(this); }
86
- DestructionTester &operator=(const DestructionTester &) {
87
- print_copy_assigned(this);
88
- return *this;
89
- }
90
- DestructionTester &operator=(DestructionTester &&) noexcept {
91
- print_move_assigned(this);
92
- return *this;
93
- }
94
- };
95
- namespace PYBIND11_NAMESPACE {
96
- namespace detail {
97
- template <>
98
- struct type_caster<DestructionTester> {
99
- PYBIND11_TYPE_CASTER(DestructionTester, const_name("DestructionTester"));
100
- bool load(handle, bool) { return true; }
101
-
102
- static handle cast(const DestructionTester &, return_value_policy, handle) {
103
- return py::bool_(true).release();
104
- }
105
- };
106
- } // namespace detail
107
- } // namespace PYBIND11_NAMESPACE
108
-
109
- // Define type caster outside of `pybind11::detail` and then alias it.
110
- namespace other_lib {
111
- struct MyType {};
112
- // Corrupt `py` shorthand alias for surrounding context.
113
- namespace py {}
114
- // Corrupt unqualified relative `pybind11` namespace.
115
- namespace PYBIND11_NAMESPACE {}
116
- // Correct alias.
117
- namespace py_ = ::pybind11;
118
- // Define caster. This is effectively no-op, we only ensure it compiles and we
119
- // don't have any symbol collision when using macro mixin.
120
- struct my_caster {
121
- PYBIND11_TYPE_CASTER(MyType, py_::detail::const_name("MyType"));
122
- bool load(py_::handle, bool) { return true; }
123
-
124
- static py_::handle cast(const MyType &, py_::return_value_policy, py_::handle) {
125
- return py_::bool_(true).release();
126
- }
127
- };
128
- } // namespace other_lib
129
- // Effectively "alias" it into correct namespace (via inheritance).
130
- namespace PYBIND11_NAMESPACE {
131
- namespace detail {
132
- template <>
133
- struct type_caster<other_lib::MyType> : public other_lib::my_caster {};
134
- } // namespace detail
135
- } // namespace PYBIND11_NAMESPACE
136
-
137
- // This simply is required to compile
138
- namespace ADL_issue {
139
- template <typename OutStringType = std::string, typename... Args>
140
- OutStringType concat(Args &&...) {
141
- return OutStringType();
142
- }
143
-
144
- struct test {};
145
- } // namespace ADL_issue
146
-
147
- TEST_SUBMODULE(custom_type_casters, m) {
148
- // test_custom_type_casters
149
-
150
- // test_noconvert_args
151
- //
152
- // Test converting. The ArgAlwaysConverts is just there to make the first no-conversion pass
153
- // fail so that our call always ends up happening via the second dispatch (the one that allows
154
- // some conversion).
155
- class ArgInspector {
156
- public:
157
- ArgInspector1 f(ArgInspector1 a, ArgAlwaysConverts) { return a; }
158
- std::string g(const ArgInspector1 &a,
159
- const ArgInspector1 &b,
160
- int c,
161
- ArgInspector2 *d,
162
- ArgAlwaysConverts) {
163
- return a.arg + "\n" + b.arg + "\n" + std::to_string(c) + "\n" + d->arg;
164
- }
165
- static ArgInspector2 h(ArgInspector2 a, ArgAlwaysConverts) { return a; }
166
- };
167
- // [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
168
- py::class_<ArgInspector>(m, "ArgInspector")
169
- .def(py::init<>())
170
- .def("f", &ArgInspector::f, py::arg(), py::arg() = ArgAlwaysConverts())
171
- .def("g",
172
- &ArgInspector::g,
173
- "a"_a.noconvert(),
174
- "b"_a,
175
- "c"_a.noconvert() = 13,
176
- "d"_a = ArgInspector2(),
177
- py::arg() = ArgAlwaysConverts())
178
- .def_static("h", &ArgInspector::h, py::arg{}.noconvert(), py::arg() = ArgAlwaysConverts());
179
- m.def(
180
- "arg_inspect_func",
181
- [](const ArgInspector2 &a, const ArgInspector1 &b, ArgAlwaysConverts) {
182
- return a.arg + "\n" + b.arg;
183
- },
184
- py::arg{}.noconvert(false),
185
- py::arg_v(nullptr, ArgInspector1()).noconvert(true),
186
- py::arg() = ArgAlwaysConverts());
187
-
188
- m.def(
189
- "floats_preferred", [](double f) { return 0.5 * f; }, "f"_a);
190
- m.def(
191
- "floats_only", [](double f) { return 0.5 * f; }, "f"_a.noconvert());
192
- m.def(
193
- "ints_preferred", [](int i) { return i / 2; }, "i"_a);
194
- m.def(
195
- "ints_only", [](int i) { return i / 2; }, "i"_a.noconvert());
196
-
197
- // test_custom_caster_destruction
198
- // Test that `take_ownership` works on types with a custom type caster when given a pointer
199
-
200
- // default policy: don't take ownership:
201
- m.def("custom_caster_no_destroy", []() {
202
- static auto *dt = new DestructionTester();
203
- return dt;
204
- });
205
-
206
- m.def(
207
- "custom_caster_destroy",
208
- []() { return new DestructionTester(); },
209
- py::return_value_policy::take_ownership); // Takes ownership: destroy when finished
210
- m.def(
211
- "custom_caster_destroy_const",
212
- []() -> const DestructionTester * { return new DestructionTester(); },
213
- py::return_value_policy::take_ownership); // Likewise (const doesn't inhibit destruction)
214
- m.def("destruction_tester_cstats",
215
- &ConstructorStats::get<DestructionTester>,
216
- py::return_value_policy::reference);
217
-
218
- m.def("other_lib_type", [](other_lib::MyType x) { return x; });
219
-
220
- m.def("_adl_issue", [](const ADL_issue::test &) {});
221
- }
 
1
+ /*
2
+ tests/test_custom_type_casters.cpp -- tests type_caster<T>
3
+
4
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include "constructor_stats.h"
11
+ #include "pybind11_tests.h"
12
+
13
+ // py::arg/py::arg_v testing: these arguments just record their argument when invoked
14
+ class ArgInspector1 {
15
+ public:
16
+ std::string arg = "(default arg inspector 1)";
17
+ };
18
+ class ArgInspector2 {
19
+ public:
20
+ std::string arg = "(default arg inspector 2)";
21
+ };
22
+ class ArgAlwaysConverts {};
23
+
24
+ namespace PYBIND11_NAMESPACE {
25
+ namespace detail {
26
+ template <>
27
+ struct type_caster<ArgInspector1> {
28
+ public:
29
+ // Classic
30
+ #ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
31
+ PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
32
+ #else
33
+ PYBIND11_TYPE_CASTER(ArgInspector1, const_name("ArgInspector1"));
34
+ #endif
35
+
36
+ bool load(handle src, bool convert) {
37
+ value.arg = "loading ArgInspector1 argument " + std::string(convert ? "WITH" : "WITHOUT")
38
+ + " conversion allowed. "
39
+ "Argument value = "
40
+ + (std::string) str(src);
41
+ return true;
42
+ }
43
+
44
+ static handle cast(const ArgInspector1 &src, return_value_policy, handle) {
45
+ return str(src.arg).release();
46
+ }
47
+ };
48
+ template <>
49
+ struct type_caster<ArgInspector2> {
50
+ public:
51
+ PYBIND11_TYPE_CASTER(ArgInspector2, const_name("ArgInspector2"));
52
+
53
+ bool load(handle src, bool convert) {
54
+ value.arg = "loading ArgInspector2 argument " + std::string(convert ? "WITH" : "WITHOUT")
55
+ + " conversion allowed. "
56
+ "Argument value = "
57
+ + (std::string) str(src);
58
+ return true;
59
+ }
60
+
61
+ static handle cast(const ArgInspector2 &src, return_value_policy, handle) {
62
+ return str(src.arg).release();
63
+ }
64
+ };
65
+ template <>
66
+ struct type_caster<ArgAlwaysConverts> {
67
+ public:
68
+ PYBIND11_TYPE_CASTER(ArgAlwaysConverts, const_name("ArgAlwaysConverts"));
69
+
70
+ bool load(handle, bool convert) { return convert; }
71
+
72
+ static handle cast(const ArgAlwaysConverts &, return_value_policy, handle) {
73
+ return py::none().release();
74
+ }
75
+ };
76
+ } // namespace detail
77
+ } // namespace PYBIND11_NAMESPACE
78
+
79
+ // test_custom_caster_destruction
80
+ class DestructionTester {
81
+ public:
82
+ DestructionTester() { print_default_created(this); }
83
+ ~DestructionTester() { print_destroyed(this); }
84
+ DestructionTester(const DestructionTester &) { print_copy_created(this); }
85
+ DestructionTester(DestructionTester &&) noexcept { print_move_created(this); }
86
+ DestructionTester &operator=(const DestructionTester &) {
87
+ print_copy_assigned(this);
88
+ return *this;
89
+ }
90
+ DestructionTester &operator=(DestructionTester &&) noexcept {
91
+ print_move_assigned(this);
92
+ return *this;
93
+ }
94
+ };
95
+ namespace PYBIND11_NAMESPACE {
96
+ namespace detail {
97
+ template <>
98
+ struct type_caster<DestructionTester> {
99
+ PYBIND11_TYPE_CASTER(DestructionTester, const_name("DestructionTester"));
100
+ bool load(handle, bool) { return true; }
101
+
102
+ static handle cast(const DestructionTester &, return_value_policy, handle) {
103
+ return py::bool_(true).release();
104
+ }
105
+ };
106
+ } // namespace detail
107
+ } // namespace PYBIND11_NAMESPACE
108
+
109
+ // Define type caster outside of `pybind11::detail` and then alias it.
110
+ namespace other_lib {
111
+ struct MyType {};
112
+ // Corrupt `py` shorthand alias for surrounding context.
113
+ namespace py {}
114
+ // Corrupt unqualified relative `pybind11` namespace.
115
+ namespace PYBIND11_NAMESPACE {}
116
+ // Correct alias.
117
+ namespace py_ = ::pybind11;
118
+ // Define caster. This is effectively no-op, we only ensure it compiles and we
119
+ // don't have any symbol collision when using macro mixin.
120
+ struct my_caster {
121
+ PYBIND11_TYPE_CASTER(MyType, py_::detail::const_name("MyType"));
122
+ bool load(py_::handle, bool) { return true; }
123
+
124
+ static py_::handle cast(const MyType &, py_::return_value_policy, py_::handle) {
125
+ return py_::bool_(true).release();
126
+ }
127
+ };
128
+ } // namespace other_lib
129
+ // Effectively "alias" it into correct namespace (via inheritance).
130
+ namespace PYBIND11_NAMESPACE {
131
+ namespace detail {
132
+ template <>
133
+ struct type_caster<other_lib::MyType> : public other_lib::my_caster {};
134
+ } // namespace detail
135
+ } // namespace PYBIND11_NAMESPACE
136
+
137
+ // This simply is required to compile
138
+ namespace ADL_issue {
139
+ template <typename OutStringType = std::string, typename... Args>
140
+ OutStringType concat(Args &&...) {
141
+ return OutStringType();
142
+ }
143
+
144
+ struct test {};
145
+ } // namespace ADL_issue
146
+
147
+ TEST_SUBMODULE(custom_type_casters, m) {
148
+ // test_custom_type_casters
149
+
150
+ // test_noconvert_args
151
+ //
152
+ // Test converting. The ArgAlwaysConverts is just there to make the first no-conversion pass
153
+ // fail so that our call always ends up happening via the second dispatch (the one that allows
154
+ // some conversion).
155
+ class ArgInspector {
156
+ public:
157
+ ArgInspector1 f(ArgInspector1 a, ArgAlwaysConverts) { return a; }
158
+ std::string g(const ArgInspector1 &a,
159
+ const ArgInspector1 &b,
160
+ int c,
161
+ ArgInspector2 *d,
162
+ ArgAlwaysConverts) {
163
+ return a.arg + "\n" + b.arg + "\n" + std::to_string(c) + "\n" + d->arg;
164
+ }
165
+ static ArgInspector2 h(ArgInspector2 a, ArgAlwaysConverts) { return a; }
166
+ };
167
+ // [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
168
+ py::class_<ArgInspector>(m, "ArgInspector")
169
+ .def(py::init<>())
170
+ .def("f", &ArgInspector::f, py::arg(), py::arg() = ArgAlwaysConverts())
171
+ .def("g",
172
+ &ArgInspector::g,
173
+ "a"_a.noconvert(),
174
+ "b"_a,
175
+ "c"_a.noconvert() = 13,
176
+ "d"_a = ArgInspector2(),
177
+ py::arg() = ArgAlwaysConverts())
178
+ .def_static("h", &ArgInspector::h, py::arg{}.noconvert(), py::arg() = ArgAlwaysConverts());
179
+ m.def(
180
+ "arg_inspect_func",
181
+ [](const ArgInspector2 &a, const ArgInspector1 &b, ArgAlwaysConverts) {
182
+ return a.arg + "\n" + b.arg;
183
+ },
184
+ py::arg{}.noconvert(false),
185
+ py::arg_v(nullptr, ArgInspector1()).noconvert(true),
186
+ py::arg() = ArgAlwaysConverts());
187
+
188
+ m.def(
189
+ "floats_preferred", [](double f) { return 0.5 * f; }, "f"_a);
190
+ m.def(
191
+ "floats_only", [](double f) { return 0.5 * f; }, "f"_a.noconvert());
192
+ m.def(
193
+ "ints_preferred", [](int i) { return i / 2; }, "i"_a);
194
+ m.def(
195
+ "ints_only", [](int i) { return i / 2; }, "i"_a.noconvert());
196
+
197
+ // test_custom_caster_destruction
198
+ // Test that `take_ownership` works on types with a custom type caster when given a pointer
199
+
200
+ // default policy: don't take ownership:
201
+ m.def("custom_caster_no_destroy", []() {
202
+ static auto *dt = new DestructionTester();
203
+ return dt;
204
+ });
205
+
206
+ m.def(
207
+ "custom_caster_destroy",
208
+ []() { return new DestructionTester(); },
209
+ py::return_value_policy::take_ownership); // Takes ownership: destroy when finished
210
+ m.def(
211
+ "custom_caster_destroy_const",
212
+ []() -> const DestructionTester * { return new DestructionTester(); },
213
+ py::return_value_policy::take_ownership); // Likewise (const doesn't inhibit destruction)
214
+ m.def("destruction_tester_cstats",
215
+ &ConstructorStats::get<DestructionTester>,
216
+ py::return_value_policy::reference);
217
+
218
+ m.def("other_lib_type", [](other_lib::MyType x) { return x; });
219
+
220
+ m.def("_adl_issue", [](const ADL_issue::test &) {});
221
+ }
third_party/CityFlow/extern/pybind11/tests/test_custom_type_casters.py CHANGED
@@ -1,122 +1,122 @@
1
- import pytest
2
-
3
- from pybind11_tests import custom_type_casters as m
4
-
5
-
6
- def test_noconvert_args(msg):
7
- a = m.ArgInspector()
8
- assert (
9
- msg(a.f("hi"))
10
- == """
11
- loading ArgInspector1 argument WITH conversion allowed. Argument value = hi
12
- """
13
- )
14
- assert (
15
- msg(a.g("this is a", "this is b"))
16
- == """
17
- loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
18
- loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
19
- 13
20
- loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
21
- """
22
- )
23
- assert (
24
- msg(a.g("this is a", "this is b", 42))
25
- == """
26
- loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
27
- loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
28
- 42
29
- loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
30
- """
31
- )
32
- assert (
33
- msg(a.g("this is a", "this is b", 42, "this is d"))
34
- == """
35
- loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
36
- loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
37
- 42
38
- loading ArgInspector2 argument WITH conversion allowed. Argument value = this is d
39
- """
40
- )
41
- assert (
42
- a.h("arg 1")
43
- == "loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1"
44
- )
45
- assert (
46
- msg(m.arg_inspect_func("A1", "A2"))
47
- == """
48
- loading ArgInspector2 argument WITH conversion allowed. Argument value = A1
49
- loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = A2
50
- """
51
- )
52
-
53
- assert m.floats_preferred(4) == 2.0
54
- assert m.floats_only(4.0) == 2.0
55
- with pytest.raises(TypeError) as excinfo:
56
- m.floats_only(4)
57
- assert (
58
- msg(excinfo.value)
59
- == """
60
- floats_only(): incompatible function arguments. The following argument types are supported:
61
- 1. (f: float) -> float
62
-
63
- Invoked with: 4
64
- """
65
- )
66
-
67
- assert m.ints_preferred(4) == 2
68
- assert m.ints_preferred(True) == 0
69
- with pytest.raises(TypeError) as excinfo:
70
- m.ints_preferred(4.0)
71
- assert (
72
- msg(excinfo.value)
73
- == """
74
- ints_preferred(): incompatible function arguments. The following argument types are supported:
75
- 1. (i: int) -> int
76
-
77
- Invoked with: 4.0
78
- """
79
- )
80
-
81
- assert m.ints_only(4) == 2
82
- with pytest.raises(TypeError) as excinfo:
83
- m.ints_only(4.0)
84
- assert (
85
- msg(excinfo.value)
86
- == """
87
- ints_only(): incompatible function arguments. The following argument types are supported:
88
- 1. (i: int) -> int
89
-
90
- Invoked with: 4.0
91
- """
92
- )
93
-
94
-
95
- def test_custom_caster_destruction():
96
- """Tests that returning a pointer to a type that gets converted with a custom type caster gets
97
- destroyed when the function has py::return_value_policy::take_ownership policy applied.
98
- """
99
-
100
- cstats = m.destruction_tester_cstats()
101
- # This one *doesn't* have take_ownership: the pointer should be used but not destroyed:
102
- z = m.custom_caster_no_destroy()
103
- assert cstats.alive() == 1
104
- assert cstats.default_constructions == 1
105
- assert z
106
-
107
- # take_ownership applied: this constructs a new object, casts it, then destroys it:
108
- z = m.custom_caster_destroy()
109
- assert z
110
- assert cstats.default_constructions == 2
111
-
112
- # Same, but with a const pointer return (which should *not* inhibit destruction):
113
- z = m.custom_caster_destroy_const()
114
- assert z
115
- assert cstats.default_constructions == 3
116
-
117
- # Make sure we still only have the original object (from ..._no_destroy()) alive:
118
- assert cstats.alive() == 1
119
-
120
-
121
- def test_custom_caster_other_lib():
122
- assert m.other_lib_type(True)
 
1
+ import pytest
2
+
3
+ from pybind11_tests import custom_type_casters as m
4
+
5
+
6
+ def test_noconvert_args(msg):
7
+ a = m.ArgInspector()
8
+ assert (
9
+ msg(a.f("hi"))
10
+ == """
11
+ loading ArgInspector1 argument WITH conversion allowed. Argument value = hi
12
+ """
13
+ )
14
+ assert (
15
+ msg(a.g("this is a", "this is b"))
16
+ == """
17
+ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
18
+ loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
19
+ 13
20
+ loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
21
+ """
22
+ )
23
+ assert (
24
+ msg(a.g("this is a", "this is b", 42))
25
+ == """
26
+ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
27
+ loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
28
+ 42
29
+ loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
30
+ """
31
+ )
32
+ assert (
33
+ msg(a.g("this is a", "this is b", 42, "this is d"))
34
+ == """
35
+ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
36
+ loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
37
+ 42
38
+ loading ArgInspector2 argument WITH conversion allowed. Argument value = this is d
39
+ """
40
+ )
41
+ assert (
42
+ a.h("arg 1")
43
+ == "loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1"
44
+ )
45
+ assert (
46
+ msg(m.arg_inspect_func("A1", "A2"))
47
+ == """
48
+ loading ArgInspector2 argument WITH conversion allowed. Argument value = A1
49
+ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = A2
50
+ """
51
+ )
52
+
53
+ assert m.floats_preferred(4) == 2.0
54
+ assert m.floats_only(4.0) == 2.0
55
+ with pytest.raises(TypeError) as excinfo:
56
+ m.floats_only(4)
57
+ assert (
58
+ msg(excinfo.value)
59
+ == """
60
+ floats_only(): incompatible function arguments. The following argument types are supported:
61
+ 1. (f: float) -> float
62
+
63
+ Invoked with: 4
64
+ """
65
+ )
66
+
67
+ assert m.ints_preferred(4) == 2
68
+ assert m.ints_preferred(True) == 0
69
+ with pytest.raises(TypeError) as excinfo:
70
+ m.ints_preferred(4.0)
71
+ assert (
72
+ msg(excinfo.value)
73
+ == """
74
+ ints_preferred(): incompatible function arguments. The following argument types are supported:
75
+ 1. (i: int) -> int
76
+
77
+ Invoked with: 4.0
78
+ """
79
+ )
80
+
81
+ assert m.ints_only(4) == 2
82
+ with pytest.raises(TypeError) as excinfo:
83
+ m.ints_only(4.0)
84
+ assert (
85
+ msg(excinfo.value)
86
+ == """
87
+ ints_only(): incompatible function arguments. The following argument types are supported:
88
+ 1. (i: int) -> int
89
+
90
+ Invoked with: 4.0
91
+ """
92
+ )
93
+
94
+
95
+ def test_custom_caster_destruction():
96
+ """Tests that returning a pointer to a type that gets converted with a custom type caster gets
97
+ destroyed when the function has py::return_value_policy::take_ownership policy applied.
98
+ """
99
+
100
+ cstats = m.destruction_tester_cstats()
101
+ # This one *doesn't* have take_ownership: the pointer should be used but not destroyed:
102
+ z = m.custom_caster_no_destroy()
103
+ assert cstats.alive() == 1
104
+ assert cstats.default_constructions == 1
105
+ assert z
106
+
107
+ # take_ownership applied: this constructs a new object, casts it, then destroys it:
108
+ z = m.custom_caster_destroy()
109
+ assert z
110
+ assert cstats.default_constructions == 2
111
+
112
+ # Same, but with a const pointer return (which should *not* inhibit destruction):
113
+ z = m.custom_caster_destroy_const()
114
+ assert z
115
+ assert cstats.default_constructions == 3
116
+
117
+ # Make sure we still only have the original object (from ..._no_destroy()) alive:
118
+ assert cstats.alive() == 1
119
+
120
+
121
+ def test_custom_caster_other_lib():
122
+ assert m.other_lib_type(True)
third_party/CityFlow/extern/pybind11/tests/test_custom_type_setup.cpp CHANGED
@@ -1,41 +1,41 @@
1
- /*
2
- tests/test_custom_type_setup.cpp -- Tests `pybind11::custom_type_setup`
3
-
4
- Copyright (c) Google LLC
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include <pybind11/pybind11.h>
11
-
12
- #include "pybind11_tests.h"
13
-
14
- namespace py = pybind11;
15
-
16
- namespace {
17
-
18
- struct OwnsPythonObjects {
19
- py::object value = py::none();
20
- };
21
- } // namespace
22
-
23
- TEST_SUBMODULE(custom_type_setup, m) {
24
- py::class_<OwnsPythonObjects> cls(
25
- m, "OwnsPythonObjects", py::custom_type_setup([](PyHeapTypeObject *heap_type) {
26
- auto *type = &heap_type->ht_type;
27
- type->tp_flags |= Py_TPFLAGS_HAVE_GC;
28
- type->tp_traverse = [](PyObject *self_base, visitproc visit, void *arg) {
29
- auto &self = py::cast<OwnsPythonObjects &>(py::handle(self_base));
30
- Py_VISIT(self.value.ptr());
31
- return 0;
32
- };
33
- type->tp_clear = [](PyObject *self_base) {
34
- auto &self = py::cast<OwnsPythonObjects &>(py::handle(self_base));
35
- self.value = py::none();
36
- return 0;
37
- };
38
- }));
39
- cls.def(py::init<>());
40
- cls.def_readwrite("value", &OwnsPythonObjects::value);
41
- }
 
1
+ /*
2
+ tests/test_custom_type_setup.cpp -- Tests `pybind11::custom_type_setup`
3
+
4
+ Copyright (c) Google LLC
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include <pybind11/pybind11.h>
11
+
12
+ #include "pybind11_tests.h"
13
+
14
+ namespace py = pybind11;
15
+
16
+ namespace {
17
+
18
+ struct OwnsPythonObjects {
19
+ py::object value = py::none();
20
+ };
21
+ } // namespace
22
+
23
+ TEST_SUBMODULE(custom_type_setup, m) {
24
+ py::class_<OwnsPythonObjects> cls(
25
+ m, "OwnsPythonObjects", py::custom_type_setup([](PyHeapTypeObject *heap_type) {
26
+ auto *type = &heap_type->ht_type;
27
+ type->tp_flags |= Py_TPFLAGS_HAVE_GC;
28
+ type->tp_traverse = [](PyObject *self_base, visitproc visit, void *arg) {
29
+ auto &self = py::cast<OwnsPythonObjects &>(py::handle(self_base));
30
+ Py_VISIT(self.value.ptr());
31
+ return 0;
32
+ };
33
+ type->tp_clear = [](PyObject *self_base) {
34
+ auto &self = py::cast<OwnsPythonObjects &>(py::handle(self_base));
35
+ self.value = py::none();
36
+ return 0;
37
+ };
38
+ }));
39
+ cls.def(py::init<>());
40
+ cls.def_readwrite("value", &OwnsPythonObjects::value);
41
+ }
third_party/CityFlow/extern/pybind11/tests/test_custom_type_setup.py CHANGED
@@ -1,48 +1,48 @@
1
- import gc
2
- import weakref
3
-
4
- import pytest
5
-
6
- import env # noqa: F401
7
- from pybind11_tests import custom_type_setup as m
8
-
9
-
10
- @pytest.fixture()
11
- def gc_tester():
12
- """Tests that an object is garbage collected.
13
-
14
- Assumes that any unreferenced objects are fully collected after calling
15
- `gc.collect()`. That is true on CPython, but does not appear to reliably
16
- hold on PyPy.
17
- """
18
-
19
- weak_refs = []
20
-
21
- def add_ref(obj):
22
- # PyPy does not support `gc.is_tracked`.
23
- if hasattr(gc, "is_tracked"):
24
- assert gc.is_tracked(obj)
25
- weak_refs.append(weakref.ref(obj))
26
-
27
- yield add_ref
28
-
29
- gc.collect()
30
- for ref in weak_refs:
31
- assert ref() is None
32
-
33
-
34
- # PyPy does not seem to reliably garbage collect.
35
- @pytest.mark.skipif("env.PYPY")
36
- def test_self_cycle(gc_tester):
37
- obj = m.OwnsPythonObjects()
38
- obj.value = obj
39
- gc_tester(obj)
40
-
41
-
42
- # PyPy does not seem to reliably garbage collect.
43
- @pytest.mark.skipif("env.PYPY")
44
- def test_indirect_cycle(gc_tester):
45
- obj = m.OwnsPythonObjects()
46
- obj_list = [obj]
47
- obj.value = obj_list
48
- gc_tester(obj)
 
1
+ import gc
2
+ import weakref
3
+
4
+ import pytest
5
+
6
+ import env # noqa: F401
7
+ from pybind11_tests import custom_type_setup as m
8
+
9
+
10
+ @pytest.fixture()
11
+ def gc_tester():
12
+ """Tests that an object is garbage collected.
13
+
14
+ Assumes that any unreferenced objects are fully collected after calling
15
+ `gc.collect()`. That is true on CPython, but does not appear to reliably
16
+ hold on PyPy.
17
+ """
18
+
19
+ weak_refs = []
20
+
21
+ def add_ref(obj):
22
+ # PyPy does not support `gc.is_tracked`.
23
+ if hasattr(gc, "is_tracked"):
24
+ assert gc.is_tracked(obj)
25
+ weak_refs.append(weakref.ref(obj))
26
+
27
+ yield add_ref
28
+
29
+ gc.collect()
30
+ for ref in weak_refs:
31
+ assert ref() is None
32
+
33
+
34
+ # PyPy does not seem to reliably garbage collect.
35
+ @pytest.mark.skipif("env.PYPY")
36
+ def test_self_cycle(gc_tester):
37
+ obj = m.OwnsPythonObjects()
38
+ obj.value = obj
39
+ gc_tester(obj)
40
+
41
+
42
+ # PyPy does not seem to reliably garbage collect.
43
+ @pytest.mark.skipif("env.PYPY")
44
+ def test_indirect_cycle(gc_tester):
45
+ obj = m.OwnsPythonObjects()
46
+ obj_list = [obj]
47
+ obj.value = obj_list
48
+ gc_tester(obj)
third_party/CityFlow/extern/pybind11/tests/test_docstring_options.cpp CHANGED
@@ -1,141 +1,141 @@
1
- /*
2
- tests/test_docstring_options.cpp -- generation of docstrings and signatures
3
-
4
- Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include "pybind11_tests.h"
11
-
12
- TEST_SUBMODULE(docstring_options, m) {
13
- // test_docstring_options
14
- {
15
- py::options options;
16
- options.disable_function_signatures();
17
-
18
- m.def(
19
- "test_function1", [](int, int) {}, py::arg("a"), py::arg("b"));
20
- m.def(
21
- "test_function2", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
22
-
23
- m.def(
24
- "test_overloaded1", [](int) {}, py::arg("i"), "Overload docstring");
25
- m.def(
26
- "test_overloaded1", [](double) {}, py::arg("d"));
27
-
28
- m.def(
29
- "test_overloaded2", [](int) {}, py::arg("i"), "overload docstring 1");
30
- m.def(
31
- "test_overloaded2", [](double) {}, py::arg("d"), "overload docstring 2");
32
-
33
- m.def(
34
- "test_overloaded3", [](int) {}, py::arg("i"));
35
- m.def(
36
- "test_overloaded3", [](double) {}, py::arg("d"), "Overload docstr");
37
-
38
- options.enable_function_signatures();
39
-
40
- m.def(
41
- "test_function3", [](int, int) {}, py::arg("a"), py::arg("b"));
42
- m.def(
43
- "test_function4", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
44
-
45
- options.disable_function_signatures().disable_user_defined_docstrings();
46
-
47
- m.def(
48
- "test_function5", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
49
-
50
- {
51
- py::options nested_options;
52
- nested_options.enable_user_defined_docstrings();
53
- m.def(
54
- "test_function6",
55
- [](int, int) {},
56
- py::arg("a"),
57
- py::arg("b"),
58
- "A custom docstring");
59
- }
60
- }
61
-
62
- m.def(
63
- "test_function7", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
64
-
65
- {
66
- py::options options;
67
- options.disable_user_defined_docstrings();
68
- options.disable_function_signatures();
69
-
70
- m.def("test_function8", []() {});
71
- }
72
-
73
- {
74
- py::options options;
75
- options.disable_user_defined_docstrings();
76
-
77
- struct DocstringTestFoo {
78
- int value;
79
- void setValue(int v) { value = v; }
80
- int getValue() const { return value; }
81
- };
82
- py::class_<DocstringTestFoo>(m, "DocstringTestFoo", "This is a class docstring")
83
- .def_property("value_prop",
84
- &DocstringTestFoo::getValue,
85
- &DocstringTestFoo::setValue,
86
- "This is a property docstring");
87
- }
88
-
89
- {
90
- enum class DocstringTestEnum1 { Member1, Member2 };
91
-
92
- py::enum_<DocstringTestEnum1>(m, "DocstringTestEnum1", "Enum docstring")
93
- .value("Member1", DocstringTestEnum1::Member1)
94
- .value("Member2", DocstringTestEnum1::Member2);
95
- }
96
-
97
- {
98
- py::options options;
99
- options.enable_enum_members_docstring();
100
-
101
- enum class DocstringTestEnum2 { Member1, Member2 };
102
-
103
- py::enum_<DocstringTestEnum2>(m, "DocstringTestEnum2", "Enum docstring")
104
- .value("Member1", DocstringTestEnum2::Member1)
105
- .value("Member2", DocstringTestEnum2::Member2);
106
- }
107
-
108
- {
109
- py::options options;
110
- options.disable_enum_members_docstring();
111
-
112
- enum class DocstringTestEnum3 { Member1, Member2 };
113
-
114
- py::enum_<DocstringTestEnum3>(m, "DocstringTestEnum3", "Enum docstring")
115
- .value("Member1", DocstringTestEnum3::Member1)
116
- .value("Member2", DocstringTestEnum3::Member2);
117
- }
118
-
119
- {
120
- py::options options;
121
- options.disable_user_defined_docstrings();
122
-
123
- enum class DocstringTestEnum4 { Member1, Member2 };
124
-
125
- py::enum_<DocstringTestEnum4>(m, "DocstringTestEnum4", "Enum docstring")
126
- .value("Member1", DocstringTestEnum4::Member1)
127
- .value("Member2", DocstringTestEnum4::Member2);
128
- }
129
-
130
- {
131
- py::options options;
132
- options.disable_user_defined_docstrings();
133
- options.disable_enum_members_docstring();
134
-
135
- enum class DocstringTestEnum5 { Member1, Member2 };
136
-
137
- py::enum_<DocstringTestEnum5>(m, "DocstringTestEnum5", "Enum docstring")
138
- .value("Member1", DocstringTestEnum5::Member1)
139
- .value("Member2", DocstringTestEnum5::Member2);
140
- }
141
- }
 
1
+ /*
2
+ tests/test_docstring_options.cpp -- generation of docstrings and signatures
3
+
4
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include "pybind11_tests.h"
11
+
12
+ TEST_SUBMODULE(docstring_options, m) {
13
+ // test_docstring_options
14
+ {
15
+ py::options options;
16
+ options.disable_function_signatures();
17
+
18
+ m.def(
19
+ "test_function1", [](int, int) {}, py::arg("a"), py::arg("b"));
20
+ m.def(
21
+ "test_function2", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
22
+
23
+ m.def(
24
+ "test_overloaded1", [](int) {}, py::arg("i"), "Overload docstring");
25
+ m.def(
26
+ "test_overloaded1", [](double) {}, py::arg("d"));
27
+
28
+ m.def(
29
+ "test_overloaded2", [](int) {}, py::arg("i"), "overload docstring 1");
30
+ m.def(
31
+ "test_overloaded2", [](double) {}, py::arg("d"), "overload docstring 2");
32
+
33
+ m.def(
34
+ "test_overloaded3", [](int) {}, py::arg("i"));
35
+ m.def(
36
+ "test_overloaded3", [](double) {}, py::arg("d"), "Overload docstr");
37
+
38
+ options.enable_function_signatures();
39
+
40
+ m.def(
41
+ "test_function3", [](int, int) {}, py::arg("a"), py::arg("b"));
42
+ m.def(
43
+ "test_function4", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
44
+
45
+ options.disable_function_signatures().disable_user_defined_docstrings();
46
+
47
+ m.def(
48
+ "test_function5", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
49
+
50
+ {
51
+ py::options nested_options;
52
+ nested_options.enable_user_defined_docstrings();
53
+ m.def(
54
+ "test_function6",
55
+ [](int, int) {},
56
+ py::arg("a"),
57
+ py::arg("b"),
58
+ "A custom docstring");
59
+ }
60
+ }
61
+
62
+ m.def(
63
+ "test_function7", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
64
+
65
+ {
66
+ py::options options;
67
+ options.disable_user_defined_docstrings();
68
+ options.disable_function_signatures();
69
+
70
+ m.def("test_function8", []() {});
71
+ }
72
+
73
+ {
74
+ py::options options;
75
+ options.disable_user_defined_docstrings();
76
+
77
+ struct DocstringTestFoo {
78
+ int value;
79
+ void setValue(int v) { value = v; }
80
+ int getValue() const { return value; }
81
+ };
82
+ py::class_<DocstringTestFoo>(m, "DocstringTestFoo", "This is a class docstring")
83
+ .def_property("value_prop",
84
+ &DocstringTestFoo::getValue,
85
+ &DocstringTestFoo::setValue,
86
+ "This is a property docstring");
87
+ }
88
+
89
+ {
90
+ enum class DocstringTestEnum1 { Member1, Member2 };
91
+
92
+ py::enum_<DocstringTestEnum1>(m, "DocstringTestEnum1", "Enum docstring")
93
+ .value("Member1", DocstringTestEnum1::Member1)
94
+ .value("Member2", DocstringTestEnum1::Member2);
95
+ }
96
+
97
+ {
98
+ py::options options;
99
+ options.enable_enum_members_docstring();
100
+
101
+ enum class DocstringTestEnum2 { Member1, Member2 };
102
+
103
+ py::enum_<DocstringTestEnum2>(m, "DocstringTestEnum2", "Enum docstring")
104
+ .value("Member1", DocstringTestEnum2::Member1)
105
+ .value("Member2", DocstringTestEnum2::Member2);
106
+ }
107
+
108
+ {
109
+ py::options options;
110
+ options.disable_enum_members_docstring();
111
+
112
+ enum class DocstringTestEnum3 { Member1, Member2 };
113
+
114
+ py::enum_<DocstringTestEnum3>(m, "DocstringTestEnum3", "Enum docstring")
115
+ .value("Member1", DocstringTestEnum3::Member1)
116
+ .value("Member2", DocstringTestEnum3::Member2);
117
+ }
118
+
119
+ {
120
+ py::options options;
121
+ options.disable_user_defined_docstrings();
122
+
123
+ enum class DocstringTestEnum4 { Member1, Member2 };
124
+
125
+ py::enum_<DocstringTestEnum4>(m, "DocstringTestEnum4", "Enum docstring")
126
+ .value("Member1", DocstringTestEnum4::Member1)
127
+ .value("Member2", DocstringTestEnum4::Member2);
128
+ }
129
+
130
+ {
131
+ py::options options;
132
+ options.disable_user_defined_docstrings();
133
+ options.disable_enum_members_docstring();
134
+
135
+ enum class DocstringTestEnum5 { Member1, Member2 };
136
+
137
+ py::enum_<DocstringTestEnum5>(m, "DocstringTestEnum5", "Enum docstring")
138
+ .value("Member1", DocstringTestEnum5::Member1)
139
+ .value("Member2", DocstringTestEnum5::Member2);
140
+ }
141
+ }
third_party/CityFlow/extern/pybind11/tests/test_docstring_options.py CHANGED
@@ -1,64 +1,64 @@
1
- from pybind11_tests import docstring_options as m
2
-
3
-
4
- def test_docstring_options():
5
- # options.disable_function_signatures()
6
- assert not m.test_function1.__doc__
7
-
8
- assert m.test_function2.__doc__ == "A custom docstring"
9
-
10
- # docstring specified on just the first overload definition:
11
- assert m.test_overloaded1.__doc__ == "Overload docstring"
12
-
13
- # docstring on both overloads:
14
- assert m.test_overloaded2.__doc__ == "overload docstring 1\noverload docstring 2"
15
-
16
- # docstring on only second overload:
17
- assert m.test_overloaded3.__doc__ == "Overload docstr"
18
-
19
- # options.enable_function_signatures()
20
- assert m.test_function3.__doc__.startswith("test_function3(a: int, b: int) -> None")
21
-
22
- assert m.test_function4.__doc__.startswith("test_function4(a: int, b: int) -> None")
23
- assert m.test_function4.__doc__.endswith("A custom docstring\n")
24
-
25
- # options.disable_function_signatures()
26
- # options.disable_user_defined_docstrings()
27
- assert not m.test_function5.__doc__
28
-
29
- # nested options.enable_user_defined_docstrings()
30
- assert m.test_function6.__doc__ == "A custom docstring"
31
-
32
- # RAII destructor
33
- assert m.test_function7.__doc__.startswith("test_function7(a: int, b: int) -> None")
34
- assert m.test_function7.__doc__.endswith("A custom docstring\n")
35
-
36
- # when all options are disabled, no docstring (instead of an empty one) should be generated
37
- assert m.test_function8.__doc__ is None
38
-
39
- # Suppression of user-defined docstrings for non-function objects
40
- assert not m.DocstringTestFoo.__doc__
41
- assert not m.DocstringTestFoo.value_prop.__doc__
42
-
43
- # Check existig behaviour of enum docstings
44
- assert (
45
- m.DocstringTestEnum1.__doc__
46
- == "Enum docstring\n\nMembers:\n\n Member1\n\n Member2"
47
- )
48
-
49
- # options.enable_enum_members_docstring()
50
- assert (
51
- m.DocstringTestEnum2.__doc__
52
- == "Enum docstring\n\nMembers:\n\n Member1\n\n Member2"
53
- )
54
-
55
- # options.disable_enum_members_docstring()
56
- assert m.DocstringTestEnum3.__doc__ == "Enum docstring"
57
-
58
- # options.disable_user_defined_docstrings()
59
- assert m.DocstringTestEnum4.__doc__ == "Members:\n\n Member1\n\n Member2"
60
-
61
- # options.disable_user_defined_docstrings()
62
- # options.disable_enum_members_docstring()
63
- # When all options are disabled, no docstring (instead of an empty one) should be generated
64
- assert m.DocstringTestEnum5.__doc__ is None
 
1
+ from pybind11_tests import docstring_options as m
2
+
3
+
4
+ def test_docstring_options():
5
+ # options.disable_function_signatures()
6
+ assert not m.test_function1.__doc__
7
+
8
+ assert m.test_function2.__doc__ == "A custom docstring"
9
+
10
+ # docstring specified on just the first overload definition:
11
+ assert m.test_overloaded1.__doc__ == "Overload docstring"
12
+
13
+ # docstring on both overloads:
14
+ assert m.test_overloaded2.__doc__ == "overload docstring 1\noverload docstring 2"
15
+
16
+ # docstring on only second overload:
17
+ assert m.test_overloaded3.__doc__ == "Overload docstr"
18
+
19
+ # options.enable_function_signatures()
20
+ assert m.test_function3.__doc__.startswith("test_function3(a: int, b: int) -> None")
21
+
22
+ assert m.test_function4.__doc__.startswith("test_function4(a: int, b: int) -> None")
23
+ assert m.test_function4.__doc__.endswith("A custom docstring\n")
24
+
25
+ # options.disable_function_signatures()
26
+ # options.disable_user_defined_docstrings()
27
+ assert not m.test_function5.__doc__
28
+
29
+ # nested options.enable_user_defined_docstrings()
30
+ assert m.test_function6.__doc__ == "A custom docstring"
31
+
32
+ # RAII destructor
33
+ assert m.test_function7.__doc__.startswith("test_function7(a: int, b: int) -> None")
34
+ assert m.test_function7.__doc__.endswith("A custom docstring\n")
35
+
36
+ # when all options are disabled, no docstring (instead of an empty one) should be generated
37
+ assert m.test_function8.__doc__ is None
38
+
39
+ # Suppression of user-defined docstrings for non-function objects
40
+ assert not m.DocstringTestFoo.__doc__
41
+ assert not m.DocstringTestFoo.value_prop.__doc__
42
+
43
+ # Check existig behaviour of enum docstings
44
+ assert (
45
+ m.DocstringTestEnum1.__doc__
46
+ == "Enum docstring\n\nMembers:\n\n Member1\n\n Member2"
47
+ )
48
+
49
+ # options.enable_enum_members_docstring()
50
+ assert (
51
+ m.DocstringTestEnum2.__doc__
52
+ == "Enum docstring\n\nMembers:\n\n Member1\n\n Member2"
53
+ )
54
+
55
+ # options.disable_enum_members_docstring()
56
+ assert m.DocstringTestEnum3.__doc__ == "Enum docstring"
57
+
58
+ # options.disable_user_defined_docstrings()
59
+ assert m.DocstringTestEnum4.__doc__ == "Members:\n\n Member1\n\n Member2"
60
+
61
+ # options.disable_user_defined_docstrings()
62
+ # options.disable_enum_members_docstring()
63
+ # When all options are disabled, no docstring (instead of an empty one) should be generated
64
+ assert m.DocstringTestEnum5.__doc__ is None
third_party/CityFlow/extern/pybind11/tests/test_eigen_matrix.cpp CHANGED
@@ -1,445 +1,445 @@
1
- /*
2
- tests/eigen.cpp -- automatic conversion of Eigen types
3
-
4
- Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include <pybind11/eigen/matrix.h>
11
- #include <pybind11/stl.h>
12
-
13
- #include "constructor_stats.h"
14
- #include "pybind11_tests.h"
15
-
16
- PYBIND11_WARNING_DISABLE_MSVC(4996)
17
-
18
- #include <Eigen/Cholesky>
19
-
20
- using MatrixXdR = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
21
-
22
- // Sets/resets a testing reference matrix to have values of 10*r + c, where r and c are the
23
- // (1-based) row/column number.
24
- template <typename M>
25
- void reset_ref(M &x) {
26
- for (int i = 0; i < x.rows(); i++) {
27
- for (int j = 0; j < x.cols(); j++) {
28
- x(i, j) = 11 + 10 * i + j;
29
- }
30
- }
31
- }
32
-
33
- // Returns a static, column-major matrix
34
- Eigen::MatrixXd &get_cm() {
35
- static Eigen::MatrixXd *x;
36
- if (!x) {
37
- x = new Eigen::MatrixXd(3, 3);
38
- reset_ref(*x);
39
- }
40
- return *x;
41
- }
42
- // Likewise, but row-major
43
- MatrixXdR &get_rm() {
44
- static MatrixXdR *x;
45
- if (!x) {
46
- x = new MatrixXdR(3, 3);
47
- reset_ref(*x);
48
- }
49
- return *x;
50
- }
51
- // Resets the values of the static matrices returned by get_cm()/get_rm()
52
- void reset_refs() {
53
- reset_ref(get_cm());
54
- reset_ref(get_rm());
55
- }
56
-
57
- // Returns element 2,1 from a matrix (used to test copy/nocopy)
58
- double get_elem(const Eigen::Ref<const Eigen::MatrixXd> &m) { return m(2, 1); };
59
-
60
- // Returns a matrix with 10*r + 100*c added to each matrix element (to help test that the matrix
61
- // reference is referencing rows/columns correctly).
62
- template <typename MatrixArgType>
63
- Eigen::MatrixXd adjust_matrix(MatrixArgType m) {
64
- Eigen::MatrixXd ret(m);
65
- for (int c = 0; c < m.cols(); c++) {
66
- for (int r = 0; r < m.rows(); r++) {
67
- ret(r, c) += 10 * r + 100 * c; // NOLINT(clang-analyzer-core.uninitialized.Assign)
68
- }
69
- }
70
- return ret;
71
- }
72
-
73
- struct CustomOperatorNew {
74
- CustomOperatorNew() = default;
75
-
76
- Eigen::Matrix4d a = Eigen::Matrix4d::Zero();
77
- Eigen::Matrix4d b = Eigen::Matrix4d::Identity();
78
-
79
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
80
- };
81
-
82
- TEST_SUBMODULE(eigen_matrix, m) {
83
- using FixedMatrixR = Eigen::Matrix<float, 5, 6, Eigen::RowMajor>;
84
- using FixedMatrixC = Eigen::Matrix<float, 5, 6>;
85
- using DenseMatrixR = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
86
- using DenseMatrixC = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>;
87
- using FourRowMatrixC = Eigen::Matrix<float, 4, Eigen::Dynamic>;
88
- using FourColMatrixC = Eigen::Matrix<float, Eigen::Dynamic, 4>;
89
- using FourRowMatrixR = Eigen::Matrix<float, 4, Eigen::Dynamic>;
90
- using FourColMatrixR = Eigen::Matrix<float, Eigen::Dynamic, 4>;
91
- using SparseMatrixR = Eigen::SparseMatrix<float, Eigen::RowMajor>;
92
- using SparseMatrixC = Eigen::SparseMatrix<float>;
93
-
94
- // various tests
95
- m.def("double_col", [](const Eigen::VectorXf &x) -> Eigen::VectorXf { return 2.0f * x; });
96
- m.def("double_row",
97
- [](const Eigen::RowVectorXf &x) -> Eigen::RowVectorXf { return 2.0f * x; });
98
- m.def("double_complex",
99
- [](const Eigen::VectorXcf &x) -> Eigen::VectorXcf { return 2.0f * x; });
100
- m.def("double_threec", [](py::EigenDRef<Eigen::Vector3f> x) { x *= 2; });
101
- m.def("double_threer", [](py::EigenDRef<Eigen::RowVector3f> x) { x *= 2; });
102
- m.def("double_mat_cm", [](const Eigen::MatrixXf &x) -> Eigen::MatrixXf { return 2.0f * x; });
103
- m.def("double_mat_rm", [](const DenseMatrixR &x) -> DenseMatrixR { return 2.0f * x; });
104
-
105
- // test_eigen_ref_to_python
106
- // Different ways of passing via Eigen::Ref; the first and second are the Eigen-recommended
107
- m.def("cholesky1",
108
- [](const Eigen::Ref<MatrixXdR> &x) -> Eigen::MatrixXd { return x.llt().matrixL(); });
109
- m.def("cholesky2", [](const Eigen::Ref<const MatrixXdR> &x) -> Eigen::MatrixXd {
110
- return x.llt().matrixL();
111
- });
112
- m.def("cholesky3",
113
- [](const Eigen::Ref<MatrixXdR> &x) -> Eigen::MatrixXd { return x.llt().matrixL(); });
114
- m.def("cholesky4", [](const Eigen::Ref<const MatrixXdR> &x) -> Eigen::MatrixXd {
115
- return x.llt().matrixL();
116
- });
117
-
118
- // test_eigen_ref_mutators
119
- // Mutators: these add some value to the given element using Eigen, but Eigen should be mapping
120
- // into the numpy array data and so the result should show up there. There are three versions:
121
- // one that works on a contiguous-row matrix (numpy's default), one for a contiguous-column
122
- // matrix, and one for any matrix.
123
- auto add_rm = [](Eigen::Ref<MatrixXdR> x, int r, int c, double v) { x(r, c) += v; };
124
- auto add_cm = [](Eigen::Ref<Eigen::MatrixXd> x, int r, int c, double v) { x(r, c) += v; };
125
-
126
- // Mutators (Eigen maps into numpy variables):
127
- m.def("add_rm", add_rm); // Only takes row-contiguous
128
- m.def("add_cm", add_cm); // Only takes column-contiguous
129
- // Overloaded versions that will accept either row or column contiguous:
130
- m.def("add1", add_rm);
131
- m.def("add1", add_cm);
132
- m.def("add2", add_cm);
133
- m.def("add2", add_rm);
134
- // This one accepts a matrix of any stride:
135
- m.def("add_any",
136
- [](py::EigenDRef<Eigen::MatrixXd> x, int r, int c, double v) { x(r, c) += v; });
137
-
138
- // Return mutable references (numpy maps into eigen variables)
139
- m.def("get_cm_ref", []() { return Eigen::Ref<Eigen::MatrixXd>(get_cm()); });
140
- m.def("get_rm_ref", []() { return Eigen::Ref<MatrixXdR>(get_rm()); });
141
- // The same references, but non-mutable (numpy maps into eigen variables, but is !writeable)
142
- m.def("get_cm_const_ref", []() { return Eigen::Ref<const Eigen::MatrixXd>(get_cm()); });
143
- m.def("get_rm_const_ref", []() { return Eigen::Ref<const MatrixXdR>(get_rm()); });
144
-
145
- m.def("reset_refs", reset_refs); // Restores get_{cm,rm}_ref to original values
146
-
147
- // Increments and returns ref to (same) matrix
148
- m.def(
149
- "incr_matrix",
150
- [](Eigen::Ref<Eigen::MatrixXd> m, double v) {
151
- m += Eigen::MatrixXd::Constant(m.rows(), m.cols(), v);
152
- return m;
153
- },
154
- py::return_value_policy::reference);
155
-
156
- // Same, but accepts a matrix of any strides
157
- m.def(
158
- "incr_matrix_any",
159
- [](py::EigenDRef<Eigen::MatrixXd> m, double v) {
160
- m += Eigen::MatrixXd::Constant(m.rows(), m.cols(), v);
161
- return m;
162
- },
163
- py::return_value_policy::reference);
164
-
165
- // Returns an eigen slice of even rows
166
- m.def(
167
- "even_rows",
168
- [](py::EigenDRef<Eigen::MatrixXd> m) {
169
- return py::EigenDMap<Eigen::MatrixXd>(
170
- m.data(),
171
- (m.rows() + 1) / 2,
172
- m.cols(),
173
- py::EigenDStride(m.outerStride(), 2 * m.innerStride()));
174
- },
175
- py::return_value_policy::reference);
176
-
177
- // Returns an eigen slice of even columns
178
- m.def(
179
- "even_cols",
180
- [](py::EigenDRef<Eigen::MatrixXd> m) {
181
- return py::EigenDMap<Eigen::MatrixXd>(
182
- m.data(),
183
- m.rows(),
184
- (m.cols() + 1) / 2,
185
- py::EigenDStride(2 * m.outerStride(), m.innerStride()));
186
- },
187
- py::return_value_policy::reference);
188
-
189
- // Returns diagonals: a vector-like object with an inner stride != 1
190
- m.def("diagonal", [](const Eigen::Ref<const Eigen::MatrixXd> &x) { return x.diagonal(); });
191
- m.def("diagonal_1",
192
- [](const Eigen::Ref<const Eigen::MatrixXd> &x) { return x.diagonal<1>(); });
193
- m.def("diagonal_n",
194
- [](const Eigen::Ref<const Eigen::MatrixXd> &x, int index) { return x.diagonal(index); });
195
-
196
- // Return a block of a matrix (gives non-standard strides)
197
- m.def("block",
198
- [m](const py::object &x_obj,
199
- int start_row,
200
- int start_col,
201
- int block_rows,
202
- int block_cols) {
203
- return m.attr("_block")(x_obj, x_obj, start_row, start_col, block_rows, block_cols);
204
- });
205
-
206
- m.def(
207
- "_block",
208
- [](const py::object &x_obj,
209
- const Eigen::Ref<const Eigen::MatrixXd> &x,
210
- int start_row,
211
- int start_col,
212
- int block_rows,
213
- int block_cols) {
214
- // See PR #4217 for background. This test is a bit over the top, but might be useful
215
- // as a concrete example to point to when explaining the dangling reference trap.
216
- auto i0 = py::make_tuple(0, 0);
217
- auto x0_orig = x_obj[*i0].cast<double>();
218
- if (x(0, 0) != x0_orig) {
219
- throw std::runtime_error(
220
- "Something in the type_caster for Eigen::Ref is terribly wrong.");
221
- }
222
- double x0_mod = x0_orig + 1;
223
- x_obj[*i0] = x0_mod;
224
- auto copy_detected = (x(0, 0) != x0_mod);
225
- x_obj[*i0] = x0_orig;
226
- if (copy_detected) {
227
- throw std::runtime_error("type_caster for Eigen::Ref made a copy.");
228
- }
229
- return x.block(start_row, start_col, block_rows, block_cols);
230
- },
231
- py::keep_alive<0, 1>());
232
-
233
- // test_eigen_return_references, test_eigen_keepalive
234
- // return value referencing/copying tests:
235
- class ReturnTester {
236
- Eigen::MatrixXd mat = create();
237
-
238
- public:
239
- ReturnTester() { print_created(this); }
240
- ~ReturnTester() { print_destroyed(this); }
241
- static Eigen::MatrixXd create() { return Eigen::MatrixXd::Ones(10, 10); }
242
- // NOLINTNEXTLINE(readability-const-return-type)
243
- static const Eigen::MatrixXd createConst() { return Eigen::MatrixXd::Ones(10, 10); }
244
- Eigen::MatrixXd &get() { return mat; }
245
- Eigen::MatrixXd *getPtr() { return &mat; }
246
- const Eigen::MatrixXd &view() { return mat; }
247
- const Eigen::MatrixXd *viewPtr() { return &mat; }
248
- Eigen::Ref<Eigen::MatrixXd> ref() { return mat; }
249
- Eigen::Ref<const Eigen::MatrixXd> refConst() { return mat; }
250
- Eigen::Block<Eigen::MatrixXd> block(int r, int c, int nrow, int ncol) {
251
- return mat.block(r, c, nrow, ncol);
252
- }
253
- Eigen::Block<const Eigen::MatrixXd> blockConst(int r, int c, int nrow, int ncol) const {
254
- return mat.block(r, c, nrow, ncol);
255
- }
256
- py::EigenDMap<Eigen::Matrix2d> corners() {
257
- return py::EigenDMap<Eigen::Matrix2d>(
258
- mat.data(),
259
- py::EigenDStride(mat.outerStride() * (mat.outerSize() - 1),
260
- mat.innerStride() * (mat.innerSize() - 1)));
261
- }
262
- py::EigenDMap<const Eigen::Matrix2d> cornersConst() const {
263
- return py::EigenDMap<const Eigen::Matrix2d>(
264
- mat.data(),
265
- py::EigenDStride(mat.outerStride() * (mat.outerSize() - 1),
266
- mat.innerStride() * (mat.innerSize() - 1)));
267
- }
268
- };
269
- using rvp = py::return_value_policy;
270
- py::class_<ReturnTester>(m, "ReturnTester")
271
- .def(py::init<>())
272
- .def_static("create", &ReturnTester::create)
273
- .def_static("create_const", &ReturnTester::createConst)
274
- .def("get", &ReturnTester::get, rvp::reference_internal)
275
- .def("get_ptr", &ReturnTester::getPtr, rvp::reference_internal)
276
- .def("view", &ReturnTester::view, rvp::reference_internal)
277
- .def("view_ptr", &ReturnTester::view, rvp::reference_internal)
278
- .def("copy_get", &ReturnTester::get) // Default rvp: copy
279
- .def("copy_view", &ReturnTester::view) // "
280
- .def("ref", &ReturnTester::ref) // Default for Ref is to reference
281
- .def("ref_const", &ReturnTester::refConst) // Likewise, but const
282
- .def("ref_safe", &ReturnTester::ref, rvp::reference_internal)
283
- .def("ref_const_safe", &ReturnTester::refConst, rvp::reference_internal)
284
- .def("copy_ref", &ReturnTester::ref, rvp::copy)
285
- .def("copy_ref_const", &ReturnTester::refConst, rvp::copy)
286
- .def("block", &ReturnTester::block)
287
- .def("block_safe", &ReturnTester::block, rvp::reference_internal)
288
- .def("block_const", &ReturnTester::blockConst, rvp::reference_internal)
289
- .def("copy_block", &ReturnTester::block, rvp::copy)
290
- .def("corners", &ReturnTester::corners, rvp::reference_internal)
291
- .def("corners_const", &ReturnTester::cornersConst, rvp::reference_internal);
292
-
293
- // test_special_matrix_objects
294
- // Returns a DiagonalMatrix with diagonal (1,2,3,...)
295
- m.def("incr_diag", [](int k) {
296
- Eigen::DiagonalMatrix<int, Eigen::Dynamic> m(k);
297
- for (int i = 0; i < k; i++) {
298
- m.diagonal()[i] = i + 1;
299
- }
300
- return m;
301
- });
302
-
303
- // Returns a SelfAdjointView referencing the lower triangle of m
304
- m.def("symmetric_lower",
305
- [](const Eigen::MatrixXi &m) { return m.selfadjointView<Eigen::Lower>(); });
306
- // Returns a SelfAdjointView referencing the lower triangle of m
307
- m.def("symmetric_upper",
308
- [](const Eigen::MatrixXi &m) { return m.selfadjointView<Eigen::Upper>(); });
309
-
310
- // Test matrix for various functions below.
311
- Eigen::MatrixXf mat(5, 6);
312
- mat << 0, 3, 0, 0, 0, 11, 22, 0, 0, 0, 17, 11, 7, 5, 0, 1, 0, 11, 0, 0, 0, 0, 0, 11, 0, 0, 14,
313
- 0, 8, 11;
314
-
315
- // test_fixed, and various other tests
316
- m.def("fixed_r", [mat]() -> FixedMatrixR { return FixedMatrixR(mat); });
317
- // Our Eigen does a hack which respects constness through the numpy writeable flag.
318
- // Therefore, the const return actually affects this type despite being an rvalue.
319
- // NOLINTNEXTLINE(readability-const-return-type)
320
- m.def("fixed_r_const", [mat]() -> const FixedMatrixR { return FixedMatrixR(mat); });
321
- m.def("fixed_c", [mat]() -> FixedMatrixC { return FixedMatrixC(mat); });
322
- m.def("fixed_copy_r", [](const FixedMatrixR &m) -> FixedMatrixR { return m; });
323
- m.def("fixed_copy_c", [](const FixedMatrixC &m) -> FixedMatrixC { return m; });
324
- // test_mutator_descriptors
325
- m.def("fixed_mutator_r", [](const Eigen::Ref<FixedMatrixR> &) {});
326
- m.def("fixed_mutator_c", [](const Eigen::Ref<FixedMatrixC> &) {});
327
- m.def("fixed_mutator_a", [](const py::EigenDRef<FixedMatrixC> &) {});
328
- // test_dense
329
- m.def("dense_r", [mat]() -> DenseMatrixR { return DenseMatrixR(mat); });
330
- m.def("dense_c", [mat]() -> DenseMatrixC { return DenseMatrixC(mat); });
331
- m.def("dense_copy_r", [](const DenseMatrixR &m) -> DenseMatrixR { return m; });
332
- m.def("dense_copy_c", [](const DenseMatrixC &m) -> DenseMatrixC { return m; });
333
- // test_defaults
334
- bool have_numpy = true;
335
- try {
336
- py::module_::import("numpy");
337
- } catch (const py::error_already_set &) {
338
- have_numpy = false;
339
- }
340
- if (have_numpy) {
341
- py::module_::import("numpy");
342
- Eigen::Matrix<double, 3, 3> defaultMatrix = Eigen::Matrix3d::Identity();
343
- m.def(
344
- "defaults_mat", [](const Eigen::Matrix3d &) {}, py::arg("mat") = defaultMatrix);
345
-
346
- Eigen::VectorXd defaultVector = Eigen::VectorXd::Ones(32);
347
- m.def(
348
- "defaults_vec", [](const Eigen::VectorXd &) {}, py::arg("vec") = defaultMatrix);
349
- }
350
- // test_sparse, test_sparse_signature
351
- m.def("sparse_r", [mat]() -> SparseMatrixR {
352
- // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
353
- return Eigen::SparseView<Eigen::MatrixXf>(mat);
354
- });
355
- m.def("sparse_c",
356
- [mat]() -> SparseMatrixC { return Eigen::SparseView<Eigen::MatrixXf>(mat); });
357
- m.def("sparse_copy_r", [](const SparseMatrixR &m) -> SparseMatrixR { return m; });
358
- m.def("sparse_copy_c", [](const SparseMatrixC &m) -> SparseMatrixC { return m; });
359
- // test_partially_fixed
360
- m.def("partial_copy_four_rm_r", [](const FourRowMatrixR &m) -> FourRowMatrixR { return m; });
361
- m.def("partial_copy_four_rm_c", [](const FourColMatrixR &m) -> FourColMatrixR { return m; });
362
- m.def("partial_copy_four_cm_r", [](const FourRowMatrixC &m) -> FourRowMatrixC { return m; });
363
- m.def("partial_copy_four_cm_c", [](const FourColMatrixC &m) -> FourColMatrixC { return m; });
364
-
365
- // test_cpp_casting
366
- // Test that we can cast a numpy object to a Eigen::MatrixXd explicitly
367
- m.def("cpp_copy", [](py::handle m) { return m.cast<Eigen::MatrixXd>()(1, 0); });
368
- m.def("cpp_ref_c", [](py::handle m) { return m.cast<Eigen::Ref<Eigen::MatrixXd>>()(1, 0); });
369
- m.def("cpp_ref_r", [](py::handle m) { return m.cast<Eigen::Ref<MatrixXdR>>()(1, 0); });
370
- m.def("cpp_ref_any",
371
- [](py::handle m) { return m.cast<py::EigenDRef<Eigen::MatrixXd>>()(1, 0); });
372
-
373
- // [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
374
-
375
- // test_nocopy_wrapper
376
- // Test that we can prevent copying into an argument that would normally copy: First a version
377
- // that would allow copying (if types or strides don't match) for comparison:
378
- m.def("get_elem", &get_elem);
379
- // Now this alternative that calls the tells pybind to fail rather than copy:
380
- m.def(
381
- "get_elem_nocopy",
382
- [](const Eigen::Ref<const Eigen::MatrixXd> &m) -> double { return get_elem(m); },
383
- py::arg{}.noconvert());
384
- // Also test a row-major-only no-copy const ref:
385
- m.def(
386
- "get_elem_rm_nocopy",
387
- [](Eigen::Ref<const Eigen::Matrix<long, -1, -1, Eigen::RowMajor>> &m) -> long {
388
- return m(2, 1);
389
- },
390
- py::arg{}.noconvert());
391
-
392
- // test_issue738, test_zero_length
393
- // Issue #738: 1×N or N×1 2D matrices were neither accepted nor properly copied with an
394
- // incompatible stride value on the length-1 dimension--but that should be allowed (without
395
- // requiring a copy!) because the stride value can be safely ignored on a size-1 dimension.
396
- // Similarly, 0×N or N×0 matrices were not accepted--again, these should be allowed since
397
- // they contain no data. This particularly affects numpy ≥ 1.23, which sets the strides to
398
- // 0 if any dimension size is 0.
399
- m.def("iss738_f1",
400
- &adjust_matrix<const Eigen::Ref<const Eigen::MatrixXd> &>,
401
- py::arg{}.noconvert());
402
- m.def("iss738_f2",
403
- &adjust_matrix<const Eigen::Ref<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>> &>,
404
- py::arg{}.noconvert());
405
-
406
- // test_issue1105
407
- // Issue #1105: when converting from a numpy two-dimensional (Nx1) or (1xN) value into a dense
408
- // eigen Vector or RowVector, the argument would fail to load because the numpy copy would
409
- // fail: numpy won't broadcast a Nx1 into a 1-dimensional vector.
410
- m.def("iss1105_col", [](const Eigen::VectorXd &) { return true; });
411
- m.def("iss1105_row", [](const Eigen::RowVectorXd &) { return true; });
412
-
413
- // test_named_arguments
414
- // Make sure named arguments are working properly:
415
- m.def(
416
- "matrix_multiply",
417
- [](const py::EigenDRef<const Eigen::MatrixXd> &A,
418
- const py::EigenDRef<const Eigen::MatrixXd> &B) -> Eigen::MatrixXd {
419
- if (A.cols() != B.rows()) {
420
- throw std::domain_error("Nonconformable matrices!");
421
- }
422
- return A * B;
423
- },
424
- py::arg("A"),
425
- py::arg("B"));
426
-
427
- // test_custom_operator_new
428
- py::class_<CustomOperatorNew>(m, "CustomOperatorNew")
429
- .def(py::init<>())
430
- .def_readonly("a", &CustomOperatorNew::a)
431
- .def_readonly("b", &CustomOperatorNew::b);
432
-
433
- // test_eigen_ref_life_support
434
- // In case of a failure (the caster's temp array does not live long enough), creating
435
- // a new array (np.ones(10)) increases the chances that the temp array will be garbage
436
- // collected and/or that its memory will be overridden with different values.
437
- m.def("get_elem_direct", [](const Eigen::Ref<const Eigen::VectorXd> &v) {
438
- py::module_::import("numpy").attr("ones")(10);
439
- return v(5);
440
- });
441
- m.def("get_elem_indirect", [](std::vector<Eigen::Ref<const Eigen::VectorXd>> v) {
442
- py::module_::import("numpy").attr("ones")(10);
443
- return v[0](5);
444
- });
445
- }
 
1
+ /*
2
+ tests/eigen.cpp -- automatic conversion of Eigen types
3
+
4
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include <pybind11/eigen/matrix.h>
11
+ #include <pybind11/stl.h>
12
+
13
+ #include "constructor_stats.h"
14
+ #include "pybind11_tests.h"
15
+
16
+ PYBIND11_WARNING_DISABLE_MSVC(4996)
17
+
18
+ #include <Eigen/Cholesky>
19
+
20
+ using MatrixXdR = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
21
+
22
+ // Sets/resets a testing reference matrix to have values of 10*r + c, where r and c are the
23
+ // (1-based) row/column number.
24
+ template <typename M>
25
+ void reset_ref(M &x) {
26
+ for (int i = 0; i < x.rows(); i++) {
27
+ for (int j = 0; j < x.cols(); j++) {
28
+ x(i, j) = 11 + 10 * i + j;
29
+ }
30
+ }
31
+ }
32
+
33
+ // Returns a static, column-major matrix
34
+ Eigen::MatrixXd &get_cm() {
35
+ static Eigen::MatrixXd *x;
36
+ if (!x) {
37
+ x = new Eigen::MatrixXd(3, 3);
38
+ reset_ref(*x);
39
+ }
40
+ return *x;
41
+ }
42
+ // Likewise, but row-major
43
+ MatrixXdR &get_rm() {
44
+ static MatrixXdR *x;
45
+ if (!x) {
46
+ x = new MatrixXdR(3, 3);
47
+ reset_ref(*x);
48
+ }
49
+ return *x;
50
+ }
51
+ // Resets the values of the static matrices returned by get_cm()/get_rm()
52
+ void reset_refs() {
53
+ reset_ref(get_cm());
54
+ reset_ref(get_rm());
55
+ }
56
+
57
+ // Returns element 2,1 from a matrix (used to test copy/nocopy)
58
+ double get_elem(const Eigen::Ref<const Eigen::MatrixXd> &m) { return m(2, 1); };
59
+
60
+ // Returns a matrix with 10*r + 100*c added to each matrix element (to help test that the matrix
61
+ // reference is referencing rows/columns correctly).
62
+ template <typename MatrixArgType>
63
+ Eigen::MatrixXd adjust_matrix(MatrixArgType m) {
64
+ Eigen::MatrixXd ret(m);
65
+ for (int c = 0; c < m.cols(); c++) {
66
+ for (int r = 0; r < m.rows(); r++) {
67
+ ret(r, c) += 10 * r + 100 * c; // NOLINT(clang-analyzer-core.uninitialized.Assign)
68
+ }
69
+ }
70
+ return ret;
71
+ }
72
+
73
+ struct CustomOperatorNew {
74
+ CustomOperatorNew() = default;
75
+
76
+ Eigen::Matrix4d a = Eigen::Matrix4d::Zero();
77
+ Eigen::Matrix4d b = Eigen::Matrix4d::Identity();
78
+
79
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
80
+ };
81
+
82
+ TEST_SUBMODULE(eigen_matrix, m) {
83
+ using FixedMatrixR = Eigen::Matrix<float, 5, 6, Eigen::RowMajor>;
84
+ using FixedMatrixC = Eigen::Matrix<float, 5, 6>;
85
+ using DenseMatrixR = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
86
+ using DenseMatrixC = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>;
87
+ using FourRowMatrixC = Eigen::Matrix<float, 4, Eigen::Dynamic>;
88
+ using FourColMatrixC = Eigen::Matrix<float, Eigen::Dynamic, 4>;
89
+ using FourRowMatrixR = Eigen::Matrix<float, 4, Eigen::Dynamic>;
90
+ using FourColMatrixR = Eigen::Matrix<float, Eigen::Dynamic, 4>;
91
+ using SparseMatrixR = Eigen::SparseMatrix<float, Eigen::RowMajor>;
92
+ using SparseMatrixC = Eigen::SparseMatrix<float>;
93
+
94
+ // various tests
95
+ m.def("double_col", [](const Eigen::VectorXf &x) -> Eigen::VectorXf { return 2.0f * x; });
96
+ m.def("double_row",
97
+ [](const Eigen::RowVectorXf &x) -> Eigen::RowVectorXf { return 2.0f * x; });
98
+ m.def("double_complex",
99
+ [](const Eigen::VectorXcf &x) -> Eigen::VectorXcf { return 2.0f * x; });
100
+ m.def("double_threec", [](py::EigenDRef<Eigen::Vector3f> x) { x *= 2; });
101
+ m.def("double_threer", [](py::EigenDRef<Eigen::RowVector3f> x) { x *= 2; });
102
+ m.def("double_mat_cm", [](const Eigen::MatrixXf &x) -> Eigen::MatrixXf { return 2.0f * x; });
103
+ m.def("double_mat_rm", [](const DenseMatrixR &x) -> DenseMatrixR { return 2.0f * x; });
104
+
105
+ // test_eigen_ref_to_python
106
+ // Different ways of passing via Eigen::Ref; the first and second are the Eigen-recommended
107
+ m.def("cholesky1",
108
+ [](const Eigen::Ref<MatrixXdR> &x) -> Eigen::MatrixXd { return x.llt().matrixL(); });
109
+ m.def("cholesky2", [](const Eigen::Ref<const MatrixXdR> &x) -> Eigen::MatrixXd {
110
+ return x.llt().matrixL();
111
+ });
112
+ m.def("cholesky3",
113
+ [](const Eigen::Ref<MatrixXdR> &x) -> Eigen::MatrixXd { return x.llt().matrixL(); });
114
+ m.def("cholesky4", [](const Eigen::Ref<const MatrixXdR> &x) -> Eigen::MatrixXd {
115
+ return x.llt().matrixL();
116
+ });
117
+
118
+ // test_eigen_ref_mutators
119
+ // Mutators: these add some value to the given element using Eigen, but Eigen should be mapping
120
+ // into the numpy array data and so the result should show up there. There are three versions:
121
+ // one that works on a contiguous-row matrix (numpy's default), one for a contiguous-column
122
+ // matrix, and one for any matrix.
123
+ auto add_rm = [](Eigen::Ref<MatrixXdR> x, int r, int c, double v) { x(r, c) += v; };
124
+ auto add_cm = [](Eigen::Ref<Eigen::MatrixXd> x, int r, int c, double v) { x(r, c) += v; };
125
+
126
+ // Mutators (Eigen maps into numpy variables):
127
+ m.def("add_rm", add_rm); // Only takes row-contiguous
128
+ m.def("add_cm", add_cm); // Only takes column-contiguous
129
+ // Overloaded versions that will accept either row or column contiguous:
130
+ m.def("add1", add_rm);
131
+ m.def("add1", add_cm);
132
+ m.def("add2", add_cm);
133
+ m.def("add2", add_rm);
134
+ // This one accepts a matrix of any stride:
135
+ m.def("add_any",
136
+ [](py::EigenDRef<Eigen::MatrixXd> x, int r, int c, double v) { x(r, c) += v; });
137
+
138
+ // Return mutable references (numpy maps into eigen variables)
139
+ m.def("get_cm_ref", []() { return Eigen::Ref<Eigen::MatrixXd>(get_cm()); });
140
+ m.def("get_rm_ref", []() { return Eigen::Ref<MatrixXdR>(get_rm()); });
141
+ // The same references, but non-mutable (numpy maps into eigen variables, but is !writeable)
142
+ m.def("get_cm_const_ref", []() { return Eigen::Ref<const Eigen::MatrixXd>(get_cm()); });
143
+ m.def("get_rm_const_ref", []() { return Eigen::Ref<const MatrixXdR>(get_rm()); });
144
+
145
+ m.def("reset_refs", reset_refs); // Restores get_{cm,rm}_ref to original values
146
+
147
+ // Increments and returns ref to (same) matrix
148
+ m.def(
149
+ "incr_matrix",
150
+ [](Eigen::Ref<Eigen::MatrixXd> m, double v) {
151
+ m += Eigen::MatrixXd::Constant(m.rows(), m.cols(), v);
152
+ return m;
153
+ },
154
+ py::return_value_policy::reference);
155
+
156
+ // Same, but accepts a matrix of any strides
157
+ m.def(
158
+ "incr_matrix_any",
159
+ [](py::EigenDRef<Eigen::MatrixXd> m, double v) {
160
+ m += Eigen::MatrixXd::Constant(m.rows(), m.cols(), v);
161
+ return m;
162
+ },
163
+ py::return_value_policy::reference);
164
+
165
+ // Returns an eigen slice of even rows
166
+ m.def(
167
+ "even_rows",
168
+ [](py::EigenDRef<Eigen::MatrixXd> m) {
169
+ return py::EigenDMap<Eigen::MatrixXd>(
170
+ m.data(),
171
+ (m.rows() + 1) / 2,
172
+ m.cols(),
173
+ py::EigenDStride(m.outerStride(), 2 * m.innerStride()));
174
+ },
175
+ py::return_value_policy::reference);
176
+
177
+ // Returns an eigen slice of even columns
178
+ m.def(
179
+ "even_cols",
180
+ [](py::EigenDRef<Eigen::MatrixXd> m) {
181
+ return py::EigenDMap<Eigen::MatrixXd>(
182
+ m.data(),
183
+ m.rows(),
184
+ (m.cols() + 1) / 2,
185
+ py::EigenDStride(2 * m.outerStride(), m.innerStride()));
186
+ },
187
+ py::return_value_policy::reference);
188
+
189
+ // Returns diagonals: a vector-like object with an inner stride != 1
190
+ m.def("diagonal", [](const Eigen::Ref<const Eigen::MatrixXd> &x) { return x.diagonal(); });
191
+ m.def("diagonal_1",
192
+ [](const Eigen::Ref<const Eigen::MatrixXd> &x) { return x.diagonal<1>(); });
193
+ m.def("diagonal_n",
194
+ [](const Eigen::Ref<const Eigen::MatrixXd> &x, int index) { return x.diagonal(index); });
195
+
196
+ // Return a block of a matrix (gives non-standard strides)
197
+ m.def("block",
198
+ [m](const py::object &x_obj,
199
+ int start_row,
200
+ int start_col,
201
+ int block_rows,
202
+ int block_cols) {
203
+ return m.attr("_block")(x_obj, x_obj, start_row, start_col, block_rows, block_cols);
204
+ });
205
+
206
+ m.def(
207
+ "_block",
208
+ [](const py::object &x_obj,
209
+ const Eigen::Ref<const Eigen::MatrixXd> &x,
210
+ int start_row,
211
+ int start_col,
212
+ int block_rows,
213
+ int block_cols) {
214
+ // See PR #4217 for background. This test is a bit over the top, but might be useful
215
+ // as a concrete example to point to when explaining the dangling reference trap.
216
+ auto i0 = py::make_tuple(0, 0);
217
+ auto x0_orig = x_obj[*i0].cast<double>();
218
+ if (x(0, 0) != x0_orig) {
219
+ throw std::runtime_error(
220
+ "Something in the type_caster for Eigen::Ref is terribly wrong.");
221
+ }
222
+ double x0_mod = x0_orig + 1;
223
+ x_obj[*i0] = x0_mod;
224
+ auto copy_detected = (x(0, 0) != x0_mod);
225
+ x_obj[*i0] = x0_orig;
226
+ if (copy_detected) {
227
+ throw std::runtime_error("type_caster for Eigen::Ref made a copy.");
228
+ }
229
+ return x.block(start_row, start_col, block_rows, block_cols);
230
+ },
231
+ py::keep_alive<0, 1>());
232
+
233
+ // test_eigen_return_references, test_eigen_keepalive
234
+ // return value referencing/copying tests:
235
+ class ReturnTester {
236
+ Eigen::MatrixXd mat = create();
237
+
238
+ public:
239
+ ReturnTester() { print_created(this); }
240
+ ~ReturnTester() { print_destroyed(this); }
241
+ static Eigen::MatrixXd create() { return Eigen::MatrixXd::Ones(10, 10); }
242
+ // NOLINTNEXTLINE(readability-const-return-type)
243
+ static const Eigen::MatrixXd createConst() { return Eigen::MatrixXd::Ones(10, 10); }
244
+ Eigen::MatrixXd &get() { return mat; }
245
+ Eigen::MatrixXd *getPtr() { return &mat; }
246
+ const Eigen::MatrixXd &view() { return mat; }
247
+ const Eigen::MatrixXd *viewPtr() { return &mat; }
248
+ Eigen::Ref<Eigen::MatrixXd> ref() { return mat; }
249
+ Eigen::Ref<const Eigen::MatrixXd> refConst() { return mat; }
250
+ Eigen::Block<Eigen::MatrixXd> block(int r, int c, int nrow, int ncol) {
251
+ return mat.block(r, c, nrow, ncol);
252
+ }
253
+ Eigen::Block<const Eigen::MatrixXd> blockConst(int r, int c, int nrow, int ncol) const {
254
+ return mat.block(r, c, nrow, ncol);
255
+ }
256
+ py::EigenDMap<Eigen::Matrix2d> corners() {
257
+ return py::EigenDMap<Eigen::Matrix2d>(
258
+ mat.data(),
259
+ py::EigenDStride(mat.outerStride() * (mat.outerSize() - 1),
260
+ mat.innerStride() * (mat.innerSize() - 1)));
261
+ }
262
+ py::EigenDMap<const Eigen::Matrix2d> cornersConst() const {
263
+ return py::EigenDMap<const Eigen::Matrix2d>(
264
+ mat.data(),
265
+ py::EigenDStride(mat.outerStride() * (mat.outerSize() - 1),
266
+ mat.innerStride() * (mat.innerSize() - 1)));
267
+ }
268
+ };
269
+ using rvp = py::return_value_policy;
270
+ py::class_<ReturnTester>(m, "ReturnTester")
271
+ .def(py::init<>())
272
+ .def_static("create", &ReturnTester::create)
273
+ .def_static("create_const", &ReturnTester::createConst)
274
+ .def("get", &ReturnTester::get, rvp::reference_internal)
275
+ .def("get_ptr", &ReturnTester::getPtr, rvp::reference_internal)
276
+ .def("view", &ReturnTester::view, rvp::reference_internal)
277
+ .def("view_ptr", &ReturnTester::view, rvp::reference_internal)
278
+ .def("copy_get", &ReturnTester::get) // Default rvp: copy
279
+ .def("copy_view", &ReturnTester::view) // "
280
+ .def("ref", &ReturnTester::ref) // Default for Ref is to reference
281
+ .def("ref_const", &ReturnTester::refConst) // Likewise, but const
282
+ .def("ref_safe", &ReturnTester::ref, rvp::reference_internal)
283
+ .def("ref_const_safe", &ReturnTester::refConst, rvp::reference_internal)
284
+ .def("copy_ref", &ReturnTester::ref, rvp::copy)
285
+ .def("copy_ref_const", &ReturnTester::refConst, rvp::copy)
286
+ .def("block", &ReturnTester::block)
287
+ .def("block_safe", &ReturnTester::block, rvp::reference_internal)
288
+ .def("block_const", &ReturnTester::blockConst, rvp::reference_internal)
289
+ .def("copy_block", &ReturnTester::block, rvp::copy)
290
+ .def("corners", &ReturnTester::corners, rvp::reference_internal)
291
+ .def("corners_const", &ReturnTester::cornersConst, rvp::reference_internal);
292
+
293
+ // test_special_matrix_objects
294
+ // Returns a DiagonalMatrix with diagonal (1,2,3,...)
295
+ m.def("incr_diag", [](int k) {
296
+ Eigen::DiagonalMatrix<int, Eigen::Dynamic> m(k);
297
+ for (int i = 0; i < k; i++) {
298
+ m.diagonal()[i] = i + 1;
299
+ }
300
+ return m;
301
+ });
302
+
303
+ // Returns a SelfAdjointView referencing the lower triangle of m
304
+ m.def("symmetric_lower",
305
+ [](const Eigen::MatrixXi &m) { return m.selfadjointView<Eigen::Lower>(); });
306
+ // Returns a SelfAdjointView referencing the lower triangle of m
307
+ m.def("symmetric_upper",
308
+ [](const Eigen::MatrixXi &m) { return m.selfadjointView<Eigen::Upper>(); });
309
+
310
+ // Test matrix for various functions below.
311
+ Eigen::MatrixXf mat(5, 6);
312
+ mat << 0, 3, 0, 0, 0, 11, 22, 0, 0, 0, 17, 11, 7, 5, 0, 1, 0, 11, 0, 0, 0, 0, 0, 11, 0, 0, 14,
313
+ 0, 8, 11;
314
+
315
+ // test_fixed, and various other tests
316
+ m.def("fixed_r", [mat]() -> FixedMatrixR { return FixedMatrixR(mat); });
317
+ // Our Eigen does a hack which respects constness through the numpy writeable flag.
318
+ // Therefore, the const return actually affects this type despite being an rvalue.
319
+ // NOLINTNEXTLINE(readability-const-return-type)
320
+ m.def("fixed_r_const", [mat]() -> const FixedMatrixR { return FixedMatrixR(mat); });
321
+ m.def("fixed_c", [mat]() -> FixedMatrixC { return FixedMatrixC(mat); });
322
+ m.def("fixed_copy_r", [](const FixedMatrixR &m) -> FixedMatrixR { return m; });
323
+ m.def("fixed_copy_c", [](const FixedMatrixC &m) -> FixedMatrixC { return m; });
324
+ // test_mutator_descriptors
325
+ m.def("fixed_mutator_r", [](const Eigen::Ref<FixedMatrixR> &) {});
326
+ m.def("fixed_mutator_c", [](const Eigen::Ref<FixedMatrixC> &) {});
327
+ m.def("fixed_mutator_a", [](const py::EigenDRef<FixedMatrixC> &) {});
328
+ // test_dense
329
+ m.def("dense_r", [mat]() -> DenseMatrixR { return DenseMatrixR(mat); });
330
+ m.def("dense_c", [mat]() -> DenseMatrixC { return DenseMatrixC(mat); });
331
+ m.def("dense_copy_r", [](const DenseMatrixR &m) -> DenseMatrixR { return m; });
332
+ m.def("dense_copy_c", [](const DenseMatrixC &m) -> DenseMatrixC { return m; });
333
+ // test_defaults
334
+ bool have_numpy = true;
335
+ try {
336
+ py::module_::import("numpy");
337
+ } catch (const py::error_already_set &) {
338
+ have_numpy = false;
339
+ }
340
+ if (have_numpy) {
341
+ py::module_::import("numpy");
342
+ Eigen::Matrix<double, 3, 3> defaultMatrix = Eigen::Matrix3d::Identity();
343
+ m.def(
344
+ "defaults_mat", [](const Eigen::Matrix3d &) {}, py::arg("mat") = defaultMatrix);
345
+
346
+ Eigen::VectorXd defaultVector = Eigen::VectorXd::Ones(32);
347
+ m.def(
348
+ "defaults_vec", [](const Eigen::VectorXd &) {}, py::arg("vec") = defaultMatrix);
349
+ }
350
+ // test_sparse, test_sparse_signature
351
+ m.def("sparse_r", [mat]() -> SparseMatrixR {
352
+ // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
353
+ return Eigen::SparseView<Eigen::MatrixXf>(mat);
354
+ });
355
+ m.def("sparse_c",
356
+ [mat]() -> SparseMatrixC { return Eigen::SparseView<Eigen::MatrixXf>(mat); });
357
+ m.def("sparse_copy_r", [](const SparseMatrixR &m) -> SparseMatrixR { return m; });
358
+ m.def("sparse_copy_c", [](const SparseMatrixC &m) -> SparseMatrixC { return m; });
359
+ // test_partially_fixed
360
+ m.def("partial_copy_four_rm_r", [](const FourRowMatrixR &m) -> FourRowMatrixR { return m; });
361
+ m.def("partial_copy_four_rm_c", [](const FourColMatrixR &m) -> FourColMatrixR { return m; });
362
+ m.def("partial_copy_four_cm_r", [](const FourRowMatrixC &m) -> FourRowMatrixC { return m; });
363
+ m.def("partial_copy_four_cm_c", [](const FourColMatrixC &m) -> FourColMatrixC { return m; });
364
+
365
+ // test_cpp_casting
366
+ // Test that we can cast a numpy object to a Eigen::MatrixXd explicitly
367
+ m.def("cpp_copy", [](py::handle m) { return m.cast<Eigen::MatrixXd>()(1, 0); });
368
+ m.def("cpp_ref_c", [](py::handle m) { return m.cast<Eigen::Ref<Eigen::MatrixXd>>()(1, 0); });
369
+ m.def("cpp_ref_r", [](py::handle m) { return m.cast<Eigen::Ref<MatrixXdR>>()(1, 0); });
370
+ m.def("cpp_ref_any",
371
+ [](py::handle m) { return m.cast<py::EigenDRef<Eigen::MatrixXd>>()(1, 0); });
372
+
373
+ // [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
374
+
375
+ // test_nocopy_wrapper
376
+ // Test that we can prevent copying into an argument that would normally copy: First a version
377
+ // that would allow copying (if types or strides don't match) for comparison:
378
+ m.def("get_elem", &get_elem);
379
+ // Now this alternative that calls the tells pybind to fail rather than copy:
380
+ m.def(
381
+ "get_elem_nocopy",
382
+ [](const Eigen::Ref<const Eigen::MatrixXd> &m) -> double { return get_elem(m); },
383
+ py::arg{}.noconvert());
384
+ // Also test a row-major-only no-copy const ref:
385
+ m.def(
386
+ "get_elem_rm_nocopy",
387
+ [](Eigen::Ref<const Eigen::Matrix<long, -1, -1, Eigen::RowMajor>> &m) -> long {
388
+ return m(2, 1);
389
+ },
390
+ py::arg{}.noconvert());
391
+
392
+ // test_issue738, test_zero_length
393
+ // Issue #738: 1×N or N×1 2D matrices were neither accepted nor properly copied with an
394
+ // incompatible stride value on the length-1 dimension--but that should be allowed (without
395
+ // requiring a copy!) because the stride value can be safely ignored on a size-1 dimension.
396
+ // Similarly, 0×N or N×0 matrices were not accepted--again, these should be allowed since
397
+ // they contain no data. This particularly affects numpy ≥ 1.23, which sets the strides to
398
+ // 0 if any dimension size is 0.
399
+ m.def("iss738_f1",
400
+ &adjust_matrix<const Eigen::Ref<const Eigen::MatrixXd> &>,
401
+ py::arg{}.noconvert());
402
+ m.def("iss738_f2",
403
+ &adjust_matrix<const Eigen::Ref<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>> &>,
404
+ py::arg{}.noconvert());
405
+
406
+ // test_issue1105
407
+ // Issue #1105: when converting from a numpy two-dimensional (Nx1) or (1xN) value into a dense
408
+ // eigen Vector or RowVector, the argument would fail to load because the numpy copy would
409
+ // fail: numpy won't broadcast a Nx1 into a 1-dimensional vector.
410
+ m.def("iss1105_col", [](const Eigen::VectorXd &) { return true; });
411
+ m.def("iss1105_row", [](const Eigen::RowVectorXd &) { return true; });
412
+
413
+ // test_named_arguments
414
+ // Make sure named arguments are working properly:
415
+ m.def(
416
+ "matrix_multiply",
417
+ [](const py::EigenDRef<const Eigen::MatrixXd> &A,
418
+ const py::EigenDRef<const Eigen::MatrixXd> &B) -> Eigen::MatrixXd {
419
+ if (A.cols() != B.rows()) {
420
+ throw std::domain_error("Nonconformable matrices!");
421
+ }
422
+ return A * B;
423
+ },
424
+ py::arg("A"),
425
+ py::arg("B"));
426
+
427
+ // test_custom_operator_new
428
+ py::class_<CustomOperatorNew>(m, "CustomOperatorNew")
429
+ .def(py::init<>())
430
+ .def_readonly("a", &CustomOperatorNew::a)
431
+ .def_readonly("b", &CustomOperatorNew::b);
432
+
433
+ // test_eigen_ref_life_support
434
+ // In case of a failure (the caster's temp array does not live long enough), creating
435
+ // a new array (np.ones(10)) increases the chances that the temp array will be garbage
436
+ // collected and/or that its memory will be overridden with different values.
437
+ m.def("get_elem_direct", [](const Eigen::Ref<const Eigen::VectorXd> &v) {
438
+ py::module_::import("numpy").attr("ones")(10);
439
+ return v(5);
440
+ });
441
+ m.def("get_elem_indirect", [](std::vector<Eigen::Ref<const Eigen::VectorXd>> v) {
442
+ py::module_::import("numpy").attr("ones")(10);
443
+ return v[0](5);
444
+ });
445
+ }
third_party/CityFlow/extern/pybind11/tests/test_eigen_matrix.py CHANGED
@@ -1,814 +1,814 @@
1
- import pytest
2
-
3
- from pybind11_tests import ConstructorStats
4
-
5
- np = pytest.importorskip("numpy")
6
- m = pytest.importorskip("pybind11_tests.eigen_matrix")
7
-
8
-
9
- ref = np.array(
10
- [
11
- [0.0, 3, 0, 0, 0, 11],
12
- [22, 0, 0, 0, 17, 11],
13
- [7, 5, 0, 1, 0, 11],
14
- [0, 0, 0, 0, 0, 11],
15
- [0, 0, 14, 0, 8, 11],
16
- ]
17
- )
18
-
19
-
20
- def assert_equal_ref(mat):
21
- np.testing.assert_array_equal(mat, ref)
22
-
23
-
24
- def assert_sparse_equal_ref(sparse_mat):
25
- assert_equal_ref(sparse_mat.toarray())
26
-
27
-
28
- def test_fixed():
29
- assert_equal_ref(m.fixed_c())
30
- assert_equal_ref(m.fixed_r())
31
- assert_equal_ref(m.fixed_copy_r(m.fixed_r()))
32
- assert_equal_ref(m.fixed_copy_c(m.fixed_c()))
33
- assert_equal_ref(m.fixed_copy_r(m.fixed_c()))
34
- assert_equal_ref(m.fixed_copy_c(m.fixed_r()))
35
-
36
-
37
- def test_dense():
38
- assert_equal_ref(m.dense_r())
39
- assert_equal_ref(m.dense_c())
40
- assert_equal_ref(m.dense_copy_r(m.dense_r()))
41
- assert_equal_ref(m.dense_copy_c(m.dense_c()))
42
- assert_equal_ref(m.dense_copy_r(m.dense_c()))
43
- assert_equal_ref(m.dense_copy_c(m.dense_r()))
44
-
45
-
46
- def test_partially_fixed():
47
- ref2 = np.array([[0.0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]])
48
- np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2), ref2)
49
- np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2), ref2)
50
- np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2[:, 1]), ref2[:, [1]])
51
- np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2[0, :]), ref2[[0], :])
52
- np.testing.assert_array_equal(
53
- m.partial_copy_four_rm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]
54
- )
55
- np.testing.assert_array_equal(
56
- m.partial_copy_four_rm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]
57
- )
58
-
59
- np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2), ref2)
60
- np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2), ref2)
61
- np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2[:, 1]), ref2[:, [1]])
62
- np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2[0, :]), ref2[[0], :])
63
- np.testing.assert_array_equal(
64
- m.partial_copy_four_cm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]
65
- )
66
- np.testing.assert_array_equal(
67
- m.partial_copy_four_cm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]
68
- )
69
-
70
- # TypeError should be raise for a shape mismatch
71
- functions = [
72
- m.partial_copy_four_rm_r,
73
- m.partial_copy_four_rm_c,
74
- m.partial_copy_four_cm_r,
75
- m.partial_copy_four_cm_c,
76
- ]
77
- matrix_with_wrong_shape = [[1, 2], [3, 4]]
78
- for f in functions:
79
- with pytest.raises(TypeError) as excinfo:
80
- f(matrix_with_wrong_shape)
81
- assert "incompatible function arguments" in str(excinfo.value)
82
-
83
-
84
- def test_mutator_descriptors():
85
- zr = np.arange(30, dtype="float32").reshape(5, 6) # row-major
86
- zc = zr.reshape(6, 5).transpose() # column-major
87
-
88
- m.fixed_mutator_r(zr)
89
- m.fixed_mutator_c(zc)
90
- m.fixed_mutator_a(zr)
91
- m.fixed_mutator_a(zc)
92
- with pytest.raises(TypeError) as excinfo:
93
- m.fixed_mutator_r(zc)
94
- assert (
95
- "(arg0: numpy.ndarray[numpy.float32[5, 6],"
96
- " flags.writeable, flags.c_contiguous]) -> None" in str(excinfo.value)
97
- )
98
- with pytest.raises(TypeError) as excinfo:
99
- m.fixed_mutator_c(zr)
100
- assert (
101
- "(arg0: numpy.ndarray[numpy.float32[5, 6],"
102
- " flags.writeable, flags.f_contiguous]) -> None" in str(excinfo.value)
103
- )
104
- with pytest.raises(TypeError) as excinfo:
105
- m.fixed_mutator_a(np.array([[1, 2], [3, 4]], dtype="float32"))
106
- assert "(arg0: numpy.ndarray[numpy.float32[5, 6], flags.writeable]) -> None" in str(
107
- excinfo.value
108
- )
109
- zr.flags.writeable = False
110
- with pytest.raises(TypeError):
111
- m.fixed_mutator_r(zr)
112
- with pytest.raises(TypeError):
113
- m.fixed_mutator_a(zr)
114
-
115
-
116
- def test_cpp_casting():
117
- assert m.cpp_copy(m.fixed_r()) == 22.0
118
- assert m.cpp_copy(m.fixed_c()) == 22.0
119
- z = np.array([[5.0, 6], [7, 8]])
120
- assert m.cpp_copy(z) == 7.0
121
- assert m.cpp_copy(m.get_cm_ref()) == 21.0
122
- assert m.cpp_copy(m.get_rm_ref()) == 21.0
123
- assert m.cpp_ref_c(m.get_cm_ref()) == 21.0
124
- assert m.cpp_ref_r(m.get_rm_ref()) == 21.0
125
- with pytest.raises(RuntimeError) as excinfo:
126
- # Can't reference m.fixed_c: it contains floats, m.cpp_ref_any wants doubles
127
- m.cpp_ref_any(m.fixed_c())
128
- assert "Unable to cast Python instance" in str(excinfo.value)
129
- with pytest.raises(RuntimeError) as excinfo:
130
- # Can't reference m.fixed_r: it contains floats, m.cpp_ref_any wants doubles
131
- m.cpp_ref_any(m.fixed_r())
132
- assert "Unable to cast Python instance" in str(excinfo.value)
133
- assert m.cpp_ref_any(m.ReturnTester.create()) == 1.0
134
-
135
- assert m.cpp_ref_any(m.get_cm_ref()) == 21.0
136
- assert m.cpp_ref_any(m.get_cm_ref()) == 21.0
137
-
138
-
139
- def test_pass_readonly_array():
140
- z = np.full((5, 6), 42.0)
141
- z.flags.writeable = False
142
- np.testing.assert_array_equal(z, m.fixed_copy_r(z))
143
- np.testing.assert_array_equal(m.fixed_r_const(), m.fixed_r())
144
- assert not m.fixed_r_const().flags.writeable
145
- np.testing.assert_array_equal(m.fixed_copy_r(m.fixed_r_const()), m.fixed_r_const())
146
-
147
-
148
- def test_nonunit_stride_from_python():
149
- counting_mat = np.arange(9.0, dtype=np.float32).reshape((3, 3))
150
- second_row = counting_mat[1, :]
151
- second_col = counting_mat[:, 1]
152
- np.testing.assert_array_equal(m.double_row(second_row), 2.0 * second_row)
153
- np.testing.assert_array_equal(m.double_col(second_row), 2.0 * second_row)
154
- np.testing.assert_array_equal(m.double_complex(second_row), 2.0 * second_row)
155
- np.testing.assert_array_equal(m.double_row(second_col), 2.0 * second_col)
156
- np.testing.assert_array_equal(m.double_col(second_col), 2.0 * second_col)
157
- np.testing.assert_array_equal(m.double_complex(second_col), 2.0 * second_col)
158
-
159
- counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
160
- slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
161
- for ref_mat in slices:
162
- np.testing.assert_array_equal(m.double_mat_cm(ref_mat), 2.0 * ref_mat)
163
- np.testing.assert_array_equal(m.double_mat_rm(ref_mat), 2.0 * ref_mat)
164
-
165
- # Mutator:
166
- m.double_threer(second_row)
167
- m.double_threec(second_col)
168
- np.testing.assert_array_equal(counting_mat, [[0.0, 2, 2], [6, 16, 10], [6, 14, 8]])
169
-
170
-
171
- def test_negative_stride_from_python(msg):
172
- """Eigen doesn't support (as of yet) negative strides. When a function takes an Eigen matrix by
173
- copy or const reference, we can pass a numpy array that has negative strides. Otherwise, an
174
- exception will be thrown as Eigen will not be able to map the numpy array."""
175
-
176
- counting_mat = np.arange(9.0, dtype=np.float32).reshape((3, 3))
177
- counting_mat = counting_mat[::-1, ::-1]
178
- second_row = counting_mat[1, :]
179
- second_col = counting_mat[:, 1]
180
- np.testing.assert_array_equal(m.double_row(second_row), 2.0 * second_row)
181
- np.testing.assert_array_equal(m.double_col(second_row), 2.0 * second_row)
182
- np.testing.assert_array_equal(m.double_complex(second_row), 2.0 * second_row)
183
- np.testing.assert_array_equal(m.double_row(second_col), 2.0 * second_col)
184
- np.testing.assert_array_equal(m.double_col(second_col), 2.0 * second_col)
185
- np.testing.assert_array_equal(m.double_complex(second_col), 2.0 * second_col)
186
-
187
- counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
188
- counting_3d = counting_3d[::-1, ::-1, ::-1]
189
- slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
190
- for ref_mat in slices:
191
- np.testing.assert_array_equal(m.double_mat_cm(ref_mat), 2.0 * ref_mat)
192
- np.testing.assert_array_equal(m.double_mat_rm(ref_mat), 2.0 * ref_mat)
193
-
194
- # Mutator:
195
- with pytest.raises(TypeError) as excinfo:
196
- m.double_threer(second_row)
197
- assert (
198
- msg(excinfo.value)
199
- == """
200
- double_threer(): incompatible function arguments. The following argument types are supported:
201
- 1. (arg0: numpy.ndarray[numpy.float32[1, 3], flags.writeable]) -> None
202
-
203
- Invoked with: """
204
- + repr(np.array([5.0, 4.0, 3.0], dtype="float32"))
205
- )
206
-
207
- with pytest.raises(TypeError) as excinfo:
208
- m.double_threec(second_col)
209
- assert (
210
- msg(excinfo.value)
211
- == """
212
- double_threec(): incompatible function arguments. The following argument types are supported:
213
- 1. (arg0: numpy.ndarray[numpy.float32[3, 1], flags.writeable]) -> None
214
-
215
- Invoked with: """
216
- + repr(np.array([7.0, 4.0, 1.0], dtype="float32"))
217
- )
218
-
219
-
220
- def test_block_runtime_error_type_caster_eigen_ref_made_a_copy():
221
- with pytest.raises(RuntimeError) as excinfo:
222
- m.block(ref, 0, 0, 0, 0)
223
- assert str(excinfo.value) == "type_caster for Eigen::Ref made a copy."
224
-
225
-
226
- def test_nonunit_stride_to_python():
227
- assert np.all(m.diagonal(ref) == ref.diagonal())
228
- assert np.all(m.diagonal_1(ref) == ref.diagonal(1))
229
- for i in range(-5, 7):
230
- assert np.all(m.diagonal_n(ref, i) == ref.diagonal(i)), f"m.diagonal_n({i})"
231
-
232
- # Must be order="F", otherwise the type_caster will make a copy and
233
- # m.block() will return a dangling reference (heap-use-after-free).
234
- rof = np.asarray(ref, order="F")
235
- assert np.all(m.block(rof, 2, 1, 3, 3) == rof[2:5, 1:4])
236
- assert np.all(m.block(rof, 1, 4, 4, 2) == rof[1:, 4:])
237
- assert np.all(m.block(rof, 1, 4, 3, 2) == rof[1:4, 4:])
238
-
239
-
240
- def test_eigen_ref_to_python():
241
- chols = [m.cholesky1, m.cholesky2, m.cholesky3, m.cholesky4]
242
- for i, chol in enumerate(chols, start=1):
243
- mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
244
- assert np.all(
245
- mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])
246
- ), f"cholesky{i}"
247
-
248
-
249
- def assign_both(a1, a2, r, c, v):
250
- a1[r, c] = v
251
- a2[r, c] = v
252
-
253
-
254
- def array_copy_but_one(a, r, c, v):
255
- z = np.array(a, copy=True)
256
- z[r, c] = v
257
- return z
258
-
259
-
260
- def test_eigen_return_references():
261
- """Tests various ways of returning references and non-referencing copies"""
262
-
263
- primary = np.ones((10, 10))
264
- a = m.ReturnTester()
265
- a_get1 = a.get()
266
- assert not a_get1.flags.owndata
267
- assert a_get1.flags.writeable
268
- assign_both(a_get1, primary, 3, 3, 5)
269
- a_get2 = a.get_ptr()
270
- assert not a_get2.flags.owndata
271
- assert a_get2.flags.writeable
272
- assign_both(a_get1, primary, 2, 3, 6)
273
-
274
- a_view1 = a.view()
275
- assert not a_view1.flags.owndata
276
- assert not a_view1.flags.writeable
277
- with pytest.raises(ValueError):
278
- a_view1[2, 3] = 4
279
- a_view2 = a.view_ptr()
280
- assert not a_view2.flags.owndata
281
- assert not a_view2.flags.writeable
282
- with pytest.raises(ValueError):
283
- a_view2[2, 3] = 4
284
-
285
- a_copy1 = a.copy_get()
286
- assert a_copy1.flags.owndata
287
- assert a_copy1.flags.writeable
288
- np.testing.assert_array_equal(a_copy1, primary)
289
- a_copy1[7, 7] = -44 # Shouldn't affect anything else
290
- c1want = array_copy_but_one(primary, 7, 7, -44)
291
- a_copy2 = a.copy_view()
292
- assert a_copy2.flags.owndata
293
- assert a_copy2.flags.writeable
294
- np.testing.assert_array_equal(a_copy2, primary)
295
- a_copy2[4, 4] = -22 # Shouldn't affect anything else
296
- c2want = array_copy_but_one(primary, 4, 4, -22)
297
-
298
- a_ref1 = a.ref()
299
- assert not a_ref1.flags.owndata
300
- assert a_ref1.flags.writeable
301
- assign_both(a_ref1, primary, 1, 1, 15)
302
- a_ref2 = a.ref_const()
303
- assert not a_ref2.flags.owndata
304
- assert not a_ref2.flags.writeable
305
- with pytest.raises(ValueError):
306
- a_ref2[5, 5] = 33
307
- a_ref3 = a.ref_safe()
308
- assert not a_ref3.flags.owndata
309
- assert a_ref3.flags.writeable
310
- assign_both(a_ref3, primary, 0, 7, 99)
311
- a_ref4 = a.ref_const_safe()
312
- assert not a_ref4.flags.owndata
313
- assert not a_ref4.flags.writeable
314
- with pytest.raises(ValueError):
315
- a_ref4[7, 0] = 987654321
316
-
317
- a_copy3 = a.copy_ref()
318
- assert a_copy3.flags.owndata
319
- assert a_copy3.flags.writeable
320
- np.testing.assert_array_equal(a_copy3, primary)
321
- a_copy3[8, 1] = 11
322
- c3want = array_copy_but_one(primary, 8, 1, 11)
323
- a_copy4 = a.copy_ref_const()
324
- assert a_copy4.flags.owndata
325
- assert a_copy4.flags.writeable
326
- np.testing.assert_array_equal(a_copy4, primary)
327
- a_copy4[8, 4] = 88
328
- c4want = array_copy_but_one(primary, 8, 4, 88)
329
-
330
- a_block1 = a.block(3, 3, 2, 2)
331
- assert not a_block1.flags.owndata
332
- assert a_block1.flags.writeable
333
- a_block1[0, 0] = 55
334
- primary[3, 3] = 55
335
- a_block2 = a.block_safe(2, 2, 3, 2)
336
- assert not a_block2.flags.owndata
337
- assert a_block2.flags.writeable
338
- a_block2[2, 1] = -123
339
- primary[4, 3] = -123
340
- a_block3 = a.block_const(6, 7, 4, 3)
341
- assert not a_block3.flags.owndata
342
- assert not a_block3.flags.writeable
343
- with pytest.raises(ValueError):
344
- a_block3[2, 2] = -44444
345
-
346
- a_copy5 = a.copy_block(2, 2, 2, 3)
347
- assert a_copy5.flags.owndata
348
- assert a_copy5.flags.writeable
349
- np.testing.assert_array_equal(a_copy5, primary[2:4, 2:5])
350
- a_copy5[1, 1] = 777
351
- c5want = array_copy_but_one(primary[2:4, 2:5], 1, 1, 777)
352
-
353
- a_corn1 = a.corners()
354
- assert not a_corn1.flags.owndata
355
- assert a_corn1.flags.writeable
356
- a_corn1 *= 50
357
- a_corn1[1, 1] = 999
358
- primary[0, 0] = 50
359
- primary[0, 9] = 50
360
- primary[9, 0] = 50
361
- primary[9, 9] = 999
362
- a_corn2 = a.corners_const()
363
- assert not a_corn2.flags.owndata
364
- assert not a_corn2.flags.writeable
365
- with pytest.raises(ValueError):
366
- a_corn2[1, 0] = 51
367
-
368
- # All of the changes made all the way along should be visible everywhere
369
- # now (except for the copies, of course)
370
- np.testing.assert_array_equal(a_get1, primary)
371
- np.testing.assert_array_equal(a_get2, primary)
372
- np.testing.assert_array_equal(a_view1, primary)
373
- np.testing.assert_array_equal(a_view2, primary)
374
- np.testing.assert_array_equal(a_ref1, primary)
375
- np.testing.assert_array_equal(a_ref2, primary)
376
- np.testing.assert_array_equal(a_ref3, primary)
377
- np.testing.assert_array_equal(a_ref4, primary)
378
- np.testing.assert_array_equal(a_block1, primary[3:5, 3:5])
379
- np.testing.assert_array_equal(a_block2, primary[2:5, 2:4])
380
- np.testing.assert_array_equal(a_block3, primary[6:10, 7:10])
381
- np.testing.assert_array_equal(
382
- a_corn1, primary[0 :: primary.shape[0] - 1, 0 :: primary.shape[1] - 1]
383
- )
384
- np.testing.assert_array_equal(
385
- a_corn2, primary[0 :: primary.shape[0] - 1, 0 :: primary.shape[1] - 1]
386
- )
387
-
388
- np.testing.assert_array_equal(a_copy1, c1want)
389
- np.testing.assert_array_equal(a_copy2, c2want)
390
- np.testing.assert_array_equal(a_copy3, c3want)
391
- np.testing.assert_array_equal(a_copy4, c4want)
392
- np.testing.assert_array_equal(a_copy5, c5want)
393
-
394
-
395
- def assert_keeps_alive(cl, method, *args):
396
- cstats = ConstructorStats.get(cl)
397
- start_with = cstats.alive()
398
- a = cl()
399
- assert cstats.alive() == start_with + 1
400
- z = method(a, *args)
401
- assert cstats.alive() == start_with + 1
402
- del a
403
- # Here's the keep alive in action:
404
- assert cstats.alive() == start_with + 1
405
- del z
406
- # Keep alive should have expired:
407
- assert cstats.alive() == start_with
408
-
409
-
410
- def test_eigen_keepalive():
411
- a = m.ReturnTester()
412
- cstats = ConstructorStats.get(m.ReturnTester)
413
- assert cstats.alive() == 1
414
- unsafe = [a.ref(), a.ref_const(), a.block(1, 2, 3, 4)]
415
- copies = [
416
- a.copy_get(),
417
- a.copy_view(),
418
- a.copy_ref(),
419
- a.copy_ref_const(),
420
- a.copy_block(4, 3, 2, 1),
421
- ]
422
- del a
423
- assert cstats.alive() == 0
424
- del unsafe
425
- del copies
426
-
427
- for meth in [
428
- m.ReturnTester.get,
429
- m.ReturnTester.get_ptr,
430
- m.ReturnTester.view,
431
- m.ReturnTester.view_ptr,
432
- m.ReturnTester.ref_safe,
433
- m.ReturnTester.ref_const_safe,
434
- m.ReturnTester.corners,
435
- m.ReturnTester.corners_const,
436
- ]:
437
- assert_keeps_alive(m.ReturnTester, meth)
438
-
439
- for meth in [m.ReturnTester.block_safe, m.ReturnTester.block_const]:
440
- assert_keeps_alive(m.ReturnTester, meth, 4, 3, 2, 1)
441
-
442
-
443
- def test_eigen_ref_mutators():
444
- """Tests Eigen's ability to mutate numpy values"""
445
-
446
- orig = np.array([[1.0, 2, 3], [4, 5, 6], [7, 8, 9]])
447
- zr = np.array(orig)
448
- zc = np.array(orig, order="F")
449
- m.add_rm(zr, 1, 0, 100)
450
- assert np.all(zr == np.array([[1.0, 2, 3], [104, 5, 6], [7, 8, 9]]))
451
- m.add_cm(zc, 1, 0, 200)
452
- assert np.all(zc == np.array([[1.0, 2, 3], [204, 5, 6], [7, 8, 9]]))
453
-
454
- m.add_any(zr, 1, 0, 20)
455
- assert np.all(zr == np.array([[1.0, 2, 3], [124, 5, 6], [7, 8, 9]]))
456
- m.add_any(zc, 1, 0, 10)
457
- assert np.all(zc == np.array([[1.0, 2, 3], [214, 5, 6], [7, 8, 9]]))
458
-
459
- # Can't reference a col-major array with a row-major Ref, and vice versa:
460
- with pytest.raises(TypeError):
461
- m.add_rm(zc, 1, 0, 1)
462
- with pytest.raises(TypeError):
463
- m.add_cm(zr, 1, 0, 1)
464
-
465
- # Overloads:
466
- m.add1(zr, 1, 0, -100)
467
- m.add2(zr, 1, 0, -20)
468
- assert np.all(zr == orig)
469
- m.add1(zc, 1, 0, -200)
470
- m.add2(zc, 1, 0, -10)
471
- assert np.all(zc == orig)
472
-
473
- # a non-contiguous slice (this won't work on either the row- or
474
- # column-contiguous refs, but should work for the any)
475
- cornersr = zr[0::2, 0::2]
476
- cornersc = zc[0::2, 0::2]
477
-
478
- assert np.all(cornersr == np.array([[1.0, 3], [7, 9]]))
479
- assert np.all(cornersc == np.array([[1.0, 3], [7, 9]]))
480
-
481
- with pytest.raises(TypeError):
482
- m.add_rm(cornersr, 0, 1, 25)
483
- with pytest.raises(TypeError):
484
- m.add_cm(cornersr, 0, 1, 25)
485
- with pytest.raises(TypeError):
486
- m.add_rm(cornersc, 0, 1, 25)
487
- with pytest.raises(TypeError):
488
- m.add_cm(cornersc, 0, 1, 25)
489
- m.add_any(cornersr, 0, 1, 25)
490
- m.add_any(cornersc, 0, 1, 44)
491
- assert np.all(zr == np.array([[1.0, 2, 28], [4, 5, 6], [7, 8, 9]]))
492
- assert np.all(zc == np.array([[1.0, 2, 47], [4, 5, 6], [7, 8, 9]]))
493
-
494
- # You shouldn't be allowed to pass a non-writeable array to a mutating Eigen method:
495
- zro = zr[0:4, 0:4]
496
- zro.flags.writeable = False
497
- with pytest.raises(TypeError):
498
- m.add_rm(zro, 0, 0, 0)
499
- with pytest.raises(TypeError):
500
- m.add_any(zro, 0, 0, 0)
501
- with pytest.raises(TypeError):
502
- m.add1(zro, 0, 0, 0)
503
- with pytest.raises(TypeError):
504
- m.add2(zro, 0, 0, 0)
505
-
506
- # integer array shouldn't be passable to a double-matrix-accepting mutating func:
507
- zi = np.array([[1, 2], [3, 4]])
508
- with pytest.raises(TypeError):
509
- m.add_rm(zi)
510
-
511
-
512
- def test_numpy_ref_mutators():
513
- """Tests numpy mutating Eigen matrices (for returned Eigen::Ref<...>s)"""
514
-
515
- m.reset_refs() # In case another test already changed it
516
-
517
- zc = m.get_cm_ref()
518
- zcro = m.get_cm_const_ref()
519
- zr = m.get_rm_ref()
520
- zrro = m.get_rm_const_ref()
521
-
522
- assert [zc[1, 2], zcro[1, 2], zr[1, 2], zrro[1, 2]] == [23] * 4
523
-
524
- assert not zc.flags.owndata
525
- assert zc.flags.writeable
526
- assert not zr.flags.owndata
527
- assert zr.flags.writeable
528
- assert not zcro.flags.owndata
529
- assert not zcro.flags.writeable
530
- assert not zrro.flags.owndata
531
- assert not zrro.flags.writeable
532
-
533
- zc[1, 2] = 99
534
- expect = np.array([[11.0, 12, 13], [21, 22, 99], [31, 32, 33]])
535
- # We should have just changed zc, of course, but also zcro and the original eigen matrix
536
- assert np.all(zc == expect)
537
- assert np.all(zcro == expect)
538
- assert np.all(m.get_cm_ref() == expect)
539
-
540
- zr[1, 2] = 99
541
- assert np.all(zr == expect)
542
- assert np.all(zrro == expect)
543
- assert np.all(m.get_rm_ref() == expect)
544
-
545
- # Make sure the readonly ones are numpy-readonly:
546
- with pytest.raises(ValueError):
547
- zcro[1, 2] = 6
548
- with pytest.raises(ValueError):
549
- zrro[1, 2] = 6
550
-
551
- # We should be able to explicitly copy like this (and since we're copying,
552
- # the const should drop away)
553
- y1 = np.array(m.get_cm_const_ref())
554
-
555
- assert y1.flags.owndata
556
- assert y1.flags.writeable
557
- # We should get copies of the eigen data, which was modified above:
558
- assert y1[1, 2] == 99
559
- y1[1, 2] += 12
560
- assert y1[1, 2] == 111
561
- assert zc[1, 2] == 99 # Make sure we aren't referencing the original
562
-
563
-
564
- def test_both_ref_mutators():
565
- """Tests a complex chain of nested eigen/numpy references"""
566
-
567
- m.reset_refs() # In case another test already changed it
568
-
569
- z = m.get_cm_ref() # numpy -> eigen
570
- z[0, 2] -= 3
571
- z2 = m.incr_matrix(z, 1) # numpy -> eigen -> numpy -> eigen
572
- z2[1, 1] += 6
573
- z3 = m.incr_matrix(z, 2) # (numpy -> eigen)^3
574
- z3[2, 2] += -5
575
- z4 = m.incr_matrix(z, 3) # (numpy -> eigen)^4
576
- z4[1, 1] -= 1
577
- z5 = m.incr_matrix(z, 4) # (numpy -> eigen)^5
578
- z5[0, 0] = 0
579
- assert np.all(z == z2)
580
- assert np.all(z == z3)
581
- assert np.all(z == z4)
582
- assert np.all(z == z5)
583
- expect = np.array([[0.0, 22, 20], [31, 37, 33], [41, 42, 38]])
584
- assert np.all(z == expect)
585
-
586
- y = np.array(range(100), dtype="float64").reshape(10, 10)
587
- y2 = m.incr_matrix_any(y, 10) # np -> eigen -> np
588
- y3 = m.incr_matrix_any(
589
- y2[0::2, 0::2], -33
590
- ) # np -> eigen -> np slice -> np -> eigen -> np
591
- y4 = m.even_rows(y3) # numpy -> eigen slice -> (... y3)
592
- y5 = m.even_cols(y4) # numpy -> eigen slice -> (... y4)
593
- y6 = m.incr_matrix_any(y5, 1000) # numpy -> eigen -> (... y5)
594
-
595
- # Apply same mutations using just numpy:
596
- yexpect = np.array(range(100), dtype="float64").reshape(10, 10)
597
- yexpect += 10
598
- yexpect[0::2, 0::2] -= 33
599
- yexpect[0::4, 0::4] += 1000
600
- assert np.all(y6 == yexpect[0::4, 0::4])
601
- assert np.all(y5 == yexpect[0::4, 0::4])
602
- assert np.all(y4 == yexpect[0::4, 0::2])
603
- assert np.all(y3 == yexpect[0::2, 0::2])
604
- assert np.all(y2 == yexpect)
605
- assert np.all(y == yexpect)
606
-
607
-
608
- def test_nocopy_wrapper():
609
- # get_elem requires a column-contiguous matrix reference, but should be
610
- # callable with other types of matrix (via copying):
611
- int_matrix_colmajor = np.array(
612
- [[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype="l", order="F"
613
- )
614
- dbl_matrix_colmajor = np.array(
615
- int_matrix_colmajor, dtype="double", order="F", copy=True
616
- )
617
- int_matrix_rowmajor = np.array(int_matrix_colmajor, order="C", copy=True)
618
- dbl_matrix_rowmajor = np.array(
619
- int_matrix_rowmajor, dtype="double", order="C", copy=True
620
- )
621
-
622
- # All should be callable via get_elem:
623
- assert m.get_elem(int_matrix_colmajor) == 8
624
- assert m.get_elem(dbl_matrix_colmajor) == 8
625
- assert m.get_elem(int_matrix_rowmajor) == 8
626
- assert m.get_elem(dbl_matrix_rowmajor) == 8
627
-
628
- # All but the second should fail with m.get_elem_nocopy:
629
- with pytest.raises(TypeError) as excinfo:
630
- m.get_elem_nocopy(int_matrix_colmajor)
631
- assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
632
- assert ", flags.f_contiguous" in str(excinfo.value)
633
- assert m.get_elem_nocopy(dbl_matrix_colmajor) == 8
634
- with pytest.raises(TypeError) as excinfo:
635
- m.get_elem_nocopy(int_matrix_rowmajor)
636
- assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
637
- assert ", flags.f_contiguous" in str(excinfo.value)
638
- with pytest.raises(TypeError) as excinfo:
639
- m.get_elem_nocopy(dbl_matrix_rowmajor)
640
- assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
641
- assert ", flags.f_contiguous" in str(excinfo.value)
642
-
643
- # For the row-major test, we take a long matrix in row-major, so only the third is allowed:
644
- with pytest.raises(TypeError) as excinfo:
645
- m.get_elem_rm_nocopy(int_matrix_colmajor)
646
- assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
647
- excinfo.value
648
- )
649
- assert ", flags.c_contiguous" in str(excinfo.value)
650
- with pytest.raises(TypeError) as excinfo:
651
- m.get_elem_rm_nocopy(dbl_matrix_colmajor)
652
- assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
653
- excinfo.value
654
- )
655
- assert ", flags.c_contiguous" in str(excinfo.value)
656
- assert m.get_elem_rm_nocopy(int_matrix_rowmajor) == 8
657
- with pytest.raises(TypeError) as excinfo:
658
- m.get_elem_rm_nocopy(dbl_matrix_rowmajor)
659
- assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
660
- excinfo.value
661
- )
662
- assert ", flags.c_contiguous" in str(excinfo.value)
663
-
664
-
665
- def test_eigen_ref_life_support():
666
- """Ensure the lifetime of temporary arrays created by the `Ref` caster
667
-
668
- The `Ref` caster sometimes creates a copy which needs to stay alive. This needs to
669
- happen both for directs casts (just the array) or indirectly (e.g. list of arrays).
670
- """
671
-
672
- a = np.full(shape=10, fill_value=8, dtype=np.int8)
673
- assert m.get_elem_direct(a) == 8
674
-
675
- list_of_a = [a]
676
- assert m.get_elem_indirect(list_of_a) == 8
677
-
678
-
679
- def test_special_matrix_objects():
680
- assert np.all(m.incr_diag(7) == np.diag([1.0, 2, 3, 4, 5, 6, 7]))
681
-
682
- asymm = np.array([[1.0, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
683
- symm_lower = np.array(asymm)
684
- symm_upper = np.array(asymm)
685
- for i in range(4):
686
- for j in range(i + 1, 4):
687
- symm_lower[i, j] = symm_lower[j, i]
688
- symm_upper[j, i] = symm_upper[i, j]
689
-
690
- assert np.all(m.symmetric_lower(asymm) == symm_lower)
691
- assert np.all(m.symmetric_upper(asymm) == symm_upper)
692
-
693
-
694
- def test_dense_signature(doc):
695
- assert (
696
- doc(m.double_col)
697
- == """
698
- double_col(arg0: numpy.ndarray[numpy.float32[m, 1]]) -> numpy.ndarray[numpy.float32[m, 1]]
699
- """
700
- )
701
- assert (
702
- doc(m.double_row)
703
- == """
704
- double_row(arg0: numpy.ndarray[numpy.float32[1, n]]) -> numpy.ndarray[numpy.float32[1, n]]
705
- """
706
- )
707
- assert doc(m.double_complex) == (
708
- """
709
- double_complex(arg0: numpy.ndarray[numpy.complex64[m, 1]])"""
710
- """ -> numpy.ndarray[numpy.complex64[m, 1]]
711
- """
712
- )
713
- assert doc(m.double_mat_rm) == (
714
- """
715
- double_mat_rm(arg0: numpy.ndarray[numpy.float32[m, n]])"""
716
- """ -> numpy.ndarray[numpy.float32[m, n]]
717
- """
718
- )
719
-
720
-
721
- def test_defaults(doc):
722
- assert "\n" not in str(doc(m.defaults_mat))
723
- assert "\n" not in str(doc(m.defaults_vec))
724
-
725
-
726
- def test_named_arguments():
727
- a = np.array([[1.0, 2], [3, 4], [5, 6]])
728
- b = np.ones((2, 1))
729
-
730
- assert np.all(m.matrix_multiply(a, b) == np.array([[3.0], [7], [11]]))
731
- assert np.all(m.matrix_multiply(A=a, B=b) == np.array([[3.0], [7], [11]]))
732
- assert np.all(m.matrix_multiply(B=b, A=a) == np.array([[3.0], [7], [11]]))
733
-
734
- with pytest.raises(ValueError) as excinfo:
735
- m.matrix_multiply(b, a)
736
- assert str(excinfo.value) == "Nonconformable matrices!"
737
-
738
- with pytest.raises(ValueError) as excinfo:
739
- m.matrix_multiply(A=b, B=a)
740
- assert str(excinfo.value) == "Nonconformable matrices!"
741
-
742
- with pytest.raises(ValueError) as excinfo:
743
- m.matrix_multiply(B=a, A=b)
744
- assert str(excinfo.value) == "Nonconformable matrices!"
745
-
746
-
747
- def test_sparse():
748
- pytest.importorskip("scipy")
749
- assert_sparse_equal_ref(m.sparse_r())
750
- assert_sparse_equal_ref(m.sparse_c())
751
- assert_sparse_equal_ref(m.sparse_copy_r(m.sparse_r()))
752
- assert_sparse_equal_ref(m.sparse_copy_c(m.sparse_c()))
753
- assert_sparse_equal_ref(m.sparse_copy_r(m.sparse_c()))
754
- assert_sparse_equal_ref(m.sparse_copy_c(m.sparse_r()))
755
-
756
-
757
- def test_sparse_signature(doc):
758
- pytest.importorskip("scipy")
759
- assert (
760
- doc(m.sparse_copy_r)
761
- == """
762
- sparse_copy_r(arg0: scipy.sparse.csr_matrix[numpy.float32]) -> scipy.sparse.csr_matrix[numpy.float32]
763
- """
764
- )
765
- assert (
766
- doc(m.sparse_copy_c)
767
- == """
768
- sparse_copy_c(arg0: scipy.sparse.csc_matrix[numpy.float32]) -> scipy.sparse.csc_matrix[numpy.float32]
769
- """
770
- )
771
-
772
-
773
- def test_issue738():
774
- """Ignore strides on a length-1 dimension (even if they would be incompatible length > 1)"""
775
- assert np.all(m.iss738_f1(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]]))
776
- assert np.all(
777
- m.iss738_f1(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]])
778
- )
779
-
780
- assert np.all(m.iss738_f2(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]]))
781
- assert np.all(
782
- m.iss738_f2(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]])
783
- )
784
-
785
-
786
- @pytest.mark.parametrize("func", [m.iss738_f1, m.iss738_f2])
787
- @pytest.mark.parametrize("sizes", [(0, 2), (2, 0)])
788
- def test_zero_length(func, sizes):
789
- """Ignore strides on a length-0 dimension (even if they would be incompatible length > 1)"""
790
- assert np.all(func(np.zeros(sizes)) == np.zeros(sizes))
791
-
792
-
793
- def test_issue1105():
794
- """Issue 1105: 1xN or Nx1 input arrays weren't accepted for eigen
795
- compile-time row vectors or column vector"""
796
- assert m.iss1105_row(np.ones((1, 7)))
797
- assert m.iss1105_col(np.ones((7, 1)))
798
-
799
- # These should still fail (incompatible dimensions):
800
- with pytest.raises(TypeError) as excinfo:
801
- m.iss1105_row(np.ones((7, 1)))
802
- assert "incompatible function arguments" in str(excinfo.value)
803
- with pytest.raises(TypeError) as excinfo:
804
- m.iss1105_col(np.ones((1, 7)))
805
- assert "incompatible function arguments" in str(excinfo.value)
806
-
807
-
808
- def test_custom_operator_new():
809
- """Using Eigen types as member variables requires a class-specific
810
- operator new with proper alignment"""
811
-
812
- o = m.CustomOperatorNew()
813
- np.testing.assert_allclose(o.a, 0.0)
814
- np.testing.assert_allclose(o.b.diagonal(), 1.0)
 
1
+ import pytest
2
+
3
+ from pybind11_tests import ConstructorStats
4
+
5
+ np = pytest.importorskip("numpy")
6
+ m = pytest.importorskip("pybind11_tests.eigen_matrix")
7
+
8
+
9
+ ref = np.array(
10
+ [
11
+ [0.0, 3, 0, 0, 0, 11],
12
+ [22, 0, 0, 0, 17, 11],
13
+ [7, 5, 0, 1, 0, 11],
14
+ [0, 0, 0, 0, 0, 11],
15
+ [0, 0, 14, 0, 8, 11],
16
+ ]
17
+ )
18
+
19
+
20
+ def assert_equal_ref(mat):
21
+ np.testing.assert_array_equal(mat, ref)
22
+
23
+
24
+ def assert_sparse_equal_ref(sparse_mat):
25
+ assert_equal_ref(sparse_mat.toarray())
26
+
27
+
28
+ def test_fixed():
29
+ assert_equal_ref(m.fixed_c())
30
+ assert_equal_ref(m.fixed_r())
31
+ assert_equal_ref(m.fixed_copy_r(m.fixed_r()))
32
+ assert_equal_ref(m.fixed_copy_c(m.fixed_c()))
33
+ assert_equal_ref(m.fixed_copy_r(m.fixed_c()))
34
+ assert_equal_ref(m.fixed_copy_c(m.fixed_r()))
35
+
36
+
37
+ def test_dense():
38
+ assert_equal_ref(m.dense_r())
39
+ assert_equal_ref(m.dense_c())
40
+ assert_equal_ref(m.dense_copy_r(m.dense_r()))
41
+ assert_equal_ref(m.dense_copy_c(m.dense_c()))
42
+ assert_equal_ref(m.dense_copy_r(m.dense_c()))
43
+ assert_equal_ref(m.dense_copy_c(m.dense_r()))
44
+
45
+
46
+ def test_partially_fixed():
47
+ ref2 = np.array([[0.0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]])
48
+ np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2), ref2)
49
+ np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2), ref2)
50
+ np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2[:, 1]), ref2[:, [1]])
51
+ np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2[0, :]), ref2[[0], :])
52
+ np.testing.assert_array_equal(
53
+ m.partial_copy_four_rm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]
54
+ )
55
+ np.testing.assert_array_equal(
56
+ m.partial_copy_four_rm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]
57
+ )
58
+
59
+ np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2), ref2)
60
+ np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2), ref2)
61
+ np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2[:, 1]), ref2[:, [1]])
62
+ np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2[0, :]), ref2[[0], :])
63
+ np.testing.assert_array_equal(
64
+ m.partial_copy_four_cm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]
65
+ )
66
+ np.testing.assert_array_equal(
67
+ m.partial_copy_four_cm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]
68
+ )
69
+
70
+ # TypeError should be raise for a shape mismatch
71
+ functions = [
72
+ m.partial_copy_four_rm_r,
73
+ m.partial_copy_four_rm_c,
74
+ m.partial_copy_four_cm_r,
75
+ m.partial_copy_four_cm_c,
76
+ ]
77
+ matrix_with_wrong_shape = [[1, 2], [3, 4]]
78
+ for f in functions:
79
+ with pytest.raises(TypeError) as excinfo:
80
+ f(matrix_with_wrong_shape)
81
+ assert "incompatible function arguments" in str(excinfo.value)
82
+
83
+
84
+ def test_mutator_descriptors():
85
+ zr = np.arange(30, dtype="float32").reshape(5, 6) # row-major
86
+ zc = zr.reshape(6, 5).transpose() # column-major
87
+
88
+ m.fixed_mutator_r(zr)
89
+ m.fixed_mutator_c(zc)
90
+ m.fixed_mutator_a(zr)
91
+ m.fixed_mutator_a(zc)
92
+ with pytest.raises(TypeError) as excinfo:
93
+ m.fixed_mutator_r(zc)
94
+ assert (
95
+ "(arg0: numpy.ndarray[numpy.float32[5, 6],"
96
+ " flags.writeable, flags.c_contiguous]) -> None" in str(excinfo.value)
97
+ )
98
+ with pytest.raises(TypeError) as excinfo:
99
+ m.fixed_mutator_c(zr)
100
+ assert (
101
+ "(arg0: numpy.ndarray[numpy.float32[5, 6],"
102
+ " flags.writeable, flags.f_contiguous]) -> None" in str(excinfo.value)
103
+ )
104
+ with pytest.raises(TypeError) as excinfo:
105
+ m.fixed_mutator_a(np.array([[1, 2], [3, 4]], dtype="float32"))
106
+ assert "(arg0: numpy.ndarray[numpy.float32[5, 6], flags.writeable]) -> None" in str(
107
+ excinfo.value
108
+ )
109
+ zr.flags.writeable = False
110
+ with pytest.raises(TypeError):
111
+ m.fixed_mutator_r(zr)
112
+ with pytest.raises(TypeError):
113
+ m.fixed_mutator_a(zr)
114
+
115
+
116
+ def test_cpp_casting():
117
+ assert m.cpp_copy(m.fixed_r()) == 22.0
118
+ assert m.cpp_copy(m.fixed_c()) == 22.0
119
+ z = np.array([[5.0, 6], [7, 8]])
120
+ assert m.cpp_copy(z) == 7.0
121
+ assert m.cpp_copy(m.get_cm_ref()) == 21.0
122
+ assert m.cpp_copy(m.get_rm_ref()) == 21.0
123
+ assert m.cpp_ref_c(m.get_cm_ref()) == 21.0
124
+ assert m.cpp_ref_r(m.get_rm_ref()) == 21.0
125
+ with pytest.raises(RuntimeError) as excinfo:
126
+ # Can't reference m.fixed_c: it contains floats, m.cpp_ref_any wants doubles
127
+ m.cpp_ref_any(m.fixed_c())
128
+ assert "Unable to cast Python instance" in str(excinfo.value)
129
+ with pytest.raises(RuntimeError) as excinfo:
130
+ # Can't reference m.fixed_r: it contains floats, m.cpp_ref_any wants doubles
131
+ m.cpp_ref_any(m.fixed_r())
132
+ assert "Unable to cast Python instance" in str(excinfo.value)
133
+ assert m.cpp_ref_any(m.ReturnTester.create()) == 1.0
134
+
135
+ assert m.cpp_ref_any(m.get_cm_ref()) == 21.0
136
+ assert m.cpp_ref_any(m.get_cm_ref()) == 21.0
137
+
138
+
139
+ def test_pass_readonly_array():
140
+ z = np.full((5, 6), 42.0)
141
+ z.flags.writeable = False
142
+ np.testing.assert_array_equal(z, m.fixed_copy_r(z))
143
+ np.testing.assert_array_equal(m.fixed_r_const(), m.fixed_r())
144
+ assert not m.fixed_r_const().flags.writeable
145
+ np.testing.assert_array_equal(m.fixed_copy_r(m.fixed_r_const()), m.fixed_r_const())
146
+
147
+
148
+ def test_nonunit_stride_from_python():
149
+ counting_mat = np.arange(9.0, dtype=np.float32).reshape((3, 3))
150
+ second_row = counting_mat[1, :]
151
+ second_col = counting_mat[:, 1]
152
+ np.testing.assert_array_equal(m.double_row(second_row), 2.0 * second_row)
153
+ np.testing.assert_array_equal(m.double_col(second_row), 2.0 * second_row)
154
+ np.testing.assert_array_equal(m.double_complex(second_row), 2.0 * second_row)
155
+ np.testing.assert_array_equal(m.double_row(second_col), 2.0 * second_col)
156
+ np.testing.assert_array_equal(m.double_col(second_col), 2.0 * second_col)
157
+ np.testing.assert_array_equal(m.double_complex(second_col), 2.0 * second_col)
158
+
159
+ counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
160
+ slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
161
+ for ref_mat in slices:
162
+ np.testing.assert_array_equal(m.double_mat_cm(ref_mat), 2.0 * ref_mat)
163
+ np.testing.assert_array_equal(m.double_mat_rm(ref_mat), 2.0 * ref_mat)
164
+
165
+ # Mutator:
166
+ m.double_threer(second_row)
167
+ m.double_threec(second_col)
168
+ np.testing.assert_array_equal(counting_mat, [[0.0, 2, 2], [6, 16, 10], [6, 14, 8]])
169
+
170
+
171
+ def test_negative_stride_from_python(msg):
172
+ """Eigen doesn't support (as of yet) negative strides. When a function takes an Eigen matrix by
173
+ copy or const reference, we can pass a numpy array that has negative strides. Otherwise, an
174
+ exception will be thrown as Eigen will not be able to map the numpy array."""
175
+
176
+ counting_mat = np.arange(9.0, dtype=np.float32).reshape((3, 3))
177
+ counting_mat = counting_mat[::-1, ::-1]
178
+ second_row = counting_mat[1, :]
179
+ second_col = counting_mat[:, 1]
180
+ np.testing.assert_array_equal(m.double_row(second_row), 2.0 * second_row)
181
+ np.testing.assert_array_equal(m.double_col(second_row), 2.0 * second_row)
182
+ np.testing.assert_array_equal(m.double_complex(second_row), 2.0 * second_row)
183
+ np.testing.assert_array_equal(m.double_row(second_col), 2.0 * second_col)
184
+ np.testing.assert_array_equal(m.double_col(second_col), 2.0 * second_col)
185
+ np.testing.assert_array_equal(m.double_complex(second_col), 2.0 * second_col)
186
+
187
+ counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
188
+ counting_3d = counting_3d[::-1, ::-1, ::-1]
189
+ slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
190
+ for ref_mat in slices:
191
+ np.testing.assert_array_equal(m.double_mat_cm(ref_mat), 2.0 * ref_mat)
192
+ np.testing.assert_array_equal(m.double_mat_rm(ref_mat), 2.0 * ref_mat)
193
+
194
+ # Mutator:
195
+ with pytest.raises(TypeError) as excinfo:
196
+ m.double_threer(second_row)
197
+ assert (
198
+ msg(excinfo.value)
199
+ == """
200
+ double_threer(): incompatible function arguments. The following argument types are supported:
201
+ 1. (arg0: numpy.ndarray[numpy.float32[1, 3], flags.writeable]) -> None
202
+
203
+ Invoked with: """
204
+ + repr(np.array([5.0, 4.0, 3.0], dtype="float32"))
205
+ )
206
+
207
+ with pytest.raises(TypeError) as excinfo:
208
+ m.double_threec(second_col)
209
+ assert (
210
+ msg(excinfo.value)
211
+ == """
212
+ double_threec(): incompatible function arguments. The following argument types are supported:
213
+ 1. (arg0: numpy.ndarray[numpy.float32[3, 1], flags.writeable]) -> None
214
+
215
+ Invoked with: """
216
+ + repr(np.array([7.0, 4.0, 1.0], dtype="float32"))
217
+ )
218
+
219
+
220
+ def test_block_runtime_error_type_caster_eigen_ref_made_a_copy():
221
+ with pytest.raises(RuntimeError) as excinfo:
222
+ m.block(ref, 0, 0, 0, 0)
223
+ assert str(excinfo.value) == "type_caster for Eigen::Ref made a copy."
224
+
225
+
226
+ def test_nonunit_stride_to_python():
227
+ assert np.all(m.diagonal(ref) == ref.diagonal())
228
+ assert np.all(m.diagonal_1(ref) == ref.diagonal(1))
229
+ for i in range(-5, 7):
230
+ assert np.all(m.diagonal_n(ref, i) == ref.diagonal(i)), f"m.diagonal_n({i})"
231
+
232
+ # Must be order="F", otherwise the type_caster will make a copy and
233
+ # m.block() will return a dangling reference (heap-use-after-free).
234
+ rof = np.asarray(ref, order="F")
235
+ assert np.all(m.block(rof, 2, 1, 3, 3) == rof[2:5, 1:4])
236
+ assert np.all(m.block(rof, 1, 4, 4, 2) == rof[1:, 4:])
237
+ assert np.all(m.block(rof, 1, 4, 3, 2) == rof[1:4, 4:])
238
+
239
+
240
+ def test_eigen_ref_to_python():
241
+ chols = [m.cholesky1, m.cholesky2, m.cholesky3, m.cholesky4]
242
+ for i, chol in enumerate(chols, start=1):
243
+ mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
244
+ assert np.all(
245
+ mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])
246
+ ), f"cholesky{i}"
247
+
248
+
249
+ def assign_both(a1, a2, r, c, v):
250
+ a1[r, c] = v
251
+ a2[r, c] = v
252
+
253
+
254
+ def array_copy_but_one(a, r, c, v):
255
+ z = np.array(a, copy=True)
256
+ z[r, c] = v
257
+ return z
258
+
259
+
260
+ def test_eigen_return_references():
261
+ """Tests various ways of returning references and non-referencing copies"""
262
+
263
+ primary = np.ones((10, 10))
264
+ a = m.ReturnTester()
265
+ a_get1 = a.get()
266
+ assert not a_get1.flags.owndata
267
+ assert a_get1.flags.writeable
268
+ assign_both(a_get1, primary, 3, 3, 5)
269
+ a_get2 = a.get_ptr()
270
+ assert not a_get2.flags.owndata
271
+ assert a_get2.flags.writeable
272
+ assign_both(a_get1, primary, 2, 3, 6)
273
+
274
+ a_view1 = a.view()
275
+ assert not a_view1.flags.owndata
276
+ assert not a_view1.flags.writeable
277
+ with pytest.raises(ValueError):
278
+ a_view1[2, 3] = 4
279
+ a_view2 = a.view_ptr()
280
+ assert not a_view2.flags.owndata
281
+ assert not a_view2.flags.writeable
282
+ with pytest.raises(ValueError):
283
+ a_view2[2, 3] = 4
284
+
285
+ a_copy1 = a.copy_get()
286
+ assert a_copy1.flags.owndata
287
+ assert a_copy1.flags.writeable
288
+ np.testing.assert_array_equal(a_copy1, primary)
289
+ a_copy1[7, 7] = -44 # Shouldn't affect anything else
290
+ c1want = array_copy_but_one(primary, 7, 7, -44)
291
+ a_copy2 = a.copy_view()
292
+ assert a_copy2.flags.owndata
293
+ assert a_copy2.flags.writeable
294
+ np.testing.assert_array_equal(a_copy2, primary)
295
+ a_copy2[4, 4] = -22 # Shouldn't affect anything else
296
+ c2want = array_copy_but_one(primary, 4, 4, -22)
297
+
298
+ a_ref1 = a.ref()
299
+ assert not a_ref1.flags.owndata
300
+ assert a_ref1.flags.writeable
301
+ assign_both(a_ref1, primary, 1, 1, 15)
302
+ a_ref2 = a.ref_const()
303
+ assert not a_ref2.flags.owndata
304
+ assert not a_ref2.flags.writeable
305
+ with pytest.raises(ValueError):
306
+ a_ref2[5, 5] = 33
307
+ a_ref3 = a.ref_safe()
308
+ assert not a_ref3.flags.owndata
309
+ assert a_ref3.flags.writeable
310
+ assign_both(a_ref3, primary, 0, 7, 99)
311
+ a_ref4 = a.ref_const_safe()
312
+ assert not a_ref4.flags.owndata
313
+ assert not a_ref4.flags.writeable
314
+ with pytest.raises(ValueError):
315
+ a_ref4[7, 0] = 987654321
316
+
317
+ a_copy3 = a.copy_ref()
318
+ assert a_copy3.flags.owndata
319
+ assert a_copy3.flags.writeable
320
+ np.testing.assert_array_equal(a_copy3, primary)
321
+ a_copy3[8, 1] = 11
322
+ c3want = array_copy_but_one(primary, 8, 1, 11)
323
+ a_copy4 = a.copy_ref_const()
324
+ assert a_copy4.flags.owndata
325
+ assert a_copy4.flags.writeable
326
+ np.testing.assert_array_equal(a_copy4, primary)
327
+ a_copy4[8, 4] = 88
328
+ c4want = array_copy_but_one(primary, 8, 4, 88)
329
+
330
+ a_block1 = a.block(3, 3, 2, 2)
331
+ assert not a_block1.flags.owndata
332
+ assert a_block1.flags.writeable
333
+ a_block1[0, 0] = 55
334
+ primary[3, 3] = 55
335
+ a_block2 = a.block_safe(2, 2, 3, 2)
336
+ assert not a_block2.flags.owndata
337
+ assert a_block2.flags.writeable
338
+ a_block2[2, 1] = -123
339
+ primary[4, 3] = -123
340
+ a_block3 = a.block_const(6, 7, 4, 3)
341
+ assert not a_block3.flags.owndata
342
+ assert not a_block3.flags.writeable
343
+ with pytest.raises(ValueError):
344
+ a_block3[2, 2] = -44444
345
+
346
+ a_copy5 = a.copy_block(2, 2, 2, 3)
347
+ assert a_copy5.flags.owndata
348
+ assert a_copy5.flags.writeable
349
+ np.testing.assert_array_equal(a_copy5, primary[2:4, 2:5])
350
+ a_copy5[1, 1] = 777
351
+ c5want = array_copy_but_one(primary[2:4, 2:5], 1, 1, 777)
352
+
353
+ a_corn1 = a.corners()
354
+ assert not a_corn1.flags.owndata
355
+ assert a_corn1.flags.writeable
356
+ a_corn1 *= 50
357
+ a_corn1[1, 1] = 999
358
+ primary[0, 0] = 50
359
+ primary[0, 9] = 50
360
+ primary[9, 0] = 50
361
+ primary[9, 9] = 999
362
+ a_corn2 = a.corners_const()
363
+ assert not a_corn2.flags.owndata
364
+ assert not a_corn2.flags.writeable
365
+ with pytest.raises(ValueError):
366
+ a_corn2[1, 0] = 51
367
+
368
+ # All of the changes made all the way along should be visible everywhere
369
+ # now (except for the copies, of course)
370
+ np.testing.assert_array_equal(a_get1, primary)
371
+ np.testing.assert_array_equal(a_get2, primary)
372
+ np.testing.assert_array_equal(a_view1, primary)
373
+ np.testing.assert_array_equal(a_view2, primary)
374
+ np.testing.assert_array_equal(a_ref1, primary)
375
+ np.testing.assert_array_equal(a_ref2, primary)
376
+ np.testing.assert_array_equal(a_ref3, primary)
377
+ np.testing.assert_array_equal(a_ref4, primary)
378
+ np.testing.assert_array_equal(a_block1, primary[3:5, 3:5])
379
+ np.testing.assert_array_equal(a_block2, primary[2:5, 2:4])
380
+ np.testing.assert_array_equal(a_block3, primary[6:10, 7:10])
381
+ np.testing.assert_array_equal(
382
+ a_corn1, primary[0 :: primary.shape[0] - 1, 0 :: primary.shape[1] - 1]
383
+ )
384
+ np.testing.assert_array_equal(
385
+ a_corn2, primary[0 :: primary.shape[0] - 1, 0 :: primary.shape[1] - 1]
386
+ )
387
+
388
+ np.testing.assert_array_equal(a_copy1, c1want)
389
+ np.testing.assert_array_equal(a_copy2, c2want)
390
+ np.testing.assert_array_equal(a_copy3, c3want)
391
+ np.testing.assert_array_equal(a_copy4, c4want)
392
+ np.testing.assert_array_equal(a_copy5, c5want)
393
+
394
+
395
+ def assert_keeps_alive(cl, method, *args):
396
+ cstats = ConstructorStats.get(cl)
397
+ start_with = cstats.alive()
398
+ a = cl()
399
+ assert cstats.alive() == start_with + 1
400
+ z = method(a, *args)
401
+ assert cstats.alive() == start_with + 1
402
+ del a
403
+ # Here's the keep alive in action:
404
+ assert cstats.alive() == start_with + 1
405
+ del z
406
+ # Keep alive should have expired:
407
+ assert cstats.alive() == start_with
408
+
409
+
410
+ def test_eigen_keepalive():
411
+ a = m.ReturnTester()
412
+ cstats = ConstructorStats.get(m.ReturnTester)
413
+ assert cstats.alive() == 1
414
+ unsafe = [a.ref(), a.ref_const(), a.block(1, 2, 3, 4)]
415
+ copies = [
416
+ a.copy_get(),
417
+ a.copy_view(),
418
+ a.copy_ref(),
419
+ a.copy_ref_const(),
420
+ a.copy_block(4, 3, 2, 1),
421
+ ]
422
+ del a
423
+ assert cstats.alive() == 0
424
+ del unsafe
425
+ del copies
426
+
427
+ for meth in [
428
+ m.ReturnTester.get,
429
+ m.ReturnTester.get_ptr,
430
+ m.ReturnTester.view,
431
+ m.ReturnTester.view_ptr,
432
+ m.ReturnTester.ref_safe,
433
+ m.ReturnTester.ref_const_safe,
434
+ m.ReturnTester.corners,
435
+ m.ReturnTester.corners_const,
436
+ ]:
437
+ assert_keeps_alive(m.ReturnTester, meth)
438
+
439
+ for meth in [m.ReturnTester.block_safe, m.ReturnTester.block_const]:
440
+ assert_keeps_alive(m.ReturnTester, meth, 4, 3, 2, 1)
441
+
442
+
443
+ def test_eigen_ref_mutators():
444
+ """Tests Eigen's ability to mutate numpy values"""
445
+
446
+ orig = np.array([[1.0, 2, 3], [4, 5, 6], [7, 8, 9]])
447
+ zr = np.array(orig)
448
+ zc = np.array(orig, order="F")
449
+ m.add_rm(zr, 1, 0, 100)
450
+ assert np.all(zr == np.array([[1.0, 2, 3], [104, 5, 6], [7, 8, 9]]))
451
+ m.add_cm(zc, 1, 0, 200)
452
+ assert np.all(zc == np.array([[1.0, 2, 3], [204, 5, 6], [7, 8, 9]]))
453
+
454
+ m.add_any(zr, 1, 0, 20)
455
+ assert np.all(zr == np.array([[1.0, 2, 3], [124, 5, 6], [7, 8, 9]]))
456
+ m.add_any(zc, 1, 0, 10)
457
+ assert np.all(zc == np.array([[1.0, 2, 3], [214, 5, 6], [7, 8, 9]]))
458
+
459
+ # Can't reference a col-major array with a row-major Ref, and vice versa:
460
+ with pytest.raises(TypeError):
461
+ m.add_rm(zc, 1, 0, 1)
462
+ with pytest.raises(TypeError):
463
+ m.add_cm(zr, 1, 0, 1)
464
+
465
+ # Overloads:
466
+ m.add1(zr, 1, 0, -100)
467
+ m.add2(zr, 1, 0, -20)
468
+ assert np.all(zr == orig)
469
+ m.add1(zc, 1, 0, -200)
470
+ m.add2(zc, 1, 0, -10)
471
+ assert np.all(zc == orig)
472
+
473
+ # a non-contiguous slice (this won't work on either the row- or
474
+ # column-contiguous refs, but should work for the any)
475
+ cornersr = zr[0::2, 0::2]
476
+ cornersc = zc[0::2, 0::2]
477
+
478
+ assert np.all(cornersr == np.array([[1.0, 3], [7, 9]]))
479
+ assert np.all(cornersc == np.array([[1.0, 3], [7, 9]]))
480
+
481
+ with pytest.raises(TypeError):
482
+ m.add_rm(cornersr, 0, 1, 25)
483
+ with pytest.raises(TypeError):
484
+ m.add_cm(cornersr, 0, 1, 25)
485
+ with pytest.raises(TypeError):
486
+ m.add_rm(cornersc, 0, 1, 25)
487
+ with pytest.raises(TypeError):
488
+ m.add_cm(cornersc, 0, 1, 25)
489
+ m.add_any(cornersr, 0, 1, 25)
490
+ m.add_any(cornersc, 0, 1, 44)
491
+ assert np.all(zr == np.array([[1.0, 2, 28], [4, 5, 6], [7, 8, 9]]))
492
+ assert np.all(zc == np.array([[1.0, 2, 47], [4, 5, 6], [7, 8, 9]]))
493
+
494
+ # You shouldn't be allowed to pass a non-writeable array to a mutating Eigen method:
495
+ zro = zr[0:4, 0:4]
496
+ zro.flags.writeable = False
497
+ with pytest.raises(TypeError):
498
+ m.add_rm(zro, 0, 0, 0)
499
+ with pytest.raises(TypeError):
500
+ m.add_any(zro, 0, 0, 0)
501
+ with pytest.raises(TypeError):
502
+ m.add1(zro, 0, 0, 0)
503
+ with pytest.raises(TypeError):
504
+ m.add2(zro, 0, 0, 0)
505
+
506
+ # integer array shouldn't be passable to a double-matrix-accepting mutating func:
507
+ zi = np.array([[1, 2], [3, 4]])
508
+ with pytest.raises(TypeError):
509
+ m.add_rm(zi)
510
+
511
+
512
+ def test_numpy_ref_mutators():
513
+ """Tests numpy mutating Eigen matrices (for returned Eigen::Ref<...>s)"""
514
+
515
+ m.reset_refs() # In case another test already changed it
516
+
517
+ zc = m.get_cm_ref()
518
+ zcro = m.get_cm_const_ref()
519
+ zr = m.get_rm_ref()
520
+ zrro = m.get_rm_const_ref()
521
+
522
+ assert [zc[1, 2], zcro[1, 2], zr[1, 2], zrro[1, 2]] == [23] * 4
523
+
524
+ assert not zc.flags.owndata
525
+ assert zc.flags.writeable
526
+ assert not zr.flags.owndata
527
+ assert zr.flags.writeable
528
+ assert not zcro.flags.owndata
529
+ assert not zcro.flags.writeable
530
+ assert not zrro.flags.owndata
531
+ assert not zrro.flags.writeable
532
+
533
+ zc[1, 2] = 99
534
+ expect = np.array([[11.0, 12, 13], [21, 22, 99], [31, 32, 33]])
535
+ # We should have just changed zc, of course, but also zcro and the original eigen matrix
536
+ assert np.all(zc == expect)
537
+ assert np.all(zcro == expect)
538
+ assert np.all(m.get_cm_ref() == expect)
539
+
540
+ zr[1, 2] = 99
541
+ assert np.all(zr == expect)
542
+ assert np.all(zrro == expect)
543
+ assert np.all(m.get_rm_ref() == expect)
544
+
545
+ # Make sure the readonly ones are numpy-readonly:
546
+ with pytest.raises(ValueError):
547
+ zcro[1, 2] = 6
548
+ with pytest.raises(ValueError):
549
+ zrro[1, 2] = 6
550
+
551
+ # We should be able to explicitly copy like this (and since we're copying,
552
+ # the const should drop away)
553
+ y1 = np.array(m.get_cm_const_ref())
554
+
555
+ assert y1.flags.owndata
556
+ assert y1.flags.writeable
557
+ # We should get copies of the eigen data, which was modified above:
558
+ assert y1[1, 2] == 99
559
+ y1[1, 2] += 12
560
+ assert y1[1, 2] == 111
561
+ assert zc[1, 2] == 99 # Make sure we aren't referencing the original
562
+
563
+
564
+ def test_both_ref_mutators():
565
+ """Tests a complex chain of nested eigen/numpy references"""
566
+
567
+ m.reset_refs() # In case another test already changed it
568
+
569
+ z = m.get_cm_ref() # numpy -> eigen
570
+ z[0, 2] -= 3
571
+ z2 = m.incr_matrix(z, 1) # numpy -> eigen -> numpy -> eigen
572
+ z2[1, 1] += 6
573
+ z3 = m.incr_matrix(z, 2) # (numpy -> eigen)^3
574
+ z3[2, 2] += -5
575
+ z4 = m.incr_matrix(z, 3) # (numpy -> eigen)^4
576
+ z4[1, 1] -= 1
577
+ z5 = m.incr_matrix(z, 4) # (numpy -> eigen)^5
578
+ z5[0, 0] = 0
579
+ assert np.all(z == z2)
580
+ assert np.all(z == z3)
581
+ assert np.all(z == z4)
582
+ assert np.all(z == z5)
583
+ expect = np.array([[0.0, 22, 20], [31, 37, 33], [41, 42, 38]])
584
+ assert np.all(z == expect)
585
+
586
+ y = np.array(range(100), dtype="float64").reshape(10, 10)
587
+ y2 = m.incr_matrix_any(y, 10) # np -> eigen -> np
588
+ y3 = m.incr_matrix_any(
589
+ y2[0::2, 0::2], -33
590
+ ) # np -> eigen -> np slice -> np -> eigen -> np
591
+ y4 = m.even_rows(y3) # numpy -> eigen slice -> (... y3)
592
+ y5 = m.even_cols(y4) # numpy -> eigen slice -> (... y4)
593
+ y6 = m.incr_matrix_any(y5, 1000) # numpy -> eigen -> (... y5)
594
+
595
+ # Apply same mutations using just numpy:
596
+ yexpect = np.array(range(100), dtype="float64").reshape(10, 10)
597
+ yexpect += 10
598
+ yexpect[0::2, 0::2] -= 33
599
+ yexpect[0::4, 0::4] += 1000
600
+ assert np.all(y6 == yexpect[0::4, 0::4])
601
+ assert np.all(y5 == yexpect[0::4, 0::4])
602
+ assert np.all(y4 == yexpect[0::4, 0::2])
603
+ assert np.all(y3 == yexpect[0::2, 0::2])
604
+ assert np.all(y2 == yexpect)
605
+ assert np.all(y == yexpect)
606
+
607
+
608
+ def test_nocopy_wrapper():
609
+ # get_elem requires a column-contiguous matrix reference, but should be
610
+ # callable with other types of matrix (via copying):
611
+ int_matrix_colmajor = np.array(
612
+ [[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype="l", order="F"
613
+ )
614
+ dbl_matrix_colmajor = np.array(
615
+ int_matrix_colmajor, dtype="double", order="F", copy=True
616
+ )
617
+ int_matrix_rowmajor = np.array(int_matrix_colmajor, order="C", copy=True)
618
+ dbl_matrix_rowmajor = np.array(
619
+ int_matrix_rowmajor, dtype="double", order="C", copy=True
620
+ )
621
+
622
+ # All should be callable via get_elem:
623
+ assert m.get_elem(int_matrix_colmajor) == 8
624
+ assert m.get_elem(dbl_matrix_colmajor) == 8
625
+ assert m.get_elem(int_matrix_rowmajor) == 8
626
+ assert m.get_elem(dbl_matrix_rowmajor) == 8
627
+
628
+ # All but the second should fail with m.get_elem_nocopy:
629
+ with pytest.raises(TypeError) as excinfo:
630
+ m.get_elem_nocopy(int_matrix_colmajor)
631
+ assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
632
+ assert ", flags.f_contiguous" in str(excinfo.value)
633
+ assert m.get_elem_nocopy(dbl_matrix_colmajor) == 8
634
+ with pytest.raises(TypeError) as excinfo:
635
+ m.get_elem_nocopy(int_matrix_rowmajor)
636
+ assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
637
+ assert ", flags.f_contiguous" in str(excinfo.value)
638
+ with pytest.raises(TypeError) as excinfo:
639
+ m.get_elem_nocopy(dbl_matrix_rowmajor)
640
+ assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
641
+ assert ", flags.f_contiguous" in str(excinfo.value)
642
+
643
+ # For the row-major test, we take a long matrix in row-major, so only the third is allowed:
644
+ with pytest.raises(TypeError) as excinfo:
645
+ m.get_elem_rm_nocopy(int_matrix_colmajor)
646
+ assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
647
+ excinfo.value
648
+ )
649
+ assert ", flags.c_contiguous" in str(excinfo.value)
650
+ with pytest.raises(TypeError) as excinfo:
651
+ m.get_elem_rm_nocopy(dbl_matrix_colmajor)
652
+ assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
653
+ excinfo.value
654
+ )
655
+ assert ", flags.c_contiguous" in str(excinfo.value)
656
+ assert m.get_elem_rm_nocopy(int_matrix_rowmajor) == 8
657
+ with pytest.raises(TypeError) as excinfo:
658
+ m.get_elem_rm_nocopy(dbl_matrix_rowmajor)
659
+ assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
660
+ excinfo.value
661
+ )
662
+ assert ", flags.c_contiguous" in str(excinfo.value)
663
+
664
+
665
+ def test_eigen_ref_life_support():
666
+ """Ensure the lifetime of temporary arrays created by the `Ref` caster
667
+
668
+ The `Ref` caster sometimes creates a copy which needs to stay alive. This needs to
669
+ happen both for directs casts (just the array) or indirectly (e.g. list of arrays).
670
+ """
671
+
672
+ a = np.full(shape=10, fill_value=8, dtype=np.int8)
673
+ assert m.get_elem_direct(a) == 8
674
+
675
+ list_of_a = [a]
676
+ assert m.get_elem_indirect(list_of_a) == 8
677
+
678
+
679
+ def test_special_matrix_objects():
680
+ assert np.all(m.incr_diag(7) == np.diag([1.0, 2, 3, 4, 5, 6, 7]))
681
+
682
+ asymm = np.array([[1.0, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
683
+ symm_lower = np.array(asymm)
684
+ symm_upper = np.array(asymm)
685
+ for i in range(4):
686
+ for j in range(i + 1, 4):
687
+ symm_lower[i, j] = symm_lower[j, i]
688
+ symm_upper[j, i] = symm_upper[i, j]
689
+
690
+ assert np.all(m.symmetric_lower(asymm) == symm_lower)
691
+ assert np.all(m.symmetric_upper(asymm) == symm_upper)
692
+
693
+
694
+ def test_dense_signature(doc):
695
+ assert (
696
+ doc(m.double_col)
697
+ == """
698
+ double_col(arg0: numpy.ndarray[numpy.float32[m, 1]]) -> numpy.ndarray[numpy.float32[m, 1]]
699
+ """
700
+ )
701
+ assert (
702
+ doc(m.double_row)
703
+ == """
704
+ double_row(arg0: numpy.ndarray[numpy.float32[1, n]]) -> numpy.ndarray[numpy.float32[1, n]]
705
+ """
706
+ )
707
+ assert doc(m.double_complex) == (
708
+ """
709
+ double_complex(arg0: numpy.ndarray[numpy.complex64[m, 1]])"""
710
+ """ -> numpy.ndarray[numpy.complex64[m, 1]]
711
+ """
712
+ )
713
+ assert doc(m.double_mat_rm) == (
714
+ """
715
+ double_mat_rm(arg0: numpy.ndarray[numpy.float32[m, n]])"""
716
+ """ -> numpy.ndarray[numpy.float32[m, n]]
717
+ """
718
+ )
719
+
720
+
721
+ def test_defaults(doc):
722
+ assert "\n" not in str(doc(m.defaults_mat))
723
+ assert "\n" not in str(doc(m.defaults_vec))
724
+
725
+
726
+ def test_named_arguments():
727
+ a = np.array([[1.0, 2], [3, 4], [5, 6]])
728
+ b = np.ones((2, 1))
729
+
730
+ assert np.all(m.matrix_multiply(a, b) == np.array([[3.0], [7], [11]]))
731
+ assert np.all(m.matrix_multiply(A=a, B=b) == np.array([[3.0], [7], [11]]))
732
+ assert np.all(m.matrix_multiply(B=b, A=a) == np.array([[3.0], [7], [11]]))
733
+
734
+ with pytest.raises(ValueError) as excinfo:
735
+ m.matrix_multiply(b, a)
736
+ assert str(excinfo.value) == "Nonconformable matrices!"
737
+
738
+ with pytest.raises(ValueError) as excinfo:
739
+ m.matrix_multiply(A=b, B=a)
740
+ assert str(excinfo.value) == "Nonconformable matrices!"
741
+
742
+ with pytest.raises(ValueError) as excinfo:
743
+ m.matrix_multiply(B=a, A=b)
744
+ assert str(excinfo.value) == "Nonconformable matrices!"
745
+
746
+
747
+ def test_sparse():
748
+ pytest.importorskip("scipy")
749
+ assert_sparse_equal_ref(m.sparse_r())
750
+ assert_sparse_equal_ref(m.sparse_c())
751
+ assert_sparse_equal_ref(m.sparse_copy_r(m.sparse_r()))
752
+ assert_sparse_equal_ref(m.sparse_copy_c(m.sparse_c()))
753
+ assert_sparse_equal_ref(m.sparse_copy_r(m.sparse_c()))
754
+ assert_sparse_equal_ref(m.sparse_copy_c(m.sparse_r()))
755
+
756
+
757
+ def test_sparse_signature(doc):
758
+ pytest.importorskip("scipy")
759
+ assert (
760
+ doc(m.sparse_copy_r)
761
+ == """
762
+ sparse_copy_r(arg0: scipy.sparse.csr_matrix[numpy.float32]) -> scipy.sparse.csr_matrix[numpy.float32]
763
+ """
764
+ )
765
+ assert (
766
+ doc(m.sparse_copy_c)
767
+ == """
768
+ sparse_copy_c(arg0: scipy.sparse.csc_matrix[numpy.float32]) -> scipy.sparse.csc_matrix[numpy.float32]
769
+ """
770
+ )
771
+
772
+
773
+ def test_issue738():
774
+ """Ignore strides on a length-1 dimension (even if they would be incompatible length > 1)"""
775
+ assert np.all(m.iss738_f1(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]]))
776
+ assert np.all(
777
+ m.iss738_f1(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]])
778
+ )
779
+
780
+ assert np.all(m.iss738_f2(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]]))
781
+ assert np.all(
782
+ m.iss738_f2(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]])
783
+ )
784
+
785
+
786
+ @pytest.mark.parametrize("func", [m.iss738_f1, m.iss738_f2])
787
+ @pytest.mark.parametrize("sizes", [(0, 2), (2, 0)])
788
+ def test_zero_length(func, sizes):
789
+ """Ignore strides on a length-0 dimension (even if they would be incompatible length > 1)"""
790
+ assert np.all(func(np.zeros(sizes)) == np.zeros(sizes))
791
+
792
+
793
+ def test_issue1105():
794
+ """Issue 1105: 1xN or Nx1 input arrays weren't accepted for eigen
795
+ compile-time row vectors or column vector"""
796
+ assert m.iss1105_row(np.ones((1, 7)))
797
+ assert m.iss1105_col(np.ones((7, 1)))
798
+
799
+ # These should still fail (incompatible dimensions):
800
+ with pytest.raises(TypeError) as excinfo:
801
+ m.iss1105_row(np.ones((7, 1)))
802
+ assert "incompatible function arguments" in str(excinfo.value)
803
+ with pytest.raises(TypeError) as excinfo:
804
+ m.iss1105_col(np.ones((1, 7)))
805
+ assert "incompatible function arguments" in str(excinfo.value)
806
+
807
+
808
+ def test_custom_operator_new():
809
+ """Using Eigen types as member variables requires a class-specific
810
+ operator new with proper alignment"""
811
+
812
+ o = m.CustomOperatorNew()
813
+ np.testing.assert_allclose(o.a, 0.0)
814
+ np.testing.assert_allclose(o.b.diagonal(), 1.0)
third_party/CityFlow/extern/pybind11/tests/test_eigen_tensor.cpp CHANGED
@@ -1,18 +1,18 @@
1
- /*
2
- tests/eigen_tensor.cpp -- automatic conversion of Eigen Tensor
3
-
4
- All rights reserved. Use of this source code is governed by a
5
- BSD-style license that can be found in the LICENSE file.
6
- */
7
-
8
- #define PYBIND11_TEST_EIGEN_TENSOR_NAMESPACE eigen_tensor
9
-
10
- #ifdef EIGEN_AVOID_STL_ARRAY
11
- # undef EIGEN_AVOID_STL_ARRAY
12
- #endif
13
-
14
- #include "test_eigen_tensor.inl"
15
-
16
- #include "pybind11_tests.h"
17
-
18
- test_initializer egien_tensor("eigen_tensor", eigen_tensor_test::test_module);
 
1
+ /*
2
+ tests/eigen_tensor.cpp -- automatic conversion of Eigen Tensor
3
+
4
+ All rights reserved. Use of this source code is governed by a
5
+ BSD-style license that can be found in the LICENSE file.
6
+ */
7
+
8
+ #define PYBIND11_TEST_EIGEN_TENSOR_NAMESPACE eigen_tensor
9
+
10
+ #ifdef EIGEN_AVOID_STL_ARRAY
11
+ # undef EIGEN_AVOID_STL_ARRAY
12
+ #endif
13
+
14
+ #include "test_eigen_tensor.inl"
15
+
16
+ #include "pybind11_tests.h"
17
+
18
+ test_initializer egien_tensor("eigen_tensor", eigen_tensor_test::test_module);
third_party/CityFlow/extern/pybind11/tests/test_eigen_tensor.inl CHANGED
@@ -1,333 +1,333 @@
1
- /*
2
- tests/eigen_tensor.cpp -- automatic conversion of Eigen Tensor
3
-
4
- All rights reserved. Use of this source code is governed by a
5
- BSD-style license that can be found in the LICENSE file.
6
- */
7
-
8
- #include <pybind11/eigen/tensor.h>
9
-
10
- PYBIND11_NAMESPACE_BEGIN(eigen_tensor_test)
11
-
12
- namespace py = pybind11;
13
-
14
- PYBIND11_WARNING_DISABLE_MSVC(4127)
15
-
16
- template <typename M>
17
- void reset_tensor(M &x) {
18
- for (int i = 0; i < x.dimension(0); i++) {
19
- for (int j = 0; j < x.dimension(1); j++) {
20
- for (int k = 0; k < x.dimension(2); k++) {
21
- x(i, j, k) = i * (5 * 2) + j * 2 + k;
22
- }
23
- }
24
- }
25
- }
26
-
27
- template <typename M>
28
- bool check_tensor(M &x) {
29
- for (int i = 0; i < x.dimension(0); i++) {
30
- for (int j = 0; j < x.dimension(1); j++) {
31
- for (int k = 0; k < x.dimension(2); k++) {
32
- if (x(i, j, k) != (i * (5 * 2) + j * 2 + k)) {
33
- return false;
34
- }
35
- }
36
- }
37
- }
38
- return true;
39
- }
40
-
41
- template <int Options>
42
- Eigen::Tensor<double, 3, Options> &get_tensor() {
43
- static Eigen::Tensor<double, 3, Options> *x;
44
-
45
- if (!x) {
46
- x = new Eigen::Tensor<double, 3, Options>(3, 5, 2);
47
- reset_tensor(*x);
48
- }
49
-
50
- return *x;
51
- }
52
-
53
- template <int Options>
54
- Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> &get_tensor_map() {
55
- static Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> *x;
56
-
57
- if (!x) {
58
- x = new Eigen::TensorMap<Eigen::Tensor<double, 3, Options>>(get_tensor<Options>());
59
- }
60
-
61
- return *x;
62
- }
63
-
64
- template <int Options>
65
- Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options> &get_fixed_tensor() {
66
- static Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options> *x;
67
-
68
- if (!x) {
69
- Eigen::aligned_allocator<Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>>
70
- allocator;
71
- x = new (allocator.allocate(1))
72
- Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>();
73
- reset_tensor(*x);
74
- }
75
-
76
- return *x;
77
- }
78
-
79
- template <int Options>
80
- const Eigen::Tensor<double, 3, Options> &get_const_tensor() {
81
- return get_tensor<Options>();
82
- }
83
-
84
- template <int Options>
85
- struct CustomExample {
86
- CustomExample() : member(get_tensor<Options>()), view_member(member) {}
87
-
88
- Eigen::Tensor<double, 3, Options> member;
89
- Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> view_member;
90
- };
91
-
92
- template <int Options>
93
- void init_tensor_module(pybind11::module &m) {
94
- const char *needed_options = "";
95
- if (Options == Eigen::ColMajor) {
96
- needed_options = "F";
97
- } else {
98
- needed_options = "C";
99
- }
100
- m.attr("needed_options") = needed_options;
101
-
102
- m.def("setup", []() {
103
- reset_tensor(get_tensor<Options>());
104
- reset_tensor(get_fixed_tensor<Options>());
105
- });
106
-
107
- m.def("is_ok", []() {
108
- return check_tensor(get_tensor<Options>()) && check_tensor(get_fixed_tensor<Options>());
109
- });
110
-
111
- py::class_<CustomExample<Options>>(m, "CustomExample", py::module_local())
112
- .def(py::init<>())
113
- .def_readonly(
114
- "member", &CustomExample<Options>::member, py::return_value_policy::reference_internal)
115
- .def_readonly("member_view",
116
- &CustomExample<Options>::view_member,
117
- py::return_value_policy::reference_internal);
118
-
119
- m.def(
120
- "copy_fixed_tensor",
121
- []() { return &get_fixed_tensor<Options>(); },
122
- py::return_value_policy::copy);
123
-
124
- m.def(
125
- "copy_tensor", []() { return &get_tensor<Options>(); }, py::return_value_policy::copy);
126
-
127
- m.def(
128
- "copy_const_tensor",
129
- []() { return &get_const_tensor<Options>(); },
130
- py::return_value_policy::copy);
131
-
132
- m.def(
133
- "move_fixed_tensor_copy",
134
- []() -> Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options> {
135
- return get_fixed_tensor<Options>();
136
- },
137
- py::return_value_policy::move);
138
-
139
- m.def(
140
- "move_tensor_copy",
141
- []() -> Eigen::Tensor<double, 3, Options> { return get_tensor<Options>(); },
142
- py::return_value_policy::move);
143
-
144
- m.def(
145
- "move_const_tensor",
146
- []() -> const Eigen::Tensor<double, 3, Options> & { return get_const_tensor<Options>(); },
147
- py::return_value_policy::move);
148
-
149
- m.def(
150
- "take_fixed_tensor",
151
-
152
- []() {
153
- Eigen::aligned_allocator<
154
- Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>>
155
- allocator;
156
- return new (allocator.allocate(1))
157
- Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>(
158
- get_fixed_tensor<Options>());
159
- },
160
- py::return_value_policy::take_ownership);
161
-
162
- m.def(
163
- "take_tensor",
164
- []() { return new Eigen::Tensor<double, 3, Options>(get_tensor<Options>()); },
165
- py::return_value_policy::take_ownership);
166
-
167
- m.def(
168
- "take_const_tensor",
169
- []() -> const Eigen::Tensor<double, 3, Options> * {
170
- return new Eigen::Tensor<double, 3, Options>(get_tensor<Options>());
171
- },
172
- py::return_value_policy::take_ownership);
173
-
174
- m.def(
175
- "take_view_tensor",
176
- []() -> const Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> * {
177
- return new Eigen::TensorMap<Eigen::Tensor<double, 3, Options>>(get_tensor<Options>());
178
- },
179
- py::return_value_policy::take_ownership);
180
-
181
- m.def(
182
- "reference_tensor",
183
- []() { return &get_tensor<Options>(); },
184
- py::return_value_policy::reference);
185
-
186
- m.def(
187
- "reference_tensor_v2",
188
- []() -> Eigen::Tensor<double, 3, Options> & { return get_tensor<Options>(); },
189
- py::return_value_policy::reference);
190
-
191
- m.def(
192
- "reference_tensor_internal",
193
- []() { return &get_tensor<Options>(); },
194
- py::return_value_policy::reference_internal);
195
-
196
- m.def(
197
- "reference_fixed_tensor",
198
- []() { return &get_tensor<Options>(); },
199
- py::return_value_policy::reference);
200
-
201
- m.def(
202
- "reference_const_tensor",
203
- []() { return &get_const_tensor<Options>(); },
204
- py::return_value_policy::reference);
205
-
206
- m.def(
207
- "reference_const_tensor_v2",
208
- []() -> const Eigen::Tensor<double, 3, Options> & { return get_const_tensor<Options>(); },
209
- py::return_value_policy::reference);
210
-
211
- m.def(
212
- "reference_view_of_tensor",
213
- []() -> Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> {
214
- return get_tensor_map<Options>();
215
- },
216
- py::return_value_policy::reference);
217
-
218
- m.def(
219
- "reference_view_of_tensor_v2",
220
- // NOLINTNEXTLINE(readability-const-return-type)
221
- []() -> const Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> {
222
- return get_tensor_map<Options>(); // NOLINT(readability-const-return-type)
223
- }, // NOLINT(readability-const-return-type)
224
- py::return_value_policy::reference);
225
-
226
- m.def(
227
- "reference_view_of_tensor_v3",
228
- []() -> Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> * {
229
- return &get_tensor_map<Options>();
230
- },
231
- py::return_value_policy::reference);
232
-
233
- m.def(
234
- "reference_view_of_tensor_v4",
235
- []() -> const Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> * {
236
- return &get_tensor_map<Options>();
237
- },
238
- py::return_value_policy::reference);
239
-
240
- m.def(
241
- "reference_view_of_tensor_v5",
242
- []() -> Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> & {
243
- return get_tensor_map<Options>();
244
- },
245
- py::return_value_policy::reference);
246
-
247
- m.def(
248
- "reference_view_of_tensor_v6",
249
- []() -> const Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> & {
250
- return get_tensor_map<Options>();
251
- },
252
- py::return_value_policy::reference);
253
-
254
- m.def(
255
- "reference_view_of_fixed_tensor",
256
- []() {
257
- return Eigen::TensorMap<
258
- Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>>(
259
- get_fixed_tensor<Options>());
260
- },
261
- py::return_value_policy::reference);
262
-
263
- m.def("round_trip_tensor",
264
- [](const Eigen::Tensor<double, 3, Options> &tensor) { return tensor; });
265
-
266
- m.def(
267
- "round_trip_tensor_noconvert",
268
- [](const Eigen::Tensor<double, 3, Options> &tensor) { return tensor; },
269
- py::arg("tensor").noconvert());
270
-
271
- m.def("round_trip_tensor2",
272
- [](const Eigen::Tensor<int32_t, 3, Options> &tensor) { return tensor; });
273
-
274
- m.def("round_trip_fixed_tensor",
275
- [](const Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options> &tensor) {
276
- return tensor;
277
- });
278
-
279
- m.def(
280
- "round_trip_view_tensor",
281
- [](Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> view) { return view; },
282
- py::return_value_policy::reference);
283
-
284
- m.def(
285
- "round_trip_view_tensor_ref",
286
- [](Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> &view) { return view; },
287
- py::return_value_policy::reference);
288
-
289
- m.def(
290
- "round_trip_view_tensor_ptr",
291
- [](Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> *view) { return view; },
292
- py::return_value_policy::reference);
293
-
294
- m.def(
295
- "round_trip_aligned_view_tensor",
296
- [](Eigen::TensorMap<Eigen::Tensor<double, 3, Options>, Eigen::Aligned> view) {
297
- return view;
298
- },
299
- py::return_value_policy::reference);
300
-
301
- m.def(
302
- "round_trip_const_view_tensor",
303
- [](Eigen::TensorMap<const Eigen::Tensor<double, 3, Options>> view) {
304
- return Eigen::Tensor<double, 3, Options>(view);
305
- },
306
- py::return_value_policy::move);
307
-
308
- m.def(
309
- "round_trip_rank_0",
310
- [](const Eigen::Tensor<double, 0, Options> &tensor) { return tensor; },
311
- py::return_value_policy::move);
312
-
313
- m.def(
314
- "round_trip_rank_0_noconvert",
315
- [](const Eigen::Tensor<double, 0, Options> &tensor) { return tensor; },
316
- py::arg("tensor").noconvert(),
317
- py::return_value_policy::move);
318
-
319
- m.def(
320
- "round_trip_rank_0_view",
321
- [](Eigen::TensorMap<Eigen::Tensor<double, 0, Options>> &tensor) { return tensor; },
322
- py::return_value_policy::reference);
323
- }
324
-
325
- void test_module(py::module_ &m) {
326
- auto f_style = m.def_submodule("f_style");
327
- auto c_style = m.def_submodule("c_style");
328
-
329
- init_tensor_module<Eigen::ColMajor>(f_style);
330
- init_tensor_module<Eigen::RowMajor>(c_style);
331
- }
332
-
333
- PYBIND11_NAMESPACE_END(eigen_tensor_test)
 
1
+ /*
2
+ tests/eigen_tensor.cpp -- automatic conversion of Eigen Tensor
3
+
4
+ All rights reserved. Use of this source code is governed by a
5
+ BSD-style license that can be found in the LICENSE file.
6
+ */
7
+
8
+ #include <pybind11/eigen/tensor.h>
9
+
10
+ PYBIND11_NAMESPACE_BEGIN(eigen_tensor_test)
11
+
12
+ namespace py = pybind11;
13
+
14
+ PYBIND11_WARNING_DISABLE_MSVC(4127)
15
+
16
+ template <typename M>
17
+ void reset_tensor(M &x) {
18
+ for (int i = 0; i < x.dimension(0); i++) {
19
+ for (int j = 0; j < x.dimension(1); j++) {
20
+ for (int k = 0; k < x.dimension(2); k++) {
21
+ x(i, j, k) = i * (5 * 2) + j * 2 + k;
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ template <typename M>
28
+ bool check_tensor(M &x) {
29
+ for (int i = 0; i < x.dimension(0); i++) {
30
+ for (int j = 0; j < x.dimension(1); j++) {
31
+ for (int k = 0; k < x.dimension(2); k++) {
32
+ if (x(i, j, k) != (i * (5 * 2) + j * 2 + k)) {
33
+ return false;
34
+ }
35
+ }
36
+ }
37
+ }
38
+ return true;
39
+ }
40
+
41
+ template <int Options>
42
+ Eigen::Tensor<double, 3, Options> &get_tensor() {
43
+ static Eigen::Tensor<double, 3, Options> *x;
44
+
45
+ if (!x) {
46
+ x = new Eigen::Tensor<double, 3, Options>(3, 5, 2);
47
+ reset_tensor(*x);
48
+ }
49
+
50
+ return *x;
51
+ }
52
+
53
+ template <int Options>
54
+ Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> &get_tensor_map() {
55
+ static Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> *x;
56
+
57
+ if (!x) {
58
+ x = new Eigen::TensorMap<Eigen::Tensor<double, 3, Options>>(get_tensor<Options>());
59
+ }
60
+
61
+ return *x;
62
+ }
63
+
64
+ template <int Options>
65
+ Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options> &get_fixed_tensor() {
66
+ static Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options> *x;
67
+
68
+ if (!x) {
69
+ Eigen::aligned_allocator<Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>>
70
+ allocator;
71
+ x = new (allocator.allocate(1))
72
+ Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>();
73
+ reset_tensor(*x);
74
+ }
75
+
76
+ return *x;
77
+ }
78
+
79
+ template <int Options>
80
+ const Eigen::Tensor<double, 3, Options> &get_const_tensor() {
81
+ return get_tensor<Options>();
82
+ }
83
+
84
+ template <int Options>
85
+ struct CustomExample {
86
+ CustomExample() : member(get_tensor<Options>()), view_member(member) {}
87
+
88
+ Eigen::Tensor<double, 3, Options> member;
89
+ Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> view_member;
90
+ };
91
+
92
+ template <int Options>
93
+ void init_tensor_module(pybind11::module &m) {
94
+ const char *needed_options = "";
95
+ if (Options == Eigen::ColMajor) {
96
+ needed_options = "F";
97
+ } else {
98
+ needed_options = "C";
99
+ }
100
+ m.attr("needed_options") = needed_options;
101
+
102
+ m.def("setup", []() {
103
+ reset_tensor(get_tensor<Options>());
104
+ reset_tensor(get_fixed_tensor<Options>());
105
+ });
106
+
107
+ m.def("is_ok", []() {
108
+ return check_tensor(get_tensor<Options>()) && check_tensor(get_fixed_tensor<Options>());
109
+ });
110
+
111
+ py::class_<CustomExample<Options>>(m, "CustomExample", py::module_local())
112
+ .def(py::init<>())
113
+ .def_readonly(
114
+ "member", &CustomExample<Options>::member, py::return_value_policy::reference_internal)
115
+ .def_readonly("member_view",
116
+ &CustomExample<Options>::view_member,
117
+ py::return_value_policy::reference_internal);
118
+
119
+ m.def(
120
+ "copy_fixed_tensor",
121
+ []() { return &get_fixed_tensor<Options>(); },
122
+ py::return_value_policy::copy);
123
+
124
+ m.def(
125
+ "copy_tensor", []() { return &get_tensor<Options>(); }, py::return_value_policy::copy);
126
+
127
+ m.def(
128
+ "copy_const_tensor",
129
+ []() { return &get_const_tensor<Options>(); },
130
+ py::return_value_policy::copy);
131
+
132
+ m.def(
133
+ "move_fixed_tensor_copy",
134
+ []() -> Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options> {
135
+ return get_fixed_tensor<Options>();
136
+ },
137
+ py::return_value_policy::move);
138
+
139
+ m.def(
140
+ "move_tensor_copy",
141
+ []() -> Eigen::Tensor<double, 3, Options> { return get_tensor<Options>(); },
142
+ py::return_value_policy::move);
143
+
144
+ m.def(
145
+ "move_const_tensor",
146
+ []() -> const Eigen::Tensor<double, 3, Options> & { return get_const_tensor<Options>(); },
147
+ py::return_value_policy::move);
148
+
149
+ m.def(
150
+ "take_fixed_tensor",
151
+
152
+ []() {
153
+ Eigen::aligned_allocator<
154
+ Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>>
155
+ allocator;
156
+ return new (allocator.allocate(1))
157
+ Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>(
158
+ get_fixed_tensor<Options>());
159
+ },
160
+ py::return_value_policy::take_ownership);
161
+
162
+ m.def(
163
+ "take_tensor",
164
+ []() { return new Eigen::Tensor<double, 3, Options>(get_tensor<Options>()); },
165
+ py::return_value_policy::take_ownership);
166
+
167
+ m.def(
168
+ "take_const_tensor",
169
+ []() -> const Eigen::Tensor<double, 3, Options> * {
170
+ return new Eigen::Tensor<double, 3, Options>(get_tensor<Options>());
171
+ },
172
+ py::return_value_policy::take_ownership);
173
+
174
+ m.def(
175
+ "take_view_tensor",
176
+ []() -> const Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> * {
177
+ return new Eigen::TensorMap<Eigen::Tensor<double, 3, Options>>(get_tensor<Options>());
178
+ },
179
+ py::return_value_policy::take_ownership);
180
+
181
+ m.def(
182
+ "reference_tensor",
183
+ []() { return &get_tensor<Options>(); },
184
+ py::return_value_policy::reference);
185
+
186
+ m.def(
187
+ "reference_tensor_v2",
188
+ []() -> Eigen::Tensor<double, 3, Options> & { return get_tensor<Options>(); },
189
+ py::return_value_policy::reference);
190
+
191
+ m.def(
192
+ "reference_tensor_internal",
193
+ []() { return &get_tensor<Options>(); },
194
+ py::return_value_policy::reference_internal);
195
+
196
+ m.def(
197
+ "reference_fixed_tensor",
198
+ []() { return &get_tensor<Options>(); },
199
+ py::return_value_policy::reference);
200
+
201
+ m.def(
202
+ "reference_const_tensor",
203
+ []() { return &get_const_tensor<Options>(); },
204
+ py::return_value_policy::reference);
205
+
206
+ m.def(
207
+ "reference_const_tensor_v2",
208
+ []() -> const Eigen::Tensor<double, 3, Options> & { return get_const_tensor<Options>(); },
209
+ py::return_value_policy::reference);
210
+
211
+ m.def(
212
+ "reference_view_of_tensor",
213
+ []() -> Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> {
214
+ return get_tensor_map<Options>();
215
+ },
216
+ py::return_value_policy::reference);
217
+
218
+ m.def(
219
+ "reference_view_of_tensor_v2",
220
+ // NOLINTNEXTLINE(readability-const-return-type)
221
+ []() -> const Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> {
222
+ return get_tensor_map<Options>(); // NOLINT(readability-const-return-type)
223
+ }, // NOLINT(readability-const-return-type)
224
+ py::return_value_policy::reference);
225
+
226
+ m.def(
227
+ "reference_view_of_tensor_v3",
228
+ []() -> Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> * {
229
+ return &get_tensor_map<Options>();
230
+ },
231
+ py::return_value_policy::reference);
232
+
233
+ m.def(
234
+ "reference_view_of_tensor_v4",
235
+ []() -> const Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> * {
236
+ return &get_tensor_map<Options>();
237
+ },
238
+ py::return_value_policy::reference);
239
+
240
+ m.def(
241
+ "reference_view_of_tensor_v5",
242
+ []() -> Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> & {
243
+ return get_tensor_map<Options>();
244
+ },
245
+ py::return_value_policy::reference);
246
+
247
+ m.def(
248
+ "reference_view_of_tensor_v6",
249
+ []() -> const Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> & {
250
+ return get_tensor_map<Options>();
251
+ },
252
+ py::return_value_policy::reference);
253
+
254
+ m.def(
255
+ "reference_view_of_fixed_tensor",
256
+ []() {
257
+ return Eigen::TensorMap<
258
+ Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options>>(
259
+ get_fixed_tensor<Options>());
260
+ },
261
+ py::return_value_policy::reference);
262
+
263
+ m.def("round_trip_tensor",
264
+ [](const Eigen::Tensor<double, 3, Options> &tensor) { return tensor; });
265
+
266
+ m.def(
267
+ "round_trip_tensor_noconvert",
268
+ [](const Eigen::Tensor<double, 3, Options> &tensor) { return tensor; },
269
+ py::arg("tensor").noconvert());
270
+
271
+ m.def("round_trip_tensor2",
272
+ [](const Eigen::Tensor<int32_t, 3, Options> &tensor) { return tensor; });
273
+
274
+ m.def("round_trip_fixed_tensor",
275
+ [](const Eigen::TensorFixedSize<double, Eigen::Sizes<3, 5, 2>, Options> &tensor) {
276
+ return tensor;
277
+ });
278
+
279
+ m.def(
280
+ "round_trip_view_tensor",
281
+ [](Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> view) { return view; },
282
+ py::return_value_policy::reference);
283
+
284
+ m.def(
285
+ "round_trip_view_tensor_ref",
286
+ [](Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> &view) { return view; },
287
+ py::return_value_policy::reference);
288
+
289
+ m.def(
290
+ "round_trip_view_tensor_ptr",
291
+ [](Eigen::TensorMap<Eigen::Tensor<double, 3, Options>> *view) { return view; },
292
+ py::return_value_policy::reference);
293
+
294
+ m.def(
295
+ "round_trip_aligned_view_tensor",
296
+ [](Eigen::TensorMap<Eigen::Tensor<double, 3, Options>, Eigen::Aligned> view) {
297
+ return view;
298
+ },
299
+ py::return_value_policy::reference);
300
+
301
+ m.def(
302
+ "round_trip_const_view_tensor",
303
+ [](Eigen::TensorMap<const Eigen::Tensor<double, 3, Options>> view) {
304
+ return Eigen::Tensor<double, 3, Options>(view);
305
+ },
306
+ py::return_value_policy::move);
307
+
308
+ m.def(
309
+ "round_trip_rank_0",
310
+ [](const Eigen::Tensor<double, 0, Options> &tensor) { return tensor; },
311
+ py::return_value_policy::move);
312
+
313
+ m.def(
314
+ "round_trip_rank_0_noconvert",
315
+ [](const Eigen::Tensor<double, 0, Options> &tensor) { return tensor; },
316
+ py::arg("tensor").noconvert(),
317
+ py::return_value_policy::move);
318
+
319
+ m.def(
320
+ "round_trip_rank_0_view",
321
+ [](Eigen::TensorMap<Eigen::Tensor<double, 0, Options>> &tensor) { return tensor; },
322
+ py::return_value_policy::reference);
323
+ }
324
+
325
+ void test_module(py::module_ &m) {
326
+ auto f_style = m.def_submodule("f_style");
327
+ auto c_style = m.def_submodule("c_style");
328
+
329
+ init_tensor_module<Eigen::ColMajor>(f_style);
330
+ init_tensor_module<Eigen::RowMajor>(c_style);
331
+ }
332
+
333
+ PYBIND11_NAMESPACE_END(eigen_tensor_test)
third_party/CityFlow/extern/pybind11/tests/test_eigen_tensor.py CHANGED
@@ -1,288 +1,288 @@
1
- import sys
2
-
3
- import pytest
4
-
5
- np = pytest.importorskip("numpy")
6
- eigen_tensor = pytest.importorskip("pybind11_tests.eigen_tensor")
7
- submodules = [eigen_tensor.c_style, eigen_tensor.f_style]
8
- try:
9
- import eigen_tensor_avoid_stl_array as avoid
10
-
11
- submodules += [avoid.c_style, avoid.f_style]
12
- except ImportError as e:
13
- # Ensure config, build, toolchain, etc. issues are not masked here:
14
- msg = (
15
- "import eigen_tensor_avoid_stl_array FAILED, while "
16
- "import pybind11_tests.eigen_tensor succeeded. "
17
- "Please ensure that "
18
- "test_eigen_tensor.cpp & "
19
- "eigen_tensor_avoid_stl_array.cpp "
20
- "are built together (or both are not built if Eigen is not available)."
21
- )
22
- raise RuntimeError(msg) from e
23
-
24
- tensor_ref = np.empty((3, 5, 2), dtype=np.int64)
25
-
26
- for i in range(tensor_ref.shape[0]):
27
- for j in range(tensor_ref.shape[1]):
28
- for k in range(tensor_ref.shape[2]):
29
- tensor_ref[i, j, k] = i * (5 * 2) + j * 2 + k
30
-
31
- indices = (2, 3, 1)
32
-
33
-
34
- @pytest.fixture(autouse=True)
35
- def cleanup():
36
- for module in submodules:
37
- module.setup()
38
-
39
- yield
40
-
41
- for module in submodules:
42
- assert module.is_ok()
43
-
44
-
45
- def test_import_avoid_stl_array():
46
- pytest.importorskip("eigen_tensor_avoid_stl_array")
47
- assert len(submodules) == 4
48
-
49
-
50
- def assert_equal_tensor_ref(mat, writeable=True, modified=None):
51
- assert mat.flags.writeable == writeable
52
-
53
- copy = np.array(tensor_ref)
54
- if modified is not None:
55
- copy[indices] = modified
56
-
57
- np.testing.assert_array_equal(mat, copy)
58
-
59
-
60
- @pytest.mark.parametrize("m", submodules)
61
- @pytest.mark.parametrize("member_name", ["member", "member_view"])
62
- def test_reference_internal(m, member_name):
63
- if not hasattr(sys, "getrefcount"):
64
- pytest.skip("No reference counting")
65
- foo = m.CustomExample()
66
- counts = sys.getrefcount(foo)
67
- mem = getattr(foo, member_name)
68
- assert_equal_tensor_ref(mem, writeable=False)
69
- new_counts = sys.getrefcount(foo)
70
- assert new_counts == counts + 1
71
- assert_equal_tensor_ref(mem, writeable=False)
72
- del mem
73
- assert sys.getrefcount(foo) == counts
74
-
75
-
76
- assert_equal_funcs = [
77
- "copy_tensor",
78
- "copy_fixed_tensor",
79
- "copy_const_tensor",
80
- "move_tensor_copy",
81
- "move_fixed_tensor_copy",
82
- "take_tensor",
83
- "take_fixed_tensor",
84
- "reference_tensor",
85
- "reference_tensor_v2",
86
- "reference_fixed_tensor",
87
- "reference_view_of_tensor",
88
- "reference_view_of_tensor_v3",
89
- "reference_view_of_tensor_v5",
90
- "reference_view_of_fixed_tensor",
91
- ]
92
-
93
- assert_equal_const_funcs = [
94
- "reference_view_of_tensor_v2",
95
- "reference_view_of_tensor_v4",
96
- "reference_view_of_tensor_v6",
97
- "reference_const_tensor",
98
- "reference_const_tensor_v2",
99
- ]
100
-
101
-
102
- @pytest.mark.parametrize("m", submodules)
103
- @pytest.mark.parametrize("func_name", assert_equal_funcs + assert_equal_const_funcs)
104
- def test_convert_tensor_to_py(m, func_name):
105
- writeable = func_name in assert_equal_funcs
106
- assert_equal_tensor_ref(getattr(m, func_name)(), writeable=writeable)
107
-
108
-
109
- @pytest.mark.parametrize("m", submodules)
110
- def test_bad_cpp_to_python_casts(m):
111
- with pytest.raises(
112
- RuntimeError, match="Cannot use reference internal when there is no parent"
113
- ):
114
- m.reference_tensor_internal()
115
-
116
- with pytest.raises(RuntimeError, match="Cannot move from a constant reference"):
117
- m.move_const_tensor()
118
-
119
- with pytest.raises(
120
- RuntimeError, match="Cannot take ownership of a const reference"
121
- ):
122
- m.take_const_tensor()
123
-
124
- with pytest.raises(
125
- RuntimeError,
126
- match="Invalid return_value_policy for Eigen Map type, must be either reference or reference_internal",
127
- ):
128
- m.take_view_tensor()
129
-
130
-
131
- @pytest.mark.parametrize("m", submodules)
132
- def test_bad_python_to_cpp_casts(m):
133
- with pytest.raises(
134
- TypeError, match=r"^round_trip_tensor\(\): incompatible function arguments"
135
- ):
136
- m.round_trip_tensor(np.zeros((2, 3)))
137
-
138
- with pytest.raises(TypeError, match=r"^Cannot cast array data from dtype"):
139
- m.round_trip_tensor(np.zeros(dtype=np.str_, shape=(2, 3, 1)))
140
-
141
- with pytest.raises(
142
- TypeError,
143
- match=r"^round_trip_tensor_noconvert\(\): incompatible function arguments",
144
- ):
145
- m.round_trip_tensor_noconvert(tensor_ref)
146
-
147
- assert_equal_tensor_ref(
148
- m.round_trip_tensor_noconvert(tensor_ref.astype(np.float64))
149
- )
150
-
151
- bad_options = "C" if m.needed_options == "F" else "F"
152
- # Shape, dtype and the order need to be correct for a TensorMap cast
153
- with pytest.raises(
154
- TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
155
- ):
156
- m.round_trip_view_tensor(
157
- np.zeros((3, 5, 2), dtype=np.float64, order=bad_options)
158
- )
159
-
160
- with pytest.raises(
161
- TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
162
- ):
163
- m.round_trip_view_tensor(
164
- np.zeros((3, 5, 2), dtype=np.float32, order=m.needed_options)
165
- )
166
-
167
- with pytest.raises(
168
- TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
169
- ):
170
- m.round_trip_view_tensor(
171
- np.zeros((3, 5), dtype=np.float64, order=m.needed_options)
172
- )
173
-
174
- temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
175
- with pytest.raises(
176
- TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
177
- ):
178
- m.round_trip_view_tensor(
179
- temp[:, ::-1, :],
180
- )
181
-
182
- temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
183
- temp.setflags(write=False)
184
- with pytest.raises(
185
- TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
186
- ):
187
- m.round_trip_view_tensor(temp)
188
-
189
-
190
- @pytest.mark.parametrize("m", submodules)
191
- def test_references_actually_refer(m):
192
- a = m.reference_tensor()
193
- temp = a[indices]
194
- a[indices] = 100
195
- assert_equal_tensor_ref(m.copy_const_tensor(), modified=100)
196
- a[indices] = temp
197
- assert_equal_tensor_ref(m.copy_const_tensor())
198
-
199
- a = m.reference_view_of_tensor()
200
- a[indices] = 100
201
- assert_equal_tensor_ref(m.copy_const_tensor(), modified=100)
202
- a[indices] = temp
203
- assert_equal_tensor_ref(m.copy_const_tensor())
204
-
205
-
206
- @pytest.mark.parametrize("m", submodules)
207
- def test_round_trip(m):
208
- assert_equal_tensor_ref(m.round_trip_tensor(tensor_ref))
209
-
210
- with pytest.raises(TypeError, match="^Cannot cast array data from"):
211
- assert_equal_tensor_ref(m.round_trip_tensor2(tensor_ref))
212
-
213
- assert_equal_tensor_ref(m.round_trip_tensor2(np.array(tensor_ref, dtype=np.int32)))
214
- assert_equal_tensor_ref(m.round_trip_fixed_tensor(tensor_ref))
215
- assert_equal_tensor_ref(m.round_trip_aligned_view_tensor(m.reference_tensor()))
216
-
217
- copy = np.array(tensor_ref, dtype=np.float64, order=m.needed_options)
218
- assert_equal_tensor_ref(m.round_trip_view_tensor(copy))
219
- assert_equal_tensor_ref(m.round_trip_view_tensor_ref(copy))
220
- assert_equal_tensor_ref(m.round_trip_view_tensor_ptr(copy))
221
- copy.setflags(write=False)
222
- assert_equal_tensor_ref(m.round_trip_const_view_tensor(copy))
223
-
224
- np.testing.assert_array_equal(
225
- tensor_ref[:, ::-1, :], m.round_trip_tensor(tensor_ref[:, ::-1, :])
226
- )
227
-
228
- assert m.round_trip_rank_0(np.float64(3.5)) == 3.5
229
- assert m.round_trip_rank_0(3.5) == 3.5
230
-
231
- with pytest.raises(
232
- TypeError,
233
- match=r"^round_trip_rank_0_noconvert\(\): incompatible function arguments",
234
- ):
235
- m.round_trip_rank_0_noconvert(np.float64(3.5))
236
-
237
- with pytest.raises(
238
- TypeError,
239
- match=r"^round_trip_rank_0_noconvert\(\): incompatible function arguments",
240
- ):
241
- m.round_trip_rank_0_noconvert(3.5)
242
-
243
- with pytest.raises(
244
- TypeError, match=r"^round_trip_rank_0_view\(\): incompatible function arguments"
245
- ):
246
- m.round_trip_rank_0_view(np.float64(3.5))
247
-
248
- with pytest.raises(
249
- TypeError, match=r"^round_trip_rank_0_view\(\): incompatible function arguments"
250
- ):
251
- m.round_trip_rank_0_view(3.5)
252
-
253
-
254
- @pytest.mark.parametrize("m", submodules)
255
- def test_round_trip_references_actually_refer(m):
256
- # Need to create a copy that matches the type on the C side
257
- copy = np.array(tensor_ref, dtype=np.float64, order=m.needed_options)
258
- a = m.round_trip_view_tensor(copy)
259
- temp = a[indices]
260
- a[indices] = 100
261
- assert_equal_tensor_ref(copy, modified=100)
262
- a[indices] = temp
263
- assert_equal_tensor_ref(copy)
264
-
265
-
266
- @pytest.mark.parametrize("m", submodules)
267
- def test_doc_string(m, doc):
268
- assert (
269
- doc(m.copy_tensor) == "copy_tensor() -> numpy.ndarray[numpy.float64[?, ?, ?]]"
270
- )
271
- assert (
272
- doc(m.copy_fixed_tensor)
273
- == "copy_fixed_tensor() -> numpy.ndarray[numpy.float64[3, 5, 2]]"
274
- )
275
- assert (
276
- doc(m.reference_const_tensor)
277
- == "reference_const_tensor() -> numpy.ndarray[numpy.float64[?, ?, ?]]"
278
- )
279
-
280
- order_flag = f"flags.{m.needed_options.lower()}_contiguous"
281
- assert doc(m.round_trip_view_tensor) == (
282
- f"round_trip_view_tensor(arg0: numpy.ndarray[numpy.float64[?, ?, ?], flags.writeable, {order_flag}])"
283
- f" -> numpy.ndarray[numpy.float64[?, ?, ?], flags.writeable, {order_flag}]"
284
- )
285
- assert doc(m.round_trip_const_view_tensor) == (
286
- f"round_trip_const_view_tensor(arg0: numpy.ndarray[numpy.float64[?, ?, ?], {order_flag}])"
287
- " -> numpy.ndarray[numpy.float64[?, ?, ?]]"
288
- )
 
1
+ import sys
2
+
3
+ import pytest
4
+
5
+ np = pytest.importorskip("numpy")
6
+ eigen_tensor = pytest.importorskip("pybind11_tests.eigen_tensor")
7
+ submodules = [eigen_tensor.c_style, eigen_tensor.f_style]
8
+ try:
9
+ import eigen_tensor_avoid_stl_array as avoid
10
+
11
+ submodules += [avoid.c_style, avoid.f_style]
12
+ except ImportError as e:
13
+ # Ensure config, build, toolchain, etc. issues are not masked here:
14
+ msg = (
15
+ "import eigen_tensor_avoid_stl_array FAILED, while "
16
+ "import pybind11_tests.eigen_tensor succeeded. "
17
+ "Please ensure that "
18
+ "test_eigen_tensor.cpp & "
19
+ "eigen_tensor_avoid_stl_array.cpp "
20
+ "are built together (or both are not built if Eigen is not available)."
21
+ )
22
+ raise RuntimeError(msg) from e
23
+
24
+ tensor_ref = np.empty((3, 5, 2), dtype=np.int64)
25
+
26
+ for i in range(tensor_ref.shape[0]):
27
+ for j in range(tensor_ref.shape[1]):
28
+ for k in range(tensor_ref.shape[2]):
29
+ tensor_ref[i, j, k] = i * (5 * 2) + j * 2 + k
30
+
31
+ indices = (2, 3, 1)
32
+
33
+
34
+ @pytest.fixture(autouse=True)
35
+ def cleanup():
36
+ for module in submodules:
37
+ module.setup()
38
+
39
+ yield
40
+
41
+ for module in submodules:
42
+ assert module.is_ok()
43
+
44
+
45
+ def test_import_avoid_stl_array():
46
+ pytest.importorskip("eigen_tensor_avoid_stl_array")
47
+ assert len(submodules) == 4
48
+
49
+
50
+ def assert_equal_tensor_ref(mat, writeable=True, modified=None):
51
+ assert mat.flags.writeable == writeable
52
+
53
+ copy = np.array(tensor_ref)
54
+ if modified is not None:
55
+ copy[indices] = modified
56
+
57
+ np.testing.assert_array_equal(mat, copy)
58
+
59
+
60
+ @pytest.mark.parametrize("m", submodules)
61
+ @pytest.mark.parametrize("member_name", ["member", "member_view"])
62
+ def test_reference_internal(m, member_name):
63
+ if not hasattr(sys, "getrefcount"):
64
+ pytest.skip("No reference counting")
65
+ foo = m.CustomExample()
66
+ counts = sys.getrefcount(foo)
67
+ mem = getattr(foo, member_name)
68
+ assert_equal_tensor_ref(mem, writeable=False)
69
+ new_counts = sys.getrefcount(foo)
70
+ assert new_counts == counts + 1
71
+ assert_equal_tensor_ref(mem, writeable=False)
72
+ del mem
73
+ assert sys.getrefcount(foo) == counts
74
+
75
+
76
+ assert_equal_funcs = [
77
+ "copy_tensor",
78
+ "copy_fixed_tensor",
79
+ "copy_const_tensor",
80
+ "move_tensor_copy",
81
+ "move_fixed_tensor_copy",
82
+ "take_tensor",
83
+ "take_fixed_tensor",
84
+ "reference_tensor",
85
+ "reference_tensor_v2",
86
+ "reference_fixed_tensor",
87
+ "reference_view_of_tensor",
88
+ "reference_view_of_tensor_v3",
89
+ "reference_view_of_tensor_v5",
90
+ "reference_view_of_fixed_tensor",
91
+ ]
92
+
93
+ assert_equal_const_funcs = [
94
+ "reference_view_of_tensor_v2",
95
+ "reference_view_of_tensor_v4",
96
+ "reference_view_of_tensor_v6",
97
+ "reference_const_tensor",
98
+ "reference_const_tensor_v2",
99
+ ]
100
+
101
+
102
+ @pytest.mark.parametrize("m", submodules)
103
+ @pytest.mark.parametrize("func_name", assert_equal_funcs + assert_equal_const_funcs)
104
+ def test_convert_tensor_to_py(m, func_name):
105
+ writeable = func_name in assert_equal_funcs
106
+ assert_equal_tensor_ref(getattr(m, func_name)(), writeable=writeable)
107
+
108
+
109
+ @pytest.mark.parametrize("m", submodules)
110
+ def test_bad_cpp_to_python_casts(m):
111
+ with pytest.raises(
112
+ RuntimeError, match="Cannot use reference internal when there is no parent"
113
+ ):
114
+ m.reference_tensor_internal()
115
+
116
+ with pytest.raises(RuntimeError, match="Cannot move from a constant reference"):
117
+ m.move_const_tensor()
118
+
119
+ with pytest.raises(
120
+ RuntimeError, match="Cannot take ownership of a const reference"
121
+ ):
122
+ m.take_const_tensor()
123
+
124
+ with pytest.raises(
125
+ RuntimeError,
126
+ match="Invalid return_value_policy for Eigen Map type, must be either reference or reference_internal",
127
+ ):
128
+ m.take_view_tensor()
129
+
130
+
131
+ @pytest.mark.parametrize("m", submodules)
132
+ def test_bad_python_to_cpp_casts(m):
133
+ with pytest.raises(
134
+ TypeError, match=r"^round_trip_tensor\(\): incompatible function arguments"
135
+ ):
136
+ m.round_trip_tensor(np.zeros((2, 3)))
137
+
138
+ with pytest.raises(TypeError, match=r"^Cannot cast array data from dtype"):
139
+ m.round_trip_tensor(np.zeros(dtype=np.str_, shape=(2, 3, 1)))
140
+
141
+ with pytest.raises(
142
+ TypeError,
143
+ match=r"^round_trip_tensor_noconvert\(\): incompatible function arguments",
144
+ ):
145
+ m.round_trip_tensor_noconvert(tensor_ref)
146
+
147
+ assert_equal_tensor_ref(
148
+ m.round_trip_tensor_noconvert(tensor_ref.astype(np.float64))
149
+ )
150
+
151
+ bad_options = "C" if m.needed_options == "F" else "F"
152
+ # Shape, dtype and the order need to be correct for a TensorMap cast
153
+ with pytest.raises(
154
+ TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
155
+ ):
156
+ m.round_trip_view_tensor(
157
+ np.zeros((3, 5, 2), dtype=np.float64, order=bad_options)
158
+ )
159
+
160
+ with pytest.raises(
161
+ TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
162
+ ):
163
+ m.round_trip_view_tensor(
164
+ np.zeros((3, 5, 2), dtype=np.float32, order=m.needed_options)
165
+ )
166
+
167
+ with pytest.raises(
168
+ TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
169
+ ):
170
+ m.round_trip_view_tensor(
171
+ np.zeros((3, 5), dtype=np.float64, order=m.needed_options)
172
+ )
173
+
174
+ temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
175
+ with pytest.raises(
176
+ TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
177
+ ):
178
+ m.round_trip_view_tensor(
179
+ temp[:, ::-1, :],
180
+ )
181
+
182
+ temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
183
+ temp.setflags(write=False)
184
+ with pytest.raises(
185
+ TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
186
+ ):
187
+ m.round_trip_view_tensor(temp)
188
+
189
+
190
+ @pytest.mark.parametrize("m", submodules)
191
+ def test_references_actually_refer(m):
192
+ a = m.reference_tensor()
193
+ temp = a[indices]
194
+ a[indices] = 100
195
+ assert_equal_tensor_ref(m.copy_const_tensor(), modified=100)
196
+ a[indices] = temp
197
+ assert_equal_tensor_ref(m.copy_const_tensor())
198
+
199
+ a = m.reference_view_of_tensor()
200
+ a[indices] = 100
201
+ assert_equal_tensor_ref(m.copy_const_tensor(), modified=100)
202
+ a[indices] = temp
203
+ assert_equal_tensor_ref(m.copy_const_tensor())
204
+
205
+
206
+ @pytest.mark.parametrize("m", submodules)
207
+ def test_round_trip(m):
208
+ assert_equal_tensor_ref(m.round_trip_tensor(tensor_ref))
209
+
210
+ with pytest.raises(TypeError, match="^Cannot cast array data from"):
211
+ assert_equal_tensor_ref(m.round_trip_tensor2(tensor_ref))
212
+
213
+ assert_equal_tensor_ref(m.round_trip_tensor2(np.array(tensor_ref, dtype=np.int32)))
214
+ assert_equal_tensor_ref(m.round_trip_fixed_tensor(tensor_ref))
215
+ assert_equal_tensor_ref(m.round_trip_aligned_view_tensor(m.reference_tensor()))
216
+
217
+ copy = np.array(tensor_ref, dtype=np.float64, order=m.needed_options)
218
+ assert_equal_tensor_ref(m.round_trip_view_tensor(copy))
219
+ assert_equal_tensor_ref(m.round_trip_view_tensor_ref(copy))
220
+ assert_equal_tensor_ref(m.round_trip_view_tensor_ptr(copy))
221
+ copy.setflags(write=False)
222
+ assert_equal_tensor_ref(m.round_trip_const_view_tensor(copy))
223
+
224
+ np.testing.assert_array_equal(
225
+ tensor_ref[:, ::-1, :], m.round_trip_tensor(tensor_ref[:, ::-1, :])
226
+ )
227
+
228
+ assert m.round_trip_rank_0(np.float64(3.5)) == 3.5
229
+ assert m.round_trip_rank_0(3.5) == 3.5
230
+
231
+ with pytest.raises(
232
+ TypeError,
233
+ match=r"^round_trip_rank_0_noconvert\(\): incompatible function arguments",
234
+ ):
235
+ m.round_trip_rank_0_noconvert(np.float64(3.5))
236
+
237
+ with pytest.raises(
238
+ TypeError,
239
+ match=r"^round_trip_rank_0_noconvert\(\): incompatible function arguments",
240
+ ):
241
+ m.round_trip_rank_0_noconvert(3.5)
242
+
243
+ with pytest.raises(
244
+ TypeError, match=r"^round_trip_rank_0_view\(\): incompatible function arguments"
245
+ ):
246
+ m.round_trip_rank_0_view(np.float64(3.5))
247
+
248
+ with pytest.raises(
249
+ TypeError, match=r"^round_trip_rank_0_view\(\): incompatible function arguments"
250
+ ):
251
+ m.round_trip_rank_0_view(3.5)
252
+
253
+
254
+ @pytest.mark.parametrize("m", submodules)
255
+ def test_round_trip_references_actually_refer(m):
256
+ # Need to create a copy that matches the type on the C side
257
+ copy = np.array(tensor_ref, dtype=np.float64, order=m.needed_options)
258
+ a = m.round_trip_view_tensor(copy)
259
+ temp = a[indices]
260
+ a[indices] = 100
261
+ assert_equal_tensor_ref(copy, modified=100)
262
+ a[indices] = temp
263
+ assert_equal_tensor_ref(copy)
264
+
265
+
266
+ @pytest.mark.parametrize("m", submodules)
267
+ def test_doc_string(m, doc):
268
+ assert (
269
+ doc(m.copy_tensor) == "copy_tensor() -> numpy.ndarray[numpy.float64[?, ?, ?]]"
270
+ )
271
+ assert (
272
+ doc(m.copy_fixed_tensor)
273
+ == "copy_fixed_tensor() -> numpy.ndarray[numpy.float64[3, 5, 2]]"
274
+ )
275
+ assert (
276
+ doc(m.reference_const_tensor)
277
+ == "reference_const_tensor() -> numpy.ndarray[numpy.float64[?, ?, ?]]"
278
+ )
279
+
280
+ order_flag = f"flags.{m.needed_options.lower()}_contiguous"
281
+ assert doc(m.round_trip_view_tensor) == (
282
+ f"round_trip_view_tensor(arg0: numpy.ndarray[numpy.float64[?, ?, ?], flags.writeable, {order_flag}])"
283
+ f" -> numpy.ndarray[numpy.float64[?, ?, ?], flags.writeable, {order_flag}]"
284
+ )
285
+ assert doc(m.round_trip_const_view_tensor) == (
286
+ f"round_trip_const_view_tensor(arg0: numpy.ndarray[numpy.float64[?, ?, ?], {order_flag}])"
287
+ " -> numpy.ndarray[numpy.float64[?, ?, ?]]"
288
+ )
third_party/CityFlow/extern/pybind11/tests/test_enum.cpp CHANGED
@@ -1,133 +1,133 @@
1
- /*
2
- tests/test_enums.cpp -- enumerations
3
-
4
- Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include "pybind11_tests.h"
11
-
12
- TEST_SUBMODULE(enums, m) {
13
- // test_unscoped_enum
14
- enum UnscopedEnum { EOne = 1, ETwo, EThree };
15
- py::enum_<UnscopedEnum>(m, "UnscopedEnum", py::arithmetic(), "An unscoped enumeration")
16
- .value("EOne", EOne, "Docstring for EOne")
17
- .value("ETwo", ETwo, "Docstring for ETwo")
18
- .value("EThree", EThree, "Docstring for EThree")
19
- .export_values();
20
-
21
- // test_scoped_enum
22
- enum class ScopedEnum { Two = 2, Three };
23
- py::enum_<ScopedEnum>(m, "ScopedEnum", py::arithmetic())
24
- .value("Two", ScopedEnum::Two)
25
- .value("Three", ScopedEnum::Three);
26
-
27
- m.def("test_scoped_enum", [](ScopedEnum z) {
28
- return "ScopedEnum::" + std::string(z == ScopedEnum::Two ? "Two" : "Three");
29
- });
30
-
31
- // test_binary_operators
32
- enum Flags { Read = 4, Write = 2, Execute = 1 };
33
- py::enum_<Flags>(m, "Flags", py::arithmetic())
34
- .value("Read", Flags::Read)
35
- .value("Write", Flags::Write)
36
- .value("Execute", Flags::Execute)
37
- .export_values();
38
-
39
- // test_implicit_conversion
40
- class ClassWithUnscopedEnum {
41
- public:
42
- enum EMode { EFirstMode = 1, ESecondMode };
43
-
44
- static EMode test_function(EMode mode) { return mode; }
45
- };
46
- py::class_<ClassWithUnscopedEnum> exenum_class(m, "ClassWithUnscopedEnum");
47
- exenum_class.def_static("test_function", &ClassWithUnscopedEnum::test_function);
48
- py::enum_<ClassWithUnscopedEnum::EMode>(exenum_class, "EMode")
49
- .value("EFirstMode", ClassWithUnscopedEnum::EFirstMode)
50
- .value("ESecondMode", ClassWithUnscopedEnum::ESecondMode)
51
- .export_values();
52
-
53
- // test_enum_to_int
54
- m.def("test_enum_to_int", [](int) {});
55
- m.def("test_enum_to_uint", [](uint32_t) {});
56
- m.def("test_enum_to_long_long", [](long long) {});
57
-
58
- // test_duplicate_enum_name
59
- enum SimpleEnum { ONE, TWO, THREE };
60
-
61
- m.def("register_bad_enum", [m]() {
62
- py::enum_<SimpleEnum>(m, "SimpleEnum")
63
- .value("ONE", SimpleEnum::ONE) // NOTE: all value function calls are called with the
64
- // same first parameter value
65
- .value("ONE", SimpleEnum::TWO)
66
- .value("ONE", SimpleEnum::THREE)
67
- .export_values();
68
- });
69
-
70
- // test_enum_scalar
71
- enum UnscopedUCharEnum : unsigned char {};
72
- enum class ScopedShortEnum : short {};
73
- enum class ScopedLongEnum : long {};
74
- enum UnscopedUInt64Enum : std::uint64_t {};
75
- static_assert(
76
- py::detail::all_of<
77
- std::is_same<py::enum_<UnscopedUCharEnum>::Scalar, unsigned char>,
78
- std::is_same<py::enum_<ScopedShortEnum>::Scalar, short>,
79
- std::is_same<py::enum_<ScopedLongEnum>::Scalar, long>,
80
- std::is_same<py::enum_<UnscopedUInt64Enum>::Scalar, std::uint64_t>>::value,
81
- "Error during the deduction of enum's scalar type with normal integer underlying");
82
-
83
- // test_enum_scalar_with_char_underlying
84
- enum class ScopedCharEnum : char { Zero, Positive };
85
- enum class ScopedWCharEnum : wchar_t { Zero, Positive };
86
- enum class ScopedChar32Enum : char32_t { Zero, Positive };
87
- enum class ScopedChar16Enum : char16_t { Zero, Positive };
88
-
89
- // test the scalar of char type enums according to chapter 'Character types'
90
- // from https://en.cppreference.com/w/cpp/language/types
91
- static_assert(
92
- py::detail::any_of<
93
- std::is_same<py::enum_<ScopedCharEnum>::Scalar, signed char>, // e.g. gcc on x86
94
- std::is_same<py::enum_<ScopedCharEnum>::Scalar, unsigned char> // e.g. arm linux
95
- >::value,
96
- "char should be cast to either signed char or unsigned char");
97
- static_assert(sizeof(py::enum_<ScopedWCharEnum>::Scalar) == 2
98
- || sizeof(py::enum_<ScopedWCharEnum>::Scalar) == 4,
99
- "wchar_t should be either 16 bits (Windows) or 32 (everywhere else)");
100
- static_assert(
101
- py::detail::all_of<
102
- std::is_same<py::enum_<ScopedChar32Enum>::Scalar, std::uint_least32_t>,
103
- std::is_same<py::enum_<ScopedChar16Enum>::Scalar, std::uint_least16_t>>::value,
104
- "char32_t, char16_t (and char8_t)'s size, signedness, and alignment is determined");
105
- #if defined(PYBIND11_HAS_U8STRING)
106
- enum class ScopedChar8Enum : char8_t { Zero, Positive };
107
- static_assert(std::is_same<py::enum_<ScopedChar8Enum>::Scalar, unsigned char>::value);
108
- #endif
109
-
110
- // test_char_underlying_enum
111
- py::enum_<ScopedCharEnum>(m, "ScopedCharEnum")
112
- .value("Zero", ScopedCharEnum::Zero)
113
- .value("Positive", ScopedCharEnum::Positive);
114
- py::enum_<ScopedWCharEnum>(m, "ScopedWCharEnum")
115
- .value("Zero", ScopedWCharEnum::Zero)
116
- .value("Positive", ScopedWCharEnum::Positive);
117
- py::enum_<ScopedChar32Enum>(m, "ScopedChar32Enum")
118
- .value("Zero", ScopedChar32Enum::Zero)
119
- .value("Positive", ScopedChar32Enum::Positive);
120
- py::enum_<ScopedChar16Enum>(m, "ScopedChar16Enum")
121
- .value("Zero", ScopedChar16Enum::Zero)
122
- .value("Positive", ScopedChar16Enum::Positive);
123
-
124
- // test_bool_underlying_enum
125
- enum class ScopedBoolEnum : bool { FALSE, TRUE };
126
-
127
- // bool is unsigned (std::is_signed returns false) and 1-byte long, so represented with u8
128
- static_assert(std::is_same<py::enum_<ScopedBoolEnum>::Scalar, std::uint8_t>::value, "");
129
-
130
- py::enum_<ScopedBoolEnum>(m, "ScopedBoolEnum")
131
- .value("FALSE", ScopedBoolEnum::FALSE)
132
- .value("TRUE", ScopedBoolEnum::TRUE);
133
- }
 
1
+ /*
2
+ tests/test_enums.cpp -- enumerations
3
+
4
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include "pybind11_tests.h"
11
+
12
+ TEST_SUBMODULE(enums, m) {
13
+ // test_unscoped_enum
14
+ enum UnscopedEnum { EOne = 1, ETwo, EThree };
15
+ py::enum_<UnscopedEnum>(m, "UnscopedEnum", py::arithmetic(), "An unscoped enumeration")
16
+ .value("EOne", EOne, "Docstring for EOne")
17
+ .value("ETwo", ETwo, "Docstring for ETwo")
18
+ .value("EThree", EThree, "Docstring for EThree")
19
+ .export_values();
20
+
21
+ // test_scoped_enum
22
+ enum class ScopedEnum { Two = 2, Three };
23
+ py::enum_<ScopedEnum>(m, "ScopedEnum", py::arithmetic())
24
+ .value("Two", ScopedEnum::Two)
25
+ .value("Three", ScopedEnum::Three);
26
+
27
+ m.def("test_scoped_enum", [](ScopedEnum z) {
28
+ return "ScopedEnum::" + std::string(z == ScopedEnum::Two ? "Two" : "Three");
29
+ });
30
+
31
+ // test_binary_operators
32
+ enum Flags { Read = 4, Write = 2, Execute = 1 };
33
+ py::enum_<Flags>(m, "Flags", py::arithmetic())
34
+ .value("Read", Flags::Read)
35
+ .value("Write", Flags::Write)
36
+ .value("Execute", Flags::Execute)
37
+ .export_values();
38
+
39
+ // test_implicit_conversion
40
+ class ClassWithUnscopedEnum {
41
+ public:
42
+ enum EMode { EFirstMode = 1, ESecondMode };
43
+
44
+ static EMode test_function(EMode mode) { return mode; }
45
+ };
46
+ py::class_<ClassWithUnscopedEnum> exenum_class(m, "ClassWithUnscopedEnum");
47
+ exenum_class.def_static("test_function", &ClassWithUnscopedEnum::test_function);
48
+ py::enum_<ClassWithUnscopedEnum::EMode>(exenum_class, "EMode")
49
+ .value("EFirstMode", ClassWithUnscopedEnum::EFirstMode)
50
+ .value("ESecondMode", ClassWithUnscopedEnum::ESecondMode)
51
+ .export_values();
52
+
53
+ // test_enum_to_int
54
+ m.def("test_enum_to_int", [](int) {});
55
+ m.def("test_enum_to_uint", [](uint32_t) {});
56
+ m.def("test_enum_to_long_long", [](long long) {});
57
+
58
+ // test_duplicate_enum_name
59
+ enum SimpleEnum { ONE, TWO, THREE };
60
+
61
+ m.def("register_bad_enum", [m]() {
62
+ py::enum_<SimpleEnum>(m, "SimpleEnum")
63
+ .value("ONE", SimpleEnum::ONE) // NOTE: all value function calls are called with the
64
+ // same first parameter value
65
+ .value("ONE", SimpleEnum::TWO)
66
+ .value("ONE", SimpleEnum::THREE)
67
+ .export_values();
68
+ });
69
+
70
+ // test_enum_scalar
71
+ enum UnscopedUCharEnum : unsigned char {};
72
+ enum class ScopedShortEnum : short {};
73
+ enum class ScopedLongEnum : long {};
74
+ enum UnscopedUInt64Enum : std::uint64_t {};
75
+ static_assert(
76
+ py::detail::all_of<
77
+ std::is_same<py::enum_<UnscopedUCharEnum>::Scalar, unsigned char>,
78
+ std::is_same<py::enum_<ScopedShortEnum>::Scalar, short>,
79
+ std::is_same<py::enum_<ScopedLongEnum>::Scalar, long>,
80
+ std::is_same<py::enum_<UnscopedUInt64Enum>::Scalar, std::uint64_t>>::value,
81
+ "Error during the deduction of enum's scalar type with normal integer underlying");
82
+
83
+ // test_enum_scalar_with_char_underlying
84
+ enum class ScopedCharEnum : char { Zero, Positive };
85
+ enum class ScopedWCharEnum : wchar_t { Zero, Positive };
86
+ enum class ScopedChar32Enum : char32_t { Zero, Positive };
87
+ enum class ScopedChar16Enum : char16_t { Zero, Positive };
88
+
89
+ // test the scalar of char type enums according to chapter 'Character types'
90
+ // from https://en.cppreference.com/w/cpp/language/types
91
+ static_assert(
92
+ py::detail::any_of<
93
+ std::is_same<py::enum_<ScopedCharEnum>::Scalar, signed char>, // e.g. gcc on x86
94
+ std::is_same<py::enum_<ScopedCharEnum>::Scalar, unsigned char> // e.g. arm linux
95
+ >::value,
96
+ "char should be cast to either signed char or unsigned char");
97
+ static_assert(sizeof(py::enum_<ScopedWCharEnum>::Scalar) == 2
98
+ || sizeof(py::enum_<ScopedWCharEnum>::Scalar) == 4,
99
+ "wchar_t should be either 16 bits (Windows) or 32 (everywhere else)");
100
+ static_assert(
101
+ py::detail::all_of<
102
+ std::is_same<py::enum_<ScopedChar32Enum>::Scalar, std::uint_least32_t>,
103
+ std::is_same<py::enum_<ScopedChar16Enum>::Scalar, std::uint_least16_t>>::value,
104
+ "char32_t, char16_t (and char8_t)'s size, signedness, and alignment is determined");
105
+ #if defined(PYBIND11_HAS_U8STRING)
106
+ enum class ScopedChar8Enum : char8_t { Zero, Positive };
107
+ static_assert(std::is_same<py::enum_<ScopedChar8Enum>::Scalar, unsigned char>::value);
108
+ #endif
109
+
110
+ // test_char_underlying_enum
111
+ py::enum_<ScopedCharEnum>(m, "ScopedCharEnum")
112
+ .value("Zero", ScopedCharEnum::Zero)
113
+ .value("Positive", ScopedCharEnum::Positive);
114
+ py::enum_<ScopedWCharEnum>(m, "ScopedWCharEnum")
115
+ .value("Zero", ScopedWCharEnum::Zero)
116
+ .value("Positive", ScopedWCharEnum::Positive);
117
+ py::enum_<ScopedChar32Enum>(m, "ScopedChar32Enum")
118
+ .value("Zero", ScopedChar32Enum::Zero)
119
+ .value("Positive", ScopedChar32Enum::Positive);
120
+ py::enum_<ScopedChar16Enum>(m, "ScopedChar16Enum")
121
+ .value("Zero", ScopedChar16Enum::Zero)
122
+ .value("Positive", ScopedChar16Enum::Positive);
123
+
124
+ // test_bool_underlying_enum
125
+ enum class ScopedBoolEnum : bool { FALSE, TRUE };
126
+
127
+ // bool is unsigned (std::is_signed returns false) and 1-byte long, so represented with u8
128
+ static_assert(std::is_same<py::enum_<ScopedBoolEnum>::Scalar, std::uint8_t>::value, "");
129
+
130
+ py::enum_<ScopedBoolEnum>(m, "ScopedBoolEnum")
131
+ .value("FALSE", ScopedBoolEnum::FALSE)
132
+ .value("TRUE", ScopedBoolEnum::TRUE);
133
+ }
third_party/CityFlow/extern/pybind11/tests/test_enum.py CHANGED
@@ -1,269 +1,269 @@
1
- # ruff: noqa: SIM201 SIM300 SIM202
2
-
3
- import pytest
4
-
5
- from pybind11_tests import enums as m
6
-
7
-
8
- def test_unscoped_enum():
9
- assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne"
10
- assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo"
11
- assert str(m.EOne) == "UnscopedEnum.EOne"
12
- assert repr(m.UnscopedEnum.EOne) == "<UnscopedEnum.EOne: 1>"
13
- assert repr(m.UnscopedEnum.ETwo) == "<UnscopedEnum.ETwo: 2>"
14
- assert repr(m.EOne) == "<UnscopedEnum.EOne: 1>"
15
-
16
- # name property
17
- assert m.UnscopedEnum.EOne.name == "EOne"
18
- assert m.UnscopedEnum.EOne.value == 1
19
- assert m.UnscopedEnum.ETwo.name == "ETwo"
20
- assert m.UnscopedEnum.ETwo.value == 2
21
- assert m.EOne is m.UnscopedEnum.EOne
22
- # name, value readonly
23
- with pytest.raises(AttributeError):
24
- m.UnscopedEnum.EOne.name = ""
25
- with pytest.raises(AttributeError):
26
- m.UnscopedEnum.EOne.value = 10
27
- # name, value returns a copy
28
- # TODO: Neither the name nor value tests actually check against aliasing.
29
- # Use a mutable type that has reference semantics.
30
- nonaliased_name = m.UnscopedEnum.EOne.name
31
- nonaliased_name = "bar" # noqa: F841
32
- assert m.UnscopedEnum.EOne.name == "EOne"
33
- nonaliased_value = m.UnscopedEnum.EOne.value
34
- nonaliased_value = 10 # noqa: F841
35
- assert m.UnscopedEnum.EOne.value == 1
36
-
37
- # __members__ property
38
- assert m.UnscopedEnum.__members__ == {
39
- "EOne": m.UnscopedEnum.EOne,
40
- "ETwo": m.UnscopedEnum.ETwo,
41
- "EThree": m.UnscopedEnum.EThree,
42
- }
43
- # __members__ readonly
44
- with pytest.raises(AttributeError):
45
- m.UnscopedEnum.__members__ = {}
46
- # __members__ returns a copy
47
- nonaliased_members = m.UnscopedEnum.__members__
48
- nonaliased_members["bar"] = "baz"
49
- assert m.UnscopedEnum.__members__ == {
50
- "EOne": m.UnscopedEnum.EOne,
51
- "ETwo": m.UnscopedEnum.ETwo,
52
- "EThree": m.UnscopedEnum.EThree,
53
- }
54
-
55
- for docstring_line in """An unscoped enumeration
56
-
57
- Members:
58
-
59
- EOne : Docstring for EOne
60
-
61
- ETwo : Docstring for ETwo
62
-
63
- EThree : Docstring for EThree""".split("\n"):
64
- assert docstring_line in m.UnscopedEnum.__doc__
65
-
66
- # Unscoped enums will accept ==/!= int comparisons
67
- y = m.UnscopedEnum.ETwo
68
- assert y == 2
69
- assert 2 == y
70
- assert y != 3
71
- assert 3 != y
72
- # Compare with None
73
- assert y != None # noqa: E711
74
- assert not (y == None) # noqa: E711
75
- # Compare with an object
76
- assert y != object()
77
- assert not (y == object())
78
- # Compare with string
79
- assert y != "2"
80
- assert "2" != y
81
- assert not ("2" == y)
82
- assert not (y == "2")
83
-
84
- with pytest.raises(TypeError):
85
- y < object() # noqa: B015
86
-
87
- with pytest.raises(TypeError):
88
- y <= object() # noqa: B015
89
-
90
- with pytest.raises(TypeError):
91
- y > object() # noqa: B015
92
-
93
- with pytest.raises(TypeError):
94
- y >= object() # noqa: B015
95
-
96
- with pytest.raises(TypeError):
97
- y | object()
98
-
99
- with pytest.raises(TypeError):
100
- y & object()
101
-
102
- with pytest.raises(TypeError):
103
- y ^ object()
104
-
105
- assert int(m.UnscopedEnum.ETwo) == 2
106
- assert str(m.UnscopedEnum(2)) == "UnscopedEnum.ETwo"
107
-
108
- # order
109
- assert m.UnscopedEnum.EOne < m.UnscopedEnum.ETwo
110
- assert m.UnscopedEnum.EOne < 2
111
- assert m.UnscopedEnum.ETwo > m.UnscopedEnum.EOne
112
- assert m.UnscopedEnum.ETwo > 1
113
- assert m.UnscopedEnum.ETwo <= 2
114
- assert m.UnscopedEnum.ETwo >= 2
115
- assert m.UnscopedEnum.EOne <= m.UnscopedEnum.ETwo
116
- assert m.UnscopedEnum.EOne <= 2
117
- assert m.UnscopedEnum.ETwo >= m.UnscopedEnum.EOne
118
- assert m.UnscopedEnum.ETwo >= 1
119
- assert not (m.UnscopedEnum.ETwo < m.UnscopedEnum.EOne)
120
- assert not (2 < m.UnscopedEnum.EOne)
121
-
122
- # arithmetic
123
- assert m.UnscopedEnum.EOne & m.UnscopedEnum.EThree == m.UnscopedEnum.EOne
124
- assert m.UnscopedEnum.EOne | m.UnscopedEnum.ETwo == m.UnscopedEnum.EThree
125
- assert m.UnscopedEnum.EOne ^ m.UnscopedEnum.EThree == m.UnscopedEnum.ETwo
126
-
127
-
128
- def test_scoped_enum():
129
- assert m.test_scoped_enum(m.ScopedEnum.Three) == "ScopedEnum::Three"
130
- z = m.ScopedEnum.Two
131
- assert m.test_scoped_enum(z) == "ScopedEnum::Two"
132
-
133
- # Scoped enums will *NOT* accept ==/!= int comparisons (Will always return False)
134
- assert not z == 3
135
- assert not 3 == z
136
- assert z != 3
137
- assert 3 != z
138
- # Compare with None
139
- assert z != None # noqa: E711
140
- assert not (z == None) # noqa: E711
141
- # Compare with an object
142
- assert z != object()
143
- assert not (z == object())
144
- # Scoped enums will *NOT* accept >, <, >= and <= int comparisons (Will throw exceptions)
145
- with pytest.raises(TypeError):
146
- z > 3 # noqa: B015
147
- with pytest.raises(TypeError):
148
- z < 3 # noqa: B015
149
- with pytest.raises(TypeError):
150
- z >= 3 # noqa: B015
151
- with pytest.raises(TypeError):
152
- z <= 3 # noqa: B015
153
-
154
- # order
155
- assert m.ScopedEnum.Two < m.ScopedEnum.Three
156
- assert m.ScopedEnum.Three > m.ScopedEnum.Two
157
- assert m.ScopedEnum.Two <= m.ScopedEnum.Three
158
- assert m.ScopedEnum.Two <= m.ScopedEnum.Two
159
- assert m.ScopedEnum.Two >= m.ScopedEnum.Two
160
- assert m.ScopedEnum.Three >= m.ScopedEnum.Two
161
-
162
-
163
- def test_implicit_conversion():
164
- assert str(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "EMode.EFirstMode"
165
- assert str(m.ClassWithUnscopedEnum.EFirstMode) == "EMode.EFirstMode"
166
- assert repr(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "<EMode.EFirstMode: 1>"
167
- assert repr(m.ClassWithUnscopedEnum.EFirstMode) == "<EMode.EFirstMode: 1>"
168
-
169
- f = m.ClassWithUnscopedEnum.test_function
170
- first = m.ClassWithUnscopedEnum.EFirstMode
171
- second = m.ClassWithUnscopedEnum.ESecondMode
172
-
173
- assert f(first) == 1
174
-
175
- assert f(first) == f(first)
176
- assert not f(first) != f(first)
177
-
178
- assert f(first) != f(second)
179
- assert not f(first) == f(second)
180
-
181
- assert f(first) == int(f(first))
182
- assert not f(first) != int(f(first))
183
-
184
- assert f(first) != int(f(second))
185
- assert not f(first) == int(f(second))
186
-
187
- # noinspection PyDictCreation
188
- x = {f(first): 1, f(second): 2}
189
- x[f(first)] = 3
190
- x[f(second)] = 4
191
- # Hashing test
192
- assert repr(x) == "{<EMode.EFirstMode: 1>: 3, <EMode.ESecondMode: 2>: 4}"
193
-
194
-
195
- def test_binary_operators():
196
- assert int(m.Flags.Read) == 4
197
- assert int(m.Flags.Write) == 2
198
- assert int(m.Flags.Execute) == 1
199
- assert int(m.Flags.Read | m.Flags.Write | m.Flags.Execute) == 7
200
- assert int(m.Flags.Read | m.Flags.Write) == 6
201
- assert int(m.Flags.Read | m.Flags.Execute) == 5
202
- assert int(m.Flags.Write | m.Flags.Execute) == 3
203
- assert int(m.Flags.Write | 1) == 3
204
- assert ~m.Flags.Write == -3
205
-
206
- state = m.Flags.Read | m.Flags.Write
207
- assert (state & m.Flags.Read) != 0
208
- assert (state & m.Flags.Write) != 0
209
- assert (state & m.Flags.Execute) == 0
210
- assert (state & 1) == 0
211
-
212
- state2 = ~state
213
- assert state2 == -7
214
- assert int(state ^ state2) == -1
215
-
216
-
217
- def test_enum_to_int():
218
- m.test_enum_to_int(m.Flags.Read)
219
- m.test_enum_to_int(m.ClassWithUnscopedEnum.EMode.EFirstMode)
220
- m.test_enum_to_int(m.ScopedCharEnum.Positive)
221
- m.test_enum_to_int(m.ScopedBoolEnum.TRUE)
222
- m.test_enum_to_uint(m.Flags.Read)
223
- m.test_enum_to_uint(m.ClassWithUnscopedEnum.EMode.EFirstMode)
224
- m.test_enum_to_uint(m.ScopedCharEnum.Positive)
225
- m.test_enum_to_uint(m.ScopedBoolEnum.TRUE)
226
- m.test_enum_to_long_long(m.Flags.Read)
227
- m.test_enum_to_long_long(m.ClassWithUnscopedEnum.EMode.EFirstMode)
228
- m.test_enum_to_long_long(m.ScopedCharEnum.Positive)
229
- m.test_enum_to_long_long(m.ScopedBoolEnum.TRUE)
230
-
231
-
232
- def test_duplicate_enum_name():
233
- with pytest.raises(ValueError) as excinfo:
234
- m.register_bad_enum()
235
- assert str(excinfo.value) == 'SimpleEnum: element "ONE" already exists!'
236
-
237
-
238
- def test_char_underlying_enum(): # Issue #1331/PR #1334:
239
- assert type(m.ScopedCharEnum.Positive.__int__()) is int
240
- assert int(m.ScopedChar16Enum.Zero) == 0
241
- assert hash(m.ScopedChar32Enum.Positive) == 1
242
- assert type(m.ScopedCharEnum.Positive.__getstate__()) is int
243
- assert m.ScopedWCharEnum(1) == m.ScopedWCharEnum.Positive
244
- with pytest.raises(TypeError):
245
- # Even if the underlying type is char, only an int can be used to construct the enum:
246
- m.ScopedCharEnum("0")
247
-
248
-
249
- def test_bool_underlying_enum():
250
- assert type(m.ScopedBoolEnum.TRUE.__int__()) is int
251
- assert int(m.ScopedBoolEnum.FALSE) == 0
252
- assert hash(m.ScopedBoolEnum.TRUE) == 1
253
- assert type(m.ScopedBoolEnum.TRUE.__getstate__()) is int
254
- assert m.ScopedBoolEnum(1) == m.ScopedBoolEnum.TRUE
255
- # Enum could construct with a bool
256
- # (bool is a strict subclass of int, and False will be converted to 0)
257
- assert m.ScopedBoolEnum(False) == m.ScopedBoolEnum.FALSE
258
-
259
-
260
- def test_docstring_signatures():
261
- for enum_type in [m.ScopedEnum, m.UnscopedEnum]:
262
- for attr in enum_type.__dict__.values():
263
- # Issue #2623/PR #2637: Add argument names to enum_ methods
264
- assert "arg0" not in (attr.__doc__ or "")
265
-
266
-
267
- def test_str_signature():
268
- for enum_type in [m.ScopedEnum, m.UnscopedEnum]:
269
- assert enum_type.__str__.__doc__.startswith("__str__")
 
1
+ # ruff: noqa: SIM201 SIM300 SIM202
2
+
3
+ import pytest
4
+
5
+ from pybind11_tests import enums as m
6
+
7
+
8
+ def test_unscoped_enum():
9
+ assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne"
10
+ assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo"
11
+ assert str(m.EOne) == "UnscopedEnum.EOne"
12
+ assert repr(m.UnscopedEnum.EOne) == "<UnscopedEnum.EOne: 1>"
13
+ assert repr(m.UnscopedEnum.ETwo) == "<UnscopedEnum.ETwo: 2>"
14
+ assert repr(m.EOne) == "<UnscopedEnum.EOne: 1>"
15
+
16
+ # name property
17
+ assert m.UnscopedEnum.EOne.name == "EOne"
18
+ assert m.UnscopedEnum.EOne.value == 1
19
+ assert m.UnscopedEnum.ETwo.name == "ETwo"
20
+ assert m.UnscopedEnum.ETwo.value == 2
21
+ assert m.EOne is m.UnscopedEnum.EOne
22
+ # name, value readonly
23
+ with pytest.raises(AttributeError):
24
+ m.UnscopedEnum.EOne.name = ""
25
+ with pytest.raises(AttributeError):
26
+ m.UnscopedEnum.EOne.value = 10
27
+ # name, value returns a copy
28
+ # TODO: Neither the name nor value tests actually check against aliasing.
29
+ # Use a mutable type that has reference semantics.
30
+ nonaliased_name = m.UnscopedEnum.EOne.name
31
+ nonaliased_name = "bar" # noqa: F841
32
+ assert m.UnscopedEnum.EOne.name == "EOne"
33
+ nonaliased_value = m.UnscopedEnum.EOne.value
34
+ nonaliased_value = 10 # noqa: F841
35
+ assert m.UnscopedEnum.EOne.value == 1
36
+
37
+ # __members__ property
38
+ assert m.UnscopedEnum.__members__ == {
39
+ "EOne": m.UnscopedEnum.EOne,
40
+ "ETwo": m.UnscopedEnum.ETwo,
41
+ "EThree": m.UnscopedEnum.EThree,
42
+ }
43
+ # __members__ readonly
44
+ with pytest.raises(AttributeError):
45
+ m.UnscopedEnum.__members__ = {}
46
+ # __members__ returns a copy
47
+ nonaliased_members = m.UnscopedEnum.__members__
48
+ nonaliased_members["bar"] = "baz"
49
+ assert m.UnscopedEnum.__members__ == {
50
+ "EOne": m.UnscopedEnum.EOne,
51
+ "ETwo": m.UnscopedEnum.ETwo,
52
+ "EThree": m.UnscopedEnum.EThree,
53
+ }
54
+
55
+ for docstring_line in """An unscoped enumeration
56
+
57
+ Members:
58
+
59
+ EOne : Docstring for EOne
60
+
61
+ ETwo : Docstring for ETwo
62
+
63
+ EThree : Docstring for EThree""".split("\n"):
64
+ assert docstring_line in m.UnscopedEnum.__doc__
65
+
66
+ # Unscoped enums will accept ==/!= int comparisons
67
+ y = m.UnscopedEnum.ETwo
68
+ assert y == 2
69
+ assert 2 == y
70
+ assert y != 3
71
+ assert 3 != y
72
+ # Compare with None
73
+ assert y != None # noqa: E711
74
+ assert not (y == None) # noqa: E711
75
+ # Compare with an object
76
+ assert y != object()
77
+ assert not (y == object())
78
+ # Compare with string
79
+ assert y != "2"
80
+ assert "2" != y
81
+ assert not ("2" == y)
82
+ assert not (y == "2")
83
+
84
+ with pytest.raises(TypeError):
85
+ y < object() # noqa: B015
86
+
87
+ with pytest.raises(TypeError):
88
+ y <= object() # noqa: B015
89
+
90
+ with pytest.raises(TypeError):
91
+ y > object() # noqa: B015
92
+
93
+ with pytest.raises(TypeError):
94
+ y >= object() # noqa: B015
95
+
96
+ with pytest.raises(TypeError):
97
+ y | object()
98
+
99
+ with pytest.raises(TypeError):
100
+ y & object()
101
+
102
+ with pytest.raises(TypeError):
103
+ y ^ object()
104
+
105
+ assert int(m.UnscopedEnum.ETwo) == 2
106
+ assert str(m.UnscopedEnum(2)) == "UnscopedEnum.ETwo"
107
+
108
+ # order
109
+ assert m.UnscopedEnum.EOne < m.UnscopedEnum.ETwo
110
+ assert m.UnscopedEnum.EOne < 2
111
+ assert m.UnscopedEnum.ETwo > m.UnscopedEnum.EOne
112
+ assert m.UnscopedEnum.ETwo > 1
113
+ assert m.UnscopedEnum.ETwo <= 2
114
+ assert m.UnscopedEnum.ETwo >= 2
115
+ assert m.UnscopedEnum.EOne <= m.UnscopedEnum.ETwo
116
+ assert m.UnscopedEnum.EOne <= 2
117
+ assert m.UnscopedEnum.ETwo >= m.UnscopedEnum.EOne
118
+ assert m.UnscopedEnum.ETwo >= 1
119
+ assert not (m.UnscopedEnum.ETwo < m.UnscopedEnum.EOne)
120
+ assert not (2 < m.UnscopedEnum.EOne)
121
+
122
+ # arithmetic
123
+ assert m.UnscopedEnum.EOne & m.UnscopedEnum.EThree == m.UnscopedEnum.EOne
124
+ assert m.UnscopedEnum.EOne | m.UnscopedEnum.ETwo == m.UnscopedEnum.EThree
125
+ assert m.UnscopedEnum.EOne ^ m.UnscopedEnum.EThree == m.UnscopedEnum.ETwo
126
+
127
+
128
+ def test_scoped_enum():
129
+ assert m.test_scoped_enum(m.ScopedEnum.Three) == "ScopedEnum::Three"
130
+ z = m.ScopedEnum.Two
131
+ assert m.test_scoped_enum(z) == "ScopedEnum::Two"
132
+
133
+ # Scoped enums will *NOT* accept ==/!= int comparisons (Will always return False)
134
+ assert not z == 3
135
+ assert not 3 == z
136
+ assert z != 3
137
+ assert 3 != z
138
+ # Compare with None
139
+ assert z != None # noqa: E711
140
+ assert not (z == None) # noqa: E711
141
+ # Compare with an object
142
+ assert z != object()
143
+ assert not (z == object())
144
+ # Scoped enums will *NOT* accept >, <, >= and <= int comparisons (Will throw exceptions)
145
+ with pytest.raises(TypeError):
146
+ z > 3 # noqa: B015
147
+ with pytest.raises(TypeError):
148
+ z < 3 # noqa: B015
149
+ with pytest.raises(TypeError):
150
+ z >= 3 # noqa: B015
151
+ with pytest.raises(TypeError):
152
+ z <= 3 # noqa: B015
153
+
154
+ # order
155
+ assert m.ScopedEnum.Two < m.ScopedEnum.Three
156
+ assert m.ScopedEnum.Three > m.ScopedEnum.Two
157
+ assert m.ScopedEnum.Two <= m.ScopedEnum.Three
158
+ assert m.ScopedEnum.Two <= m.ScopedEnum.Two
159
+ assert m.ScopedEnum.Two >= m.ScopedEnum.Two
160
+ assert m.ScopedEnum.Three >= m.ScopedEnum.Two
161
+
162
+
163
+ def test_implicit_conversion():
164
+ assert str(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "EMode.EFirstMode"
165
+ assert str(m.ClassWithUnscopedEnum.EFirstMode) == "EMode.EFirstMode"
166
+ assert repr(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "<EMode.EFirstMode: 1>"
167
+ assert repr(m.ClassWithUnscopedEnum.EFirstMode) == "<EMode.EFirstMode: 1>"
168
+
169
+ f = m.ClassWithUnscopedEnum.test_function
170
+ first = m.ClassWithUnscopedEnum.EFirstMode
171
+ second = m.ClassWithUnscopedEnum.ESecondMode
172
+
173
+ assert f(first) == 1
174
+
175
+ assert f(first) == f(first)
176
+ assert not f(first) != f(first)
177
+
178
+ assert f(first) != f(second)
179
+ assert not f(first) == f(second)
180
+
181
+ assert f(first) == int(f(first))
182
+ assert not f(first) != int(f(first))
183
+
184
+ assert f(first) != int(f(second))
185
+ assert not f(first) == int(f(second))
186
+
187
+ # noinspection PyDictCreation
188
+ x = {f(first): 1, f(second): 2}
189
+ x[f(first)] = 3
190
+ x[f(second)] = 4
191
+ # Hashing test
192
+ assert repr(x) == "{<EMode.EFirstMode: 1>: 3, <EMode.ESecondMode: 2>: 4}"
193
+
194
+
195
+ def test_binary_operators():
196
+ assert int(m.Flags.Read) == 4
197
+ assert int(m.Flags.Write) == 2
198
+ assert int(m.Flags.Execute) == 1
199
+ assert int(m.Flags.Read | m.Flags.Write | m.Flags.Execute) == 7
200
+ assert int(m.Flags.Read | m.Flags.Write) == 6
201
+ assert int(m.Flags.Read | m.Flags.Execute) == 5
202
+ assert int(m.Flags.Write | m.Flags.Execute) == 3
203
+ assert int(m.Flags.Write | 1) == 3
204
+ assert ~m.Flags.Write == -3
205
+
206
+ state = m.Flags.Read | m.Flags.Write
207
+ assert (state & m.Flags.Read) != 0
208
+ assert (state & m.Flags.Write) != 0
209
+ assert (state & m.Flags.Execute) == 0
210
+ assert (state & 1) == 0
211
+
212
+ state2 = ~state
213
+ assert state2 == -7
214
+ assert int(state ^ state2) == -1
215
+
216
+
217
+ def test_enum_to_int():
218
+ m.test_enum_to_int(m.Flags.Read)
219
+ m.test_enum_to_int(m.ClassWithUnscopedEnum.EMode.EFirstMode)
220
+ m.test_enum_to_int(m.ScopedCharEnum.Positive)
221
+ m.test_enum_to_int(m.ScopedBoolEnum.TRUE)
222
+ m.test_enum_to_uint(m.Flags.Read)
223
+ m.test_enum_to_uint(m.ClassWithUnscopedEnum.EMode.EFirstMode)
224
+ m.test_enum_to_uint(m.ScopedCharEnum.Positive)
225
+ m.test_enum_to_uint(m.ScopedBoolEnum.TRUE)
226
+ m.test_enum_to_long_long(m.Flags.Read)
227
+ m.test_enum_to_long_long(m.ClassWithUnscopedEnum.EMode.EFirstMode)
228
+ m.test_enum_to_long_long(m.ScopedCharEnum.Positive)
229
+ m.test_enum_to_long_long(m.ScopedBoolEnum.TRUE)
230
+
231
+
232
+ def test_duplicate_enum_name():
233
+ with pytest.raises(ValueError) as excinfo:
234
+ m.register_bad_enum()
235
+ assert str(excinfo.value) == 'SimpleEnum: element "ONE" already exists!'
236
+
237
+
238
+ def test_char_underlying_enum(): # Issue #1331/PR #1334:
239
+ assert type(m.ScopedCharEnum.Positive.__int__()) is int
240
+ assert int(m.ScopedChar16Enum.Zero) == 0
241
+ assert hash(m.ScopedChar32Enum.Positive) == 1
242
+ assert type(m.ScopedCharEnum.Positive.__getstate__()) is int
243
+ assert m.ScopedWCharEnum(1) == m.ScopedWCharEnum.Positive
244
+ with pytest.raises(TypeError):
245
+ # Even if the underlying type is char, only an int can be used to construct the enum:
246
+ m.ScopedCharEnum("0")
247
+
248
+
249
+ def test_bool_underlying_enum():
250
+ assert type(m.ScopedBoolEnum.TRUE.__int__()) is int
251
+ assert int(m.ScopedBoolEnum.FALSE) == 0
252
+ assert hash(m.ScopedBoolEnum.TRUE) == 1
253
+ assert type(m.ScopedBoolEnum.TRUE.__getstate__()) is int
254
+ assert m.ScopedBoolEnum(1) == m.ScopedBoolEnum.TRUE
255
+ # Enum could construct with a bool
256
+ # (bool is a strict subclass of int, and False will be converted to 0)
257
+ assert m.ScopedBoolEnum(False) == m.ScopedBoolEnum.FALSE
258
+
259
+
260
+ def test_docstring_signatures():
261
+ for enum_type in [m.ScopedEnum, m.UnscopedEnum]:
262
+ for attr in enum_type.__dict__.values():
263
+ # Issue #2623/PR #2637: Add argument names to enum_ methods
264
+ assert "arg0" not in (attr.__doc__ or "")
265
+
266
+
267
+ def test_str_signature():
268
+ for enum_type in [m.ScopedEnum, m.UnscopedEnum]:
269
+ assert enum_type.__str__.__doc__.startswith("__str__")
third_party/CityFlow/extern/pybind11/tests/test_eval.cpp CHANGED
@@ -1,118 +1,118 @@
1
- /*
2
- tests/test_eval.cpp -- Usage of eval() and eval_file()
3
-
4
- Copyright (c) 2016 Klemens D. Morgenstern
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
-
10
- #include <pybind11/eval.h>
11
-
12
- #include "pybind11_tests.h"
13
-
14
- #include <utility>
15
-
16
- TEST_SUBMODULE(eval_, m) {
17
- // test_evals
18
-
19
- auto global = py::dict(py::module_::import("__main__").attr("__dict__"));
20
-
21
- m.def("test_eval_statements", [global]() {
22
- auto local = py::dict();
23
- local["call_test"] = py::cpp_function([&]() -> int { return 42; });
24
-
25
- // Regular string literal
26
- py::exec("message = 'Hello World!'\n"
27
- "x = call_test()",
28
- global,
29
- local);
30
-
31
- // Multi-line raw string literal
32
- py::exec(R"(
33
- if x == 42:
34
- print(message)
35
- else:
36
- raise RuntimeError
37
- )",
38
- global,
39
- local);
40
- auto x = local["x"].cast<int>();
41
-
42
- return x == 42;
43
- });
44
-
45
- m.def("test_eval", [global]() {
46
- auto local = py::dict();
47
- local["x"] = py::int_(42);
48
- auto x = py::eval("x", global, local);
49
- return x.cast<int>() == 42;
50
- });
51
-
52
- m.def("test_eval_single_statement", []() {
53
- auto local = py::dict();
54
- local["call_test"] = py::cpp_function([&]() -> int { return 42; });
55
-
56
- auto result = py::eval<py::eval_single_statement>("x = call_test()", py::dict(), local);
57
- auto x = local["x"].cast<int>();
58
- return result.is_none() && x == 42;
59
- });
60
-
61
- m.def("test_eval_file", [global](py::str filename) {
62
- auto local = py::dict();
63
- local["y"] = py::int_(43);
64
-
65
- int val_out = 0;
66
- local["call_test2"] = py::cpp_function([&](int value) { val_out = value; });
67
-
68
- auto result = py::eval_file(std::move(filename), global, local);
69
- return val_out == 43 && result.is_none();
70
- });
71
-
72
- m.def("test_eval_failure", []() {
73
- try {
74
- py::eval("nonsense code ...");
75
- } catch (py::error_already_set &) {
76
- return true;
77
- }
78
- return false;
79
- });
80
-
81
- m.def("test_eval_file_failure", []() {
82
- try {
83
- py::eval_file("non-existing file");
84
- } catch (std::exception &) {
85
- return true;
86
- }
87
- return false;
88
- });
89
-
90
- // test_eval_empty_globals
91
- m.def("eval_empty_globals", [](py::object global) {
92
- if (global.is_none()) {
93
- global = py::dict();
94
- }
95
- auto int_class = py::eval("isinstance(42, int)", global);
96
- return global;
97
- });
98
-
99
- // test_eval_closure
100
- m.def("test_eval_closure", []() {
101
- py::dict global;
102
- global["closure_value"] = 42;
103
- py::dict local;
104
- local["closure_value"] = 0;
105
- py::exec(R"(
106
- local_value = closure_value
107
-
108
- def func_global():
109
- return closure_value
110
-
111
- def func_local():
112
- return local_value
113
- )",
114
- global,
115
- local);
116
- return std::make_pair(global, local);
117
- });
118
- }
 
1
+ /*
2
+ tests/test_eval.cpp -- Usage of eval() and eval_file()
3
+
4
+ Copyright (c) 2016 Klemens D. Morgenstern
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #include <pybind11/eval.h>
11
+
12
+ #include "pybind11_tests.h"
13
+
14
+ #include <utility>
15
+
16
+ TEST_SUBMODULE(eval_, m) {
17
+ // test_evals
18
+
19
+ auto global = py::dict(py::module_::import("__main__").attr("__dict__"));
20
+
21
+ m.def("test_eval_statements", [global]() {
22
+ auto local = py::dict();
23
+ local["call_test"] = py::cpp_function([&]() -> int { return 42; });
24
+
25
+ // Regular string literal
26
+ py::exec("message = 'Hello World!'\n"
27
+ "x = call_test()",
28
+ global,
29
+ local);
30
+
31
+ // Multi-line raw string literal
32
+ py::exec(R"(
33
+ if x == 42:
34
+ print(message)
35
+ else:
36
+ raise RuntimeError
37
+ )",
38
+ global,
39
+ local);
40
+ auto x = local["x"].cast<int>();
41
+
42
+ return x == 42;
43
+ });
44
+
45
+ m.def("test_eval", [global]() {
46
+ auto local = py::dict();
47
+ local["x"] = py::int_(42);
48
+ auto x = py::eval("x", global, local);
49
+ return x.cast<int>() == 42;
50
+ });
51
+
52
+ m.def("test_eval_single_statement", []() {
53
+ auto local = py::dict();
54
+ local["call_test"] = py::cpp_function([&]() -> int { return 42; });
55
+
56
+ auto result = py::eval<py::eval_single_statement>("x = call_test()", py::dict(), local);
57
+ auto x = local["x"].cast<int>();
58
+ return result.is_none() && x == 42;
59
+ });
60
+
61
+ m.def("test_eval_file", [global](py::str filename) {
62
+ auto local = py::dict();
63
+ local["y"] = py::int_(43);
64
+
65
+ int val_out = 0;
66
+ local["call_test2"] = py::cpp_function([&](int value) { val_out = value; });
67
+
68
+ auto result = py::eval_file(std::move(filename), global, local);
69
+ return val_out == 43 && result.is_none();
70
+ });
71
+
72
+ m.def("test_eval_failure", []() {
73
+ try {
74
+ py::eval("nonsense code ...");
75
+ } catch (py::error_already_set &) {
76
+ return true;
77
+ }
78
+ return false;
79
+ });
80
+
81
+ m.def("test_eval_file_failure", []() {
82
+ try {
83
+ py::eval_file("non-existing file");
84
+ } catch (std::exception &) {
85
+ return true;
86
+ }
87
+ return false;
88
+ });
89
+
90
+ // test_eval_empty_globals
91
+ m.def("eval_empty_globals", [](py::object global) {
92
+ if (global.is_none()) {
93
+ global = py::dict();
94
+ }
95
+ auto int_class = py::eval("isinstance(42, int)", global);
96
+ return global;
97
+ });
98
+
99
+ // test_eval_closure
100
+ m.def("test_eval_closure", []() {
101
+ py::dict global;
102
+ global["closure_value"] = 42;
103
+ py::dict local;
104
+ local["closure_value"] = 0;
105
+ py::exec(R"(
106
+ local_value = closure_value
107
+
108
+ def func_global():
109
+ return closure_value
110
+
111
+ def func_local():
112
+ return local_value
113
+ )",
114
+ global,
115
+ local);
116
+ return std::make_pair(global, local);
117
+ });
118
+ }
third_party/CityFlow/extern/pybind11/tests/test_eval.py CHANGED
@@ -1,50 +1,50 @@
1
- import os
2
-
3
- import pytest
4
-
5
- import env # noqa: F401
6
- from pybind11_tests import eval_ as m
7
-
8
-
9
- def test_evals(capture):
10
- with capture:
11
- assert m.test_eval_statements()
12
- assert capture == "Hello World!"
13
-
14
- assert m.test_eval()
15
- assert m.test_eval_single_statement()
16
-
17
- assert m.test_eval_failure()
18
-
19
-
20
- @pytest.mark.xfail("env.PYPY", raises=RuntimeError)
21
- def test_eval_file():
22
- filename = os.path.join(os.path.dirname(__file__), "test_eval_call.py")
23
- assert m.test_eval_file(filename)
24
-
25
- assert m.test_eval_file_failure()
26
-
27
-
28
- def test_eval_empty_globals():
29
- assert "__builtins__" in m.eval_empty_globals(None)
30
-
31
- g = {}
32
- assert "__builtins__" in m.eval_empty_globals(g)
33
- assert "__builtins__" in g
34
-
35
-
36
- def test_eval_closure():
37
- global_, local = m.test_eval_closure()
38
-
39
- assert global_["closure_value"] == 42
40
- assert local["closure_value"] == 0
41
-
42
- assert "local_value" not in global_
43
- assert local["local_value"] == 0
44
-
45
- assert "func_global" not in global_
46
- assert local["func_global"]() == 42
47
-
48
- assert "func_local" not in global_
49
- with pytest.raises(NameError):
50
- local["func_local"]()
 
1
+ import os
2
+
3
+ import pytest
4
+
5
+ import env # noqa: F401
6
+ from pybind11_tests import eval_ as m
7
+
8
+
9
+ def test_evals(capture):
10
+ with capture:
11
+ assert m.test_eval_statements()
12
+ assert capture == "Hello World!"
13
+
14
+ assert m.test_eval()
15
+ assert m.test_eval_single_statement()
16
+
17
+ assert m.test_eval_failure()
18
+
19
+
20
+ @pytest.mark.xfail("env.PYPY", raises=RuntimeError)
21
+ def test_eval_file():
22
+ filename = os.path.join(os.path.dirname(__file__), "test_eval_call.py")
23
+ assert m.test_eval_file(filename)
24
+
25
+ assert m.test_eval_file_failure()
26
+
27
+
28
+ def test_eval_empty_globals():
29
+ assert "__builtins__" in m.eval_empty_globals(None)
30
+
31
+ g = {}
32
+ assert "__builtins__" in m.eval_empty_globals(g)
33
+ assert "__builtins__" in g
34
+
35
+
36
+ def test_eval_closure():
37
+ global_, local = m.test_eval_closure()
38
+
39
+ assert global_["closure_value"] == 42
40
+ assert local["closure_value"] == 0
41
+
42
+ assert "local_value" not in global_
43
+ assert local["local_value"] == 0
44
+
45
+ assert "func_global" not in global_
46
+ assert local["func_global"]() == 42
47
+
48
+ assert "func_local" not in global_
49
+ with pytest.raises(NameError):
50
+ local["func_local"]()
third_party/CityFlow/extern/pybind11/tests/test_eval_call.py CHANGED
@@ -1,4 +1,4 @@
1
- # This file is called from 'test_eval.py'
2
-
3
- if "call_test2" in locals():
4
- call_test2(y) # noqa: F821 undefined name
 
1
+ # This file is called from 'test_eval.py'
2
+
3
+ if "call_test2" in locals():
4
+ call_test2(y) # noqa: F821 undefined name
third_party/CityFlow/extern/pybind11/tests/test_exceptions.cpp CHANGED
@@ -1,388 +1,388 @@
1
- /*
2
- tests/test_custom-exceptions.cpp -- exception translation
3
-
4
- Copyright (c) 2016 Pim Schellart <P.Schellart@princeton.edu>
5
-
6
- All rights reserved. Use of this source code is governed by a
7
- BSD-style license that can be found in the LICENSE file.
8
- */
9
- #include <pybind11/gil_safe_call_once.h>
10
-
11
- #include "test_exceptions.h"
12
-
13
- #include "local_bindings.h"
14
- #include "pybind11_tests.h"
15
-
16
- #include <exception>
17
- #include <stdexcept>
18
- #include <utility>
19
-
20
- // A type that should be raised as an exception in Python
21
- class MyException : public std::exception {
22
- public:
23
- explicit MyException(const char *m) : message{m} {}
24
- const char *what() const noexcept override { return message.c_str(); }
25
-
26
- private:
27
- std::string message = "";
28
- };
29
-
30
- class MyExceptionUseDeprecatedOperatorCall : public MyException {
31
- using MyException::MyException;
32
- };
33
-
34
- // A type that should be translated to a standard Python exception
35
- class MyException2 : public std::exception {
36
- public:
37
- explicit MyException2(const char *m) : message{m} {}
38
- const char *what() const noexcept override { return message.c_str(); }
39
-
40
- private:
41
- std::string message = "";
42
- };
43
-
44
- // A type that is not derived from std::exception (and is thus unknown)
45
- class MyException3 {
46
- public:
47
- explicit MyException3(const char *m) : message{m} {}
48
- virtual const char *what() const noexcept { return message.c_str(); }
49
- // Rule of 5 BEGIN: to preempt compiler warnings.
50
- MyException3(const MyException3 &) = default;
51
- MyException3(MyException3 &&) = default;
52
- MyException3 &operator=(const MyException3 &) = default;
53
- MyException3 &operator=(MyException3 &&) = default;
54
- virtual ~MyException3() = default;
55
- // Rule of 5 END.
56
- private:
57
- std::string message = "";
58
- };
59
-
60
- // A type that should be translated to MyException
61
- // and delegated to its exception translator
62
- class MyException4 : public std::exception {
63
- public:
64
- explicit MyException4(const char *m) : message{m} {}
65
- const char *what() const noexcept override { return message.c_str(); }
66
-
67
- private:
68
- std::string message = "";
69
- };
70
-
71
- // Like the above, but declared via the helper function
72
- class MyException5 : public std::logic_error {
73
- public:
74
- explicit MyException5(const std::string &what) : std::logic_error(what) {}
75
- };
76
-
77
- // Inherits from MyException5
78
- class MyException5_1 : public MyException5 {
79
- using MyException5::MyException5;
80
- };
81
-
82
- // Exception that will be caught via the module local translator.
83
- class MyException6 : public std::exception {
84
- public:
85
- explicit MyException6(const char *m) : message{m} {}
86
- const char *what() const noexcept override { return message.c_str(); }
87
-
88
- private:
89
- std::string message = "";
90
- };
91
-
92
- struct PythonCallInDestructor {
93
- explicit PythonCallInDestructor(const py::dict &d) : d(d) {}
94
- ~PythonCallInDestructor() { d["good"] = true; }
95
-
96
- py::dict d;
97
- };
98
-
99
- struct PythonAlreadySetInDestructor {
100
- explicit PythonAlreadySetInDestructor(const py::str &s) : s(s) {}
101
- ~PythonAlreadySetInDestructor() {
102
- py::dict foo;
103
- try {
104
- // Assign to a py::object to force read access of nonexistent dict entry
105
- py::object o = foo["bar"];
106
- } catch (py::error_already_set &ex) {
107
- ex.discard_as_unraisable(s);
108
- }
109
- }
110
-
111
- py::str s;
112
- };
113
-
114
- TEST_SUBMODULE(exceptions, m) {
115
- m.def("throw_std_exception",
116
- []() { throw std::runtime_error("This exception was intentionally thrown."); });
117
-
118
- // PLEASE KEEP IN SYNC with docs/advanced/exceptions.rst
119
- PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object> ex_storage;
120
- ex_storage.call_once_and_store_result(
121
- [&]() { return py::exception<MyException>(m, "MyException"); });
122
- py::register_exception_translator([](std::exception_ptr p) {
123
- try {
124
- if (p) {
125
- std::rethrow_exception(p);
126
- }
127
- } catch (const MyException &e) {
128
- // Set MyException as the active python error
129
- py::set_error(ex_storage.get_stored(), e.what());
130
- }
131
- });
132
-
133
- // Same as above, but using the deprecated `py::exception<>::operator()`
134
- // We want to be sure it still works, until it's removed.
135
- static const auto *const exd = new py::exception<MyExceptionUseDeprecatedOperatorCall>(
136
- m, "MyExceptionUseDeprecatedOperatorCall");
137
- py::register_exception_translator([](std::exception_ptr p) {
138
- try {
139
- if (p) {
140
- std::rethrow_exception(p);
141
- }
142
- } catch (const MyExceptionUseDeprecatedOperatorCall &e) {
143
- #if defined(__INTEL_COMPILER) || defined(__NVCOMPILER)
144
- // It is not worth the trouble dealing with warning suppressions for these compilers.
145
- // Falling back to the recommended approach to keep the test code simple.
146
- py::set_error(*exd, e.what());
147
- #else
148
- PYBIND11_WARNING_PUSH
149
- PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
150
- PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
151
- PYBIND11_WARNING_DISABLE_MSVC(4996)
152
- (*exd)(e.what());
153
- PYBIND11_WARNING_POP
154
- #endif
155
- }
156
- });
157
-
158
- // register new translator for MyException2
159
- // no need to store anything here because this type will
160
- // never by visible from Python
161
- py::register_exception_translator([](std::exception_ptr p) {
162
- try {
163
- if (p) {
164
- std::rethrow_exception(p);
165
- }
166
- } catch (const MyException2 &e) {
167
- // Translate this exception to a standard RuntimeError
168
- py::set_error(PyExc_RuntimeError, e.what());
169
- }
170
- });
171
-
172
- // register new translator for MyException4
173
- // which will catch it and delegate to the previously registered
174
- // translator for MyException by throwing a new exception
175
- py::register_exception_translator([](std::exception_ptr p) {
176
- try {
177
- if (p) {
178
- std::rethrow_exception(p);
179
- }
180
- } catch (const MyException4 &e) {
181
- throw MyException(e.what());
182
- }
183
- });
184
-
185
- // A simple exception translation:
186
- auto ex5 = py::register_exception<MyException5>(m, "MyException5");
187
- // A slightly more complicated one that declares MyException5_1 as a subclass of MyException5
188
- py::register_exception<MyException5_1>(m, "MyException5_1", ex5.ptr());
189
-
190
- // py::register_local_exception<LocalSimpleException>(m, "LocalSimpleException")
191
-
192
- py::register_local_exception_translator([](std::exception_ptr p) {
193
- try {
194
- if (p) {
195
- std::rethrow_exception(p);
196
- }
197
- } catch (const MyException6 &e) {
198
- py::set_error(PyExc_RuntimeError, e.what());
199
- }
200
- });
201
-
202
- m.def("throws1",
203
- []() { throw MyException("this error should go to py::exception<MyException>"); });
204
- m.def("throws1d", []() {
205
- throw MyExceptionUseDeprecatedOperatorCall(
206
- "this error should go to py::exception<MyExceptionUseDeprecatedOperatorCall>");
207
- });
208
- m.def("throws2",
209
- []() { throw MyException2("this error should go to a standard Python exception"); });
210
- m.def("throws3", []() { throw MyException3("this error cannot be translated"); });
211
- m.def("throws4", []() { throw MyException4("this error is rethrown"); });
212
- m.def("throws5",
213
- []() { throw MyException5("this is a helper-defined translated exception"); });
214
- m.def("throws5_1", []() { throw MyException5_1("MyException5 subclass"); });
215
- m.def("throws6", []() { throw MyException6("MyException6 only handled in this module"); });
216
- m.def("throws_logic_error", []() {
217
- throw std::logic_error("this error should fall through to the standard handler");
218
- });
219
- m.def("throws_overflow_error", []() { throw std::overflow_error(""); });
220
- m.def("throws_local_error", []() { throw LocalException("never caught"); });
221
- m.def("throws_local_simple_error", []() { throw LocalSimpleException("this mod"); });
222
- m.def("exception_matches", []() {
223
- py::dict foo;
224
- try {
225
- // Assign to a py::object to force read access of nonexistent dict entry
226
- py::object o = foo["bar"];
227
- } catch (py::error_already_set &ex) {
228
- if (!ex.matches(PyExc_KeyError)) {
229
- throw;
230
- }
231
- return true;
232
- }
233
- return false;
234
- });
235
- m.def("exception_matches_base", []() {
236
- py::dict foo;
237
- try {
238
- // Assign to a py::object to force read access of nonexistent dict entry
239
- py::object o = foo["bar"];
240
- } catch (py::error_already_set &ex) {
241
- if (!ex.matches(PyExc_Exception)) {
242
- throw;
243
- }
244
- return true;
245
- }
246
- return false;
247
- });
248
- m.def("modulenotfound_exception_matches_base", []() {
249
- try {
250
- // On Python >= 3.6, this raises a ModuleNotFoundError, a subclass of ImportError
251
- py::module_::import("nonexistent");
252
- } catch (py::error_already_set &ex) {
253
- if (!ex.matches(PyExc_ImportError)) {
254
- throw;
255
- }
256
- return true;
257
- }
258
- return false;
259
- });
260
-
261
- m.def("throw_already_set", [](bool err) {
262
- if (err) {
263
- py::set_error(PyExc_ValueError, "foo");
264
- }
265
- try {
266
- throw py::error_already_set();
267
- } catch (const std::runtime_error &e) {
268
- if ((err && e.what() != std::string("ValueError: foo"))
269
- || (!err
270
- && e.what()
271
- != std::string("Internal error: pybind11::error_already_set called "
272
- "while Python error indicator not set."))) {
273
- PyErr_Clear();
274
- throw std::runtime_error("error message mismatch");
275
- }
276
- }
277
- PyErr_Clear();
278
- if (err) {
279
- py::set_error(PyExc_ValueError, "foo");
280
- }
281
- throw py::error_already_set();
282
- });
283
-
284
- m.def("python_call_in_destructor", [](const py::dict &d) {
285
- bool retval = false;
286
- try {
287
- PythonCallInDestructor set_dict_in_destructor(d);
288
- py::set_error(PyExc_ValueError, "foo");
289
- throw py::error_already_set();
290
- } catch (const py::error_already_set &) {
291
- retval = true;
292
- }
293
- return retval;
294
- });
295
-
296
- m.def("python_alreadyset_in_destructor", [](const py::str &s) {
297
- PythonAlreadySetInDestructor alreadyset_in_destructor(s);
298
- return true;
299
- });
300
-
301
- // test_nested_throws
302
- m.def("try_catch",
303
- [m](const py::object &exc_type, const py::function &f, const py::args &args) {
304
- try {
305
- f(*args);
306
- } catch (py::error_already_set &ex) {
307
- if (ex.matches(exc_type)) {
308
- py::print(ex.what());
309
- } else {
310
- // Simply `throw;` also works and is better, but using `throw ex;`
311
- // here to cover that situation (as observed in the wild).
312
- throw ex; // Invokes the copy ctor.
313
- }
314
- }
315
- });
316
-
317
- // Test repr that cannot be displayed
318
- m.def("simple_bool_passthrough", [](bool x) { return x; });
319
-
320
- m.def("throw_should_be_translated_to_key_error", []() { throw shared_exception(); });
321
-
322
- m.def("raise_from", []() {
323
- py::set_error(PyExc_ValueError, "inner");
324
- py::raise_from(PyExc_ValueError, "outer");
325
- throw py::error_already_set();
326
- });
327
-
328
- m.def("raise_from_already_set", []() {
329
- try {
330
- py::set_error(PyExc_ValueError, "inner");
331
- throw py::error_already_set();
332
- } catch (py::error_already_set &e) {
333
- py::raise_from(e, PyExc_ValueError, "outer");
334
- throw py::error_already_set();
335
- }
336
- });
337
-
338
- m.def("throw_nested_exception", []() {
339
- try {
340
- throw std::runtime_error("Inner Exception");
341
- } catch (const std::runtime_error &) {
342
- std::throw_with_nested(std::runtime_error("Outer Exception"));
343
- }
344
- });
345
-
346
- m.def("error_already_set_what", [](const py::object &exc_type, const py::object &exc_value) {
347
- py::set_error(exc_type, exc_value);
348
- std::string what = py::error_already_set().what();
349
- bool py_err_set_after_what = (PyErr_Occurred() != nullptr);
350
- PyErr_Clear();
351
- return py::make_tuple(std::move(what), py_err_set_after_what);
352
- });
353
-
354
- m.def("test_cross_module_interleaved_error_already_set", []() {
355
- auto cm = py::module_::import("cross_module_interleaved_error_already_set");
356
- auto interleaved_error_already_set
357
- = reinterpret_cast<void (*)()>(PyLong_AsVoidPtr(cm.attr("funcaddr").ptr()));
358
- interleaved_error_already_set();
359
- });
360
-
361
- m.def("test_error_already_set_double_restore", [](bool dry_run) {
362
- py::set_error(PyExc_ValueError, "Random error.");
363
- py::error_already_set e;
364
- e.restore();
365
- PyErr_Clear();
366
- if (!dry_run) {
367
- e.restore();
368
- }
369
- });
370
-
371
- // https://github.com/pybind/pybind11/issues/4075
372
- m.def("test_pypy_oserror_normalization", []() {
373
- try {
374
- py::module_::import("io").attr("open")("this_filename_must_not_exist", "r");
375
- } catch (const py::error_already_set &e) {
376
- return py::str(e.what()); // str must be built before e goes out of scope.
377
- }
378
- return py::str("UNEXPECTED");
379
- });
380
-
381
- m.def("test_fn_cast_int", [](const py::function &fn) {
382
- // function returns None instead of int, should give a useful error message
383
- fn().cast<int>();
384
- });
385
-
386
- // m.def("pass_exception_void", [](const py::exception<void>&) {}); // Does not compile.
387
- m.def("return_exception_void", []() { return py::exception<void>(); });
388
- }
 
1
+ /*
2
+ tests/test_custom-exceptions.cpp -- exception translation
3
+
4
+ Copyright (c) 2016 Pim Schellart <P.Schellart@princeton.edu>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+ #include <pybind11/gil_safe_call_once.h>
10
+
11
+ #include "test_exceptions.h"
12
+
13
+ #include "local_bindings.h"
14
+ #include "pybind11_tests.h"
15
+
16
+ #include <exception>
17
+ #include <stdexcept>
18
+ #include <utility>
19
+
20
+ // A type that should be raised as an exception in Python
21
+ class MyException : public std::exception {
22
+ public:
23
+ explicit MyException(const char *m) : message{m} {}
24
+ const char *what() const noexcept override { return message.c_str(); }
25
+
26
+ private:
27
+ std::string message = "";
28
+ };
29
+
30
+ class MyExceptionUseDeprecatedOperatorCall : public MyException {
31
+ using MyException::MyException;
32
+ };
33
+
34
+ // A type that should be translated to a standard Python exception
35
+ class MyException2 : public std::exception {
36
+ public:
37
+ explicit MyException2(const char *m) : message{m} {}
38
+ const char *what() const noexcept override { return message.c_str(); }
39
+
40
+ private:
41
+ std::string message = "";
42
+ };
43
+
44
+ // A type that is not derived from std::exception (and is thus unknown)
45
+ class MyException3 {
46
+ public:
47
+ explicit MyException3(const char *m) : message{m} {}
48
+ virtual const char *what() const noexcept { return message.c_str(); }
49
+ // Rule of 5 BEGIN: to preempt compiler warnings.
50
+ MyException3(const MyException3 &) = default;
51
+ MyException3(MyException3 &&) = default;
52
+ MyException3 &operator=(const MyException3 &) = default;
53
+ MyException3 &operator=(MyException3 &&) = default;
54
+ virtual ~MyException3() = default;
55
+ // Rule of 5 END.
56
+ private:
57
+ std::string message = "";
58
+ };
59
+
60
+ // A type that should be translated to MyException
61
+ // and delegated to its exception translator
62
+ class MyException4 : public std::exception {
63
+ public:
64
+ explicit MyException4(const char *m) : message{m} {}
65
+ const char *what() const noexcept override { return message.c_str(); }
66
+
67
+ private:
68
+ std::string message = "";
69
+ };
70
+
71
+ // Like the above, but declared via the helper function
72
+ class MyException5 : public std::logic_error {
73
+ public:
74
+ explicit MyException5(const std::string &what) : std::logic_error(what) {}
75
+ };
76
+
77
+ // Inherits from MyException5
78
+ class MyException5_1 : public MyException5 {
79
+ using MyException5::MyException5;
80
+ };
81
+
82
+ // Exception that will be caught via the module local translator.
83
+ class MyException6 : public std::exception {
84
+ public:
85
+ explicit MyException6(const char *m) : message{m} {}
86
+ const char *what() const noexcept override { return message.c_str(); }
87
+
88
+ private:
89
+ std::string message = "";
90
+ };
91
+
92
+ struct PythonCallInDestructor {
93
+ explicit PythonCallInDestructor(const py::dict &d) : d(d) {}
94
+ ~PythonCallInDestructor() { d["good"] = true; }
95
+
96
+ py::dict d;
97
+ };
98
+
99
+ struct PythonAlreadySetInDestructor {
100
+ explicit PythonAlreadySetInDestructor(const py::str &s) : s(s) {}
101
+ ~PythonAlreadySetInDestructor() {
102
+ py::dict foo;
103
+ try {
104
+ // Assign to a py::object to force read access of nonexistent dict entry
105
+ py::object o = foo["bar"];
106
+ } catch (py::error_already_set &ex) {
107
+ ex.discard_as_unraisable(s);
108
+ }
109
+ }
110
+
111
+ py::str s;
112
+ };
113
+
114
+ TEST_SUBMODULE(exceptions, m) {
115
+ m.def("throw_std_exception",
116
+ []() { throw std::runtime_error("This exception was intentionally thrown."); });
117
+
118
+ // PLEASE KEEP IN SYNC with docs/advanced/exceptions.rst
119
+ PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object> ex_storage;
120
+ ex_storage.call_once_and_store_result(
121
+ [&]() { return py::exception<MyException>(m, "MyException"); });
122
+ py::register_exception_translator([](std::exception_ptr p) {
123
+ try {
124
+ if (p) {
125
+ std::rethrow_exception(p);
126
+ }
127
+ } catch (const MyException &e) {
128
+ // Set MyException as the active python error
129
+ py::set_error(ex_storage.get_stored(), e.what());
130
+ }
131
+ });
132
+
133
+ // Same as above, but using the deprecated `py::exception<>::operator()`
134
+ // We want to be sure it still works, until it's removed.
135
+ static const auto *const exd = new py::exception<MyExceptionUseDeprecatedOperatorCall>(
136
+ m, "MyExceptionUseDeprecatedOperatorCall");
137
+ py::register_exception_translator([](std::exception_ptr p) {
138
+ try {
139
+ if (p) {
140
+ std::rethrow_exception(p);
141
+ }
142
+ } catch (const MyExceptionUseDeprecatedOperatorCall &e) {
143
+ #if defined(__INTEL_COMPILER) || defined(__NVCOMPILER)
144
+ // It is not worth the trouble dealing with warning suppressions for these compilers.
145
+ // Falling back to the recommended approach to keep the test code simple.
146
+ py::set_error(*exd, e.what());
147
+ #else
148
+ PYBIND11_WARNING_PUSH
149
+ PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
150
+ PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
151
+ PYBIND11_WARNING_DISABLE_MSVC(4996)
152
+ (*exd)(e.what());
153
+ PYBIND11_WARNING_POP
154
+ #endif
155
+ }
156
+ });
157
+
158
+ // register new translator for MyException2
159
+ // no need to store anything here because this type will
160
+ // never by visible from Python
161
+ py::register_exception_translator([](std::exception_ptr p) {
162
+ try {
163
+ if (p) {
164
+ std::rethrow_exception(p);
165
+ }
166
+ } catch (const MyException2 &e) {
167
+ // Translate this exception to a standard RuntimeError
168
+ py::set_error(PyExc_RuntimeError, e.what());
169
+ }
170
+ });
171
+
172
+ // register new translator for MyException4
173
+ // which will catch it and delegate to the previously registered
174
+ // translator for MyException by throwing a new exception
175
+ py::register_exception_translator([](std::exception_ptr p) {
176
+ try {
177
+ if (p) {
178
+ std::rethrow_exception(p);
179
+ }
180
+ } catch (const MyException4 &e) {
181
+ throw MyException(e.what());
182
+ }
183
+ });
184
+
185
+ // A simple exception translation:
186
+ auto ex5 = py::register_exception<MyException5>(m, "MyException5");
187
+ // A slightly more complicated one that declares MyException5_1 as a subclass of MyException5
188
+ py::register_exception<MyException5_1>(m, "MyException5_1", ex5.ptr());
189
+
190
+ // py::register_local_exception<LocalSimpleException>(m, "LocalSimpleException")
191
+
192
+ py::register_local_exception_translator([](std::exception_ptr p) {
193
+ try {
194
+ if (p) {
195
+ std::rethrow_exception(p);
196
+ }
197
+ } catch (const MyException6 &e) {
198
+ py::set_error(PyExc_RuntimeError, e.what());
199
+ }
200
+ });
201
+
202
+ m.def("throws1",
203
+ []() { throw MyException("this error should go to py::exception<MyException>"); });
204
+ m.def("throws1d", []() {
205
+ throw MyExceptionUseDeprecatedOperatorCall(
206
+ "this error should go to py::exception<MyExceptionUseDeprecatedOperatorCall>");
207
+ });
208
+ m.def("throws2",
209
+ []() { throw MyException2("this error should go to a standard Python exception"); });
210
+ m.def("throws3", []() { throw MyException3("this error cannot be translated"); });
211
+ m.def("throws4", []() { throw MyException4("this error is rethrown"); });
212
+ m.def("throws5",
213
+ []() { throw MyException5("this is a helper-defined translated exception"); });
214
+ m.def("throws5_1", []() { throw MyException5_1("MyException5 subclass"); });
215
+ m.def("throws6", []() { throw MyException6("MyException6 only handled in this module"); });
216
+ m.def("throws_logic_error", []() {
217
+ throw std::logic_error("this error should fall through to the standard handler");
218
+ });
219
+ m.def("throws_overflow_error", []() { throw std::overflow_error(""); });
220
+ m.def("throws_local_error", []() { throw LocalException("never caught"); });
221
+ m.def("throws_local_simple_error", []() { throw LocalSimpleException("this mod"); });
222
+ m.def("exception_matches", []() {
223
+ py::dict foo;
224
+ try {
225
+ // Assign to a py::object to force read access of nonexistent dict entry
226
+ py::object o = foo["bar"];
227
+ } catch (py::error_already_set &ex) {
228
+ if (!ex.matches(PyExc_KeyError)) {
229
+ throw;
230
+ }
231
+ return true;
232
+ }
233
+ return false;
234
+ });
235
+ m.def("exception_matches_base", []() {
236
+ py::dict foo;
237
+ try {
238
+ // Assign to a py::object to force read access of nonexistent dict entry
239
+ py::object o = foo["bar"];
240
+ } catch (py::error_already_set &ex) {
241
+ if (!ex.matches(PyExc_Exception)) {
242
+ throw;
243
+ }
244
+ return true;
245
+ }
246
+ return false;
247
+ });
248
+ m.def("modulenotfound_exception_matches_base", []() {
249
+ try {
250
+ // On Python >= 3.6, this raises a ModuleNotFoundError, a subclass of ImportError
251
+ py::module_::import("nonexistent");
252
+ } catch (py::error_already_set &ex) {
253
+ if (!ex.matches(PyExc_ImportError)) {
254
+ throw;
255
+ }
256
+ return true;
257
+ }
258
+ return false;
259
+ });
260
+
261
+ m.def("throw_already_set", [](bool err) {
262
+ if (err) {
263
+ py::set_error(PyExc_ValueError, "foo");
264
+ }
265
+ try {
266
+ throw py::error_already_set();
267
+ } catch (const std::runtime_error &e) {
268
+ if ((err && e.what() != std::string("ValueError: foo"))
269
+ || (!err
270
+ && e.what()
271
+ != std::string("Internal error: pybind11::error_already_set called "
272
+ "while Python error indicator not set."))) {
273
+ PyErr_Clear();
274
+ throw std::runtime_error("error message mismatch");
275
+ }
276
+ }
277
+ PyErr_Clear();
278
+ if (err) {
279
+ py::set_error(PyExc_ValueError, "foo");
280
+ }
281
+ throw py::error_already_set();
282
+ });
283
+
284
+ m.def("python_call_in_destructor", [](const py::dict &d) {
285
+ bool retval = false;
286
+ try {
287
+ PythonCallInDestructor set_dict_in_destructor(d);
288
+ py::set_error(PyExc_ValueError, "foo");
289
+ throw py::error_already_set();
290
+ } catch (const py::error_already_set &) {
291
+ retval = true;
292
+ }
293
+ return retval;
294
+ });
295
+
296
+ m.def("python_alreadyset_in_destructor", [](const py::str &s) {
297
+ PythonAlreadySetInDestructor alreadyset_in_destructor(s);
298
+ return true;
299
+ });
300
+
301
+ // test_nested_throws
302
+ m.def("try_catch",
303
+ [m](const py::object &exc_type, const py::function &f, const py::args &args) {
304
+ try {
305
+ f(*args);
306
+ } catch (py::error_already_set &ex) {
307
+ if (ex.matches(exc_type)) {
308
+ py::print(ex.what());
309
+ } else {
310
+ // Simply `throw;` also works and is better, but using `throw ex;`
311
+ // here to cover that situation (as observed in the wild).
312
+ throw ex; // Invokes the copy ctor.
313
+ }
314
+ }
315
+ });
316
+
317
+ // Test repr that cannot be displayed
318
+ m.def("simple_bool_passthrough", [](bool x) { return x; });
319
+
320
+ m.def("throw_should_be_translated_to_key_error", []() { throw shared_exception(); });
321
+
322
+ m.def("raise_from", []() {
323
+ py::set_error(PyExc_ValueError, "inner");
324
+ py::raise_from(PyExc_ValueError, "outer");
325
+ throw py::error_already_set();
326
+ });
327
+
328
+ m.def("raise_from_already_set", []() {
329
+ try {
330
+ py::set_error(PyExc_ValueError, "inner");
331
+ throw py::error_already_set();
332
+ } catch (py::error_already_set &e) {
333
+ py::raise_from(e, PyExc_ValueError, "outer");
334
+ throw py::error_already_set();
335
+ }
336
+ });
337
+
338
+ m.def("throw_nested_exception", []() {
339
+ try {
340
+ throw std::runtime_error("Inner Exception");
341
+ } catch (const std::runtime_error &) {
342
+ std::throw_with_nested(std::runtime_error("Outer Exception"));
343
+ }
344
+ });
345
+
346
+ m.def("error_already_set_what", [](const py::object &exc_type, const py::object &exc_value) {
347
+ py::set_error(exc_type, exc_value);
348
+ std::string what = py::error_already_set().what();
349
+ bool py_err_set_after_what = (PyErr_Occurred() != nullptr);
350
+ PyErr_Clear();
351
+ return py::make_tuple(std::move(what), py_err_set_after_what);
352
+ });
353
+
354
+ m.def("test_cross_module_interleaved_error_already_set", []() {
355
+ auto cm = py::module_::import("cross_module_interleaved_error_already_set");
356
+ auto interleaved_error_already_set
357
+ = reinterpret_cast<void (*)()>(PyLong_AsVoidPtr(cm.attr("funcaddr").ptr()));
358
+ interleaved_error_already_set();
359
+ });
360
+
361
+ m.def("test_error_already_set_double_restore", [](bool dry_run) {
362
+ py::set_error(PyExc_ValueError, "Random error.");
363
+ py::error_already_set e;
364
+ e.restore();
365
+ PyErr_Clear();
366
+ if (!dry_run) {
367
+ e.restore();
368
+ }
369
+ });
370
+
371
+ // https://github.com/pybind/pybind11/issues/4075
372
+ m.def("test_pypy_oserror_normalization", []() {
373
+ try {
374
+ py::module_::import("io").attr("open")("this_filename_must_not_exist", "r");
375
+ } catch (const py::error_already_set &e) {
376
+ return py::str(e.what()); // str must be built before e goes out of scope.
377
+ }
378
+ return py::str("UNEXPECTED");
379
+ });
380
+
381
+ m.def("test_fn_cast_int", [](const py::function &fn) {
382
+ // function returns None instead of int, should give a useful error message
383
+ fn().cast<int>();
384
+ });
385
+
386
+ // m.def("pass_exception_void", [](const py::exception<void>&) {}); // Does not compile.
387
+ m.def("return_exception_void", []() { return py::exception<void>(); });
388
+ }
third_party/CityFlow/extern/pybind11/tests/test_exceptions.h CHANGED
@@ -1,13 +1,13 @@
1
- #pragma once
2
- #include "pybind11_tests.h"
3
-
4
- #include <stdexcept>
5
-
6
- // shared exceptions for cross_module_tests
7
-
8
- class PYBIND11_EXPORT_EXCEPTION shared_exception : public pybind11::builtin_exception {
9
- public:
10
- using builtin_exception::builtin_exception;
11
- explicit shared_exception() : shared_exception("") {}
12
- void set_error() const override { py::set_error(PyExc_RuntimeError, what()); }
13
- };
 
1
+ #pragma once
2
+ #include "pybind11_tests.h"
3
+
4
+ #include <stdexcept>
5
+
6
+ // shared exceptions for cross_module_tests
7
+
8
+ class PYBIND11_EXPORT_EXCEPTION shared_exception : public pybind11::builtin_exception {
9
+ public:
10
+ using builtin_exception::builtin_exception;
11
+ explicit shared_exception() : shared_exception("") {}
12
+ void set_error() const override { py::set_error(PyExc_RuntimeError, what()); }
13
+ };
third_party/CityFlow/extern/pybind11/tests/test_exceptions.py CHANGED
@@ -1,432 +1,432 @@
1
- import sys
2
-
3
- import pytest
4
-
5
- import env
6
- import pybind11_cross_module_tests as cm
7
- import pybind11_tests
8
- from pybind11_tests import exceptions as m
9
-
10
-
11
- def test_std_exception(msg):
12
- with pytest.raises(RuntimeError) as excinfo:
13
- m.throw_std_exception()
14
- assert msg(excinfo.value) == "This exception was intentionally thrown."
15
-
16
-
17
- def test_error_already_set(msg):
18
- with pytest.raises(RuntimeError) as excinfo:
19
- m.throw_already_set(False)
20
- assert (
21
- msg(excinfo.value)
22
- == "Internal error: pybind11::error_already_set called while Python error indicator not set."
23
- )
24
-
25
- with pytest.raises(ValueError) as excinfo:
26
- m.throw_already_set(True)
27
- assert msg(excinfo.value) == "foo"
28
-
29
-
30
- def test_raise_from(msg):
31
- with pytest.raises(ValueError) as excinfo:
32
- m.raise_from()
33
- assert msg(excinfo.value) == "outer"
34
- assert msg(excinfo.value.__cause__) == "inner"
35
-
36
-
37
- def test_raise_from_already_set(msg):
38
- with pytest.raises(ValueError) as excinfo:
39
- m.raise_from_already_set()
40
- assert msg(excinfo.value) == "outer"
41
- assert msg(excinfo.value.__cause__) == "inner"
42
-
43
-
44
- def test_cross_module_exceptions(msg):
45
- with pytest.raises(RuntimeError) as excinfo:
46
- cm.raise_runtime_error()
47
- assert str(excinfo.value) == "My runtime error"
48
-
49
- with pytest.raises(ValueError) as excinfo:
50
- cm.raise_value_error()
51
- assert str(excinfo.value) == "My value error"
52
-
53
- with pytest.raises(ValueError) as excinfo:
54
- cm.throw_pybind_value_error()
55
- assert str(excinfo.value) == "pybind11 value error"
56
-
57
- with pytest.raises(TypeError) as excinfo:
58
- cm.throw_pybind_type_error()
59
- assert str(excinfo.value) == "pybind11 type error"
60
-
61
- with pytest.raises(StopIteration) as excinfo:
62
- cm.throw_stop_iteration()
63
-
64
- with pytest.raises(cm.LocalSimpleException) as excinfo:
65
- cm.throw_local_simple_error()
66
- assert msg(excinfo.value) == "external mod"
67
-
68
- with pytest.raises(KeyError) as excinfo:
69
- cm.throw_local_error()
70
- # KeyError is a repr of the key, so it has an extra set of quotes
71
- assert str(excinfo.value) == "'just local'"
72
-
73
-
74
- # TODO: FIXME
75
- @pytest.mark.xfail(
76
- "env.MACOS and (env.PYPY or pybind11_tests.compiler_info.startswith('Homebrew Clang'))",
77
- raises=RuntimeError,
78
- reason="See Issue #2847, PR #2999, PR #4324",
79
- )
80
- def test_cross_module_exception_translator():
81
- with pytest.raises(KeyError):
82
- # translator registered in cross_module_tests
83
- m.throw_should_be_translated_to_key_error()
84
-
85
-
86
- def test_python_call_in_catch():
87
- d = {}
88
- assert m.python_call_in_destructor(d) is True
89
- assert d["good"] is True
90
-
91
-
92
- def ignore_pytest_unraisable_warning(f):
93
- unraisable = "PytestUnraisableExceptionWarning"
94
- if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6
95
- dec = pytest.mark.filterwarnings(f"ignore::pytest.{unraisable}")
96
- return dec(f)
97
- return f
98
-
99
-
100
- # TODO: find out why this fails on PyPy, https://foss.heptapod.net/pypy/pypy/-/issues/3583
101
- @pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False)
102
- @ignore_pytest_unraisable_warning
103
- def test_python_alreadyset_in_destructor(monkeypatch, capsys):
104
- hooked = False
105
- triggered = False
106
-
107
- if hasattr(sys, "unraisablehook"): # Python 3.8+
108
- hooked = True
109
- # Don't take `sys.unraisablehook`, as that's overwritten by pytest
110
- default_hook = sys.__unraisablehook__
111
-
112
- def hook(unraisable_hook_args):
113
- exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args
114
- if obj == "already_set demo":
115
- nonlocal triggered
116
- triggered = True
117
- default_hook(unraisable_hook_args)
118
- return
119
-
120
- # Use monkeypatch so pytest can apply and remove the patch as appropriate
121
- monkeypatch.setattr(sys, "unraisablehook", hook)
122
-
123
- assert m.python_alreadyset_in_destructor("already_set demo") is True
124
- if hooked:
125
- assert triggered is True
126
-
127
- _, captured_stderr = capsys.readouterr()
128
- assert captured_stderr.startswith("Exception ignored in: 'already_set demo'")
129
- assert captured_stderr.rstrip().endswith("KeyError: 'bar'")
130
-
131
-
132
- def test_exception_matches():
133
- assert m.exception_matches()
134
- assert m.exception_matches_base()
135
- assert m.modulenotfound_exception_matches_base()
136
-
137
-
138
- def test_custom(msg):
139
- # Can we catch a MyException?
140
- with pytest.raises(m.MyException) as excinfo:
141
- m.throws1()
142
- assert msg(excinfo.value) == "this error should go to py::exception<MyException>"
143
-
144
- # Can we catch a MyExceptionUseDeprecatedOperatorCall?
145
- with pytest.raises(m.MyExceptionUseDeprecatedOperatorCall) as excinfo:
146
- m.throws1d()
147
- assert (
148
- msg(excinfo.value)
149
- == "this error should go to py::exception<MyExceptionUseDeprecatedOperatorCall>"
150
- )
151
-
152
- # Can we translate to standard Python exceptions?
153
- with pytest.raises(RuntimeError) as excinfo:
154
- m.throws2()
155
- assert msg(excinfo.value) == "this error should go to a standard Python exception"
156
-
157
- # Can we handle unknown exceptions?
158
- with pytest.raises(RuntimeError) as excinfo:
159
- m.throws3()
160
- assert msg(excinfo.value) == "Caught an unknown exception!"
161
-
162
- # Can we delegate to another handler by rethrowing?
163
- with pytest.raises(m.MyException) as excinfo:
164
- m.throws4()
165
- assert msg(excinfo.value) == "this error is rethrown"
166
-
167
- # Can we fall-through to the default handler?
168
- with pytest.raises(RuntimeError) as excinfo:
169
- m.throws_logic_error()
170
- assert (
171
- msg(excinfo.value) == "this error should fall through to the standard handler"
172
- )
173
-
174
- # OverFlow error translation.
175
- with pytest.raises(OverflowError) as excinfo:
176
- m.throws_overflow_error()
177
-
178
- # Can we handle a helper-declared exception?
179
- with pytest.raises(m.MyException5) as excinfo:
180
- m.throws5()
181
- assert msg(excinfo.value) == "this is a helper-defined translated exception"
182
-
183
- # Exception subclassing:
184
- with pytest.raises(m.MyException5) as excinfo:
185
- m.throws5_1()
186
- assert msg(excinfo.value) == "MyException5 subclass"
187
- assert isinstance(excinfo.value, m.MyException5_1)
188
-
189
- with pytest.raises(m.MyException5_1) as excinfo:
190
- m.throws5_1()
191
- assert msg(excinfo.value) == "MyException5 subclass"
192
-
193
- with pytest.raises(m.MyException5) as excinfo: # noqa: PT012
194
- try:
195
- m.throws5()
196
- except m.MyException5_1 as err:
197
- raise RuntimeError("Exception error: caught child from parent") from err
198
- assert msg(excinfo.value) == "this is a helper-defined translated exception"
199
-
200
-
201
- def test_nested_throws(capture):
202
- """Tests nested (e.g. C++ -> Python -> C++) exception handling"""
203
-
204
- def throw_myex():
205
- raise m.MyException("nested error")
206
-
207
- def throw_myex5():
208
- raise m.MyException5("nested error 5")
209
-
210
- # In the comments below, the exception is caught in the first step, thrown in the last step
211
-
212
- # C++ -> Python
213
- with capture:
214
- m.try_catch(m.MyException5, throw_myex5)
215
- assert str(capture).startswith("MyException5: nested error 5")
216
-
217
- # Python -> C++ -> Python
218
- with pytest.raises(m.MyException) as excinfo:
219
- m.try_catch(m.MyException5, throw_myex)
220
- assert str(excinfo.value) == "nested error"
221
-
222
- def pycatch(exctype, f, *args): # noqa: ARG001
223
- try:
224
- f(*args)
225
- except m.MyException as e:
226
- print(e)
227
-
228
- # C++ -> Python -> C++ -> Python
229
- with capture:
230
- m.try_catch(
231
- m.MyException5,
232
- pycatch,
233
- m.MyException,
234
- m.try_catch,
235
- m.MyException,
236
- throw_myex5,
237
- )
238
- assert str(capture).startswith("MyException5: nested error 5")
239
-
240
- # C++ -> Python -> C++
241
- with capture:
242
- m.try_catch(m.MyException, pycatch, m.MyException5, m.throws4)
243
- assert capture == "this error is rethrown"
244
-
245
- # Python -> C++ -> Python -> C++
246
- with pytest.raises(m.MyException5) as excinfo:
247
- m.try_catch(m.MyException, pycatch, m.MyException, m.throws5)
248
- assert str(excinfo.value) == "this is a helper-defined translated exception"
249
-
250
-
251
- # TODO: Investigate this crash, see pybind/pybind11#5062 for background
252
- @pytest.mark.skipif(
253
- sys.platform.startswith("win32") and "Clang" in pybind11_tests.compiler_info,
254
- reason="Started segfaulting February 2024",
255
- )
256
- def test_throw_nested_exception():
257
- with pytest.raises(RuntimeError) as excinfo:
258
- m.throw_nested_exception()
259
- assert str(excinfo.value) == "Outer Exception"
260
- assert str(excinfo.value.__cause__) == "Inner Exception"
261
-
262
-
263
- # This can often happen if you wrap a pybind11 class in a Python wrapper
264
- def test_invalid_repr():
265
- class MyRepr:
266
- def __repr__(self):
267
- raise AttributeError("Example error")
268
-
269
- with pytest.raises(TypeError):
270
- m.simple_bool_passthrough(MyRepr())
271
-
272
-
273
- def test_local_translator(msg):
274
- """Tests that a local translator works and that the local translator from
275
- the cross module is not applied"""
276
- with pytest.raises(RuntimeError) as excinfo:
277
- m.throws6()
278
- assert msg(excinfo.value) == "MyException6 only handled in this module"
279
-
280
- with pytest.raises(RuntimeError) as excinfo:
281
- m.throws_local_error()
282
- assert not isinstance(excinfo.value, KeyError)
283
- assert msg(excinfo.value) == "never caught"
284
-
285
- with pytest.raises(Exception) as excinfo:
286
- m.throws_local_simple_error()
287
- assert not isinstance(excinfo.value, cm.LocalSimpleException)
288
- assert msg(excinfo.value) == "this mod"
289
-
290
-
291
- def test_error_already_set_message_with_unicode_surrogate(): # Issue #4288
292
- assert m.error_already_set_what(RuntimeError, "\ud927") == (
293
- "RuntimeError: \\ud927",
294
- False,
295
- )
296
-
297
-
298
- def test_error_already_set_message_with_malformed_utf8():
299
- assert m.error_already_set_what(RuntimeError, b"\x80") == (
300
- "RuntimeError: b'\\x80'",
301
- False,
302
- )
303
-
304
-
305
- class FlakyException(Exception):
306
- def __init__(self, failure_point):
307
- if failure_point == "failure_point_init":
308
- raise ValueError("triggered_failure_point_init")
309
- self.failure_point = failure_point
310
-
311
- def __str__(self):
312
- if self.failure_point == "failure_point_str":
313
- raise ValueError("triggered_failure_point_str")
314
- return "FlakyException.__str__"
315
-
316
-
317
- @pytest.mark.parametrize(
318
- ("exc_type", "exc_value", "expected_what"),
319
- [
320
- (ValueError, "plain_str", "ValueError: plain_str"),
321
- (ValueError, ("tuple_elem",), "ValueError: tuple_elem"),
322
- (FlakyException, ("happy",), "FlakyException: FlakyException.__str__"),
323
- ],
324
- )
325
- def test_error_already_set_what_with_happy_exceptions(
326
- exc_type, exc_value, expected_what
327
- ):
328
- what, py_err_set_after_what = m.error_already_set_what(exc_type, exc_value)
329
- assert not py_err_set_after_what
330
- assert what == expected_what
331
-
332
-
333
- def _test_flaky_exception_failure_point_init_before_py_3_12():
334
- with pytest.raises(RuntimeError) as excinfo:
335
- m.error_already_set_what(FlakyException, ("failure_point_init",))
336
- lines = str(excinfo.value).splitlines()
337
- # PyErr_NormalizeException replaces the original FlakyException with ValueError:
338
- assert lines[:3] == [
339
- "pybind11::error_already_set: MISMATCH of original and normalized active exception types:"
340
- " ORIGINAL FlakyException REPLACED BY ValueError: triggered_failure_point_init",
341
- "",
342
- "At:",
343
- ]
344
- # Checking the first two lines of the traceback as formatted in error_string():
345
- assert "test_exceptions.py(" in lines[3]
346
- assert lines[3].endswith("): __init__")
347
- assert lines[4].endswith(
348
- "): _test_flaky_exception_failure_point_init_before_py_3_12"
349
- )
350
-
351
-
352
- def _test_flaky_exception_failure_point_init_py_3_12():
353
- # Behavior change in Python 3.12: https://github.com/python/cpython/issues/102594
354
- what, py_err_set_after_what = m.error_already_set_what(
355
- FlakyException, ("failure_point_init",)
356
- )
357
- assert not py_err_set_after_what
358
- lines = what.splitlines()
359
- assert lines[0].endswith("ValueError[WITH __notes__]: triggered_failure_point_init")
360
- assert lines[1] == "__notes__ (len=1):"
361
- assert "Normalization failed:" in lines[2]
362
- assert "FlakyException" in lines[2]
363
-
364
-
365
- @pytest.mark.skipif(
366
- "env.PYPY and sys.version_info[:2] < (3, 12)",
367
- reason="PyErr_NormalizeException Segmentation fault",
368
- )
369
- def test_flaky_exception_failure_point_init():
370
- if sys.version_info[:2] < (3, 12):
371
- _test_flaky_exception_failure_point_init_before_py_3_12()
372
- else:
373
- _test_flaky_exception_failure_point_init_py_3_12()
374
-
375
-
376
- def test_flaky_exception_failure_point_str():
377
- what, py_err_set_after_what = m.error_already_set_what(
378
- FlakyException, ("failure_point_str",)
379
- )
380
- assert not py_err_set_after_what
381
- lines = what.splitlines()
382
- n = 3 if env.PYPY and len(lines) == 3 else 5
383
- assert (
384
- lines[:n]
385
- == [
386
- "FlakyException: <MESSAGE UNAVAILABLE DUE TO ANOTHER EXCEPTION>",
387
- "",
388
- "MESSAGE UNAVAILABLE DUE TO EXCEPTION: ValueError: triggered_failure_point_str",
389
- "",
390
- "At:",
391
- ][:n]
392
- )
393
-
394
-
395
- def test_cross_module_interleaved_error_already_set():
396
- with pytest.raises(RuntimeError) as excinfo:
397
- m.test_cross_module_interleaved_error_already_set()
398
- assert str(excinfo.value) in (
399
- "2nd error.", # Almost all platforms.
400
- "RuntimeError: 2nd error.", # Some PyPy builds (seen under macOS).
401
- )
402
-
403
-
404
- def test_error_already_set_double_restore():
405
- m.test_error_already_set_double_restore(True) # dry_run
406
- with pytest.raises(RuntimeError) as excinfo:
407
- m.test_error_already_set_double_restore(False)
408
- assert str(excinfo.value) == (
409
- "Internal error: pybind11::detail::error_fetch_and_normalize::restore()"
410
- " called a second time. ORIGINAL ERROR: ValueError: Random error."
411
- )
412
-
413
-
414
- def test_pypy_oserror_normalization():
415
- # https://github.com/pybind/pybind11/issues/4075
416
- what = m.test_pypy_oserror_normalization()
417
- assert "this_filename_must_not_exist" in what
418
-
419
-
420
- def test_fn_cast_int_exception():
421
- with pytest.raises(RuntimeError) as excinfo:
422
- m.test_fn_cast_int(lambda: None)
423
-
424
- assert str(excinfo.value).startswith(
425
- "Unable to cast Python instance of type <class 'NoneType'> to C++ type"
426
- )
427
-
428
-
429
- def test_return_exception_void():
430
- with pytest.raises(TypeError) as excinfo:
431
- m.return_exception_void()
432
- assert "Exception" in str(excinfo.value)
 
1
+ import sys
2
+
3
+ import pytest
4
+
5
+ import env
6
+ import pybind11_cross_module_tests as cm
7
+ import pybind11_tests
8
+ from pybind11_tests import exceptions as m
9
+
10
+
11
+ def test_std_exception(msg):
12
+ with pytest.raises(RuntimeError) as excinfo:
13
+ m.throw_std_exception()
14
+ assert msg(excinfo.value) == "This exception was intentionally thrown."
15
+
16
+
17
+ def test_error_already_set(msg):
18
+ with pytest.raises(RuntimeError) as excinfo:
19
+ m.throw_already_set(False)
20
+ assert (
21
+ msg(excinfo.value)
22
+ == "Internal error: pybind11::error_already_set called while Python error indicator not set."
23
+ )
24
+
25
+ with pytest.raises(ValueError) as excinfo:
26
+ m.throw_already_set(True)
27
+ assert msg(excinfo.value) == "foo"
28
+
29
+
30
+ def test_raise_from(msg):
31
+ with pytest.raises(ValueError) as excinfo:
32
+ m.raise_from()
33
+ assert msg(excinfo.value) == "outer"
34
+ assert msg(excinfo.value.__cause__) == "inner"
35
+
36
+
37
+ def test_raise_from_already_set(msg):
38
+ with pytest.raises(ValueError) as excinfo:
39
+ m.raise_from_already_set()
40
+ assert msg(excinfo.value) == "outer"
41
+ assert msg(excinfo.value.__cause__) == "inner"
42
+
43
+
44
+ def test_cross_module_exceptions(msg):
45
+ with pytest.raises(RuntimeError) as excinfo:
46
+ cm.raise_runtime_error()
47
+ assert str(excinfo.value) == "My runtime error"
48
+
49
+ with pytest.raises(ValueError) as excinfo:
50
+ cm.raise_value_error()
51
+ assert str(excinfo.value) == "My value error"
52
+
53
+ with pytest.raises(ValueError) as excinfo:
54
+ cm.throw_pybind_value_error()
55
+ assert str(excinfo.value) == "pybind11 value error"
56
+
57
+ with pytest.raises(TypeError) as excinfo:
58
+ cm.throw_pybind_type_error()
59
+ assert str(excinfo.value) == "pybind11 type error"
60
+
61
+ with pytest.raises(StopIteration) as excinfo:
62
+ cm.throw_stop_iteration()
63
+
64
+ with pytest.raises(cm.LocalSimpleException) as excinfo:
65
+ cm.throw_local_simple_error()
66
+ assert msg(excinfo.value) == "external mod"
67
+
68
+ with pytest.raises(KeyError) as excinfo:
69
+ cm.throw_local_error()
70
+ # KeyError is a repr of the key, so it has an extra set of quotes
71
+ assert str(excinfo.value) == "'just local'"
72
+
73
+
74
+ # TODO: FIXME
75
+ @pytest.mark.xfail(
76
+ "env.MACOS and (env.PYPY or pybind11_tests.compiler_info.startswith('Homebrew Clang'))",
77
+ raises=RuntimeError,
78
+ reason="See Issue #2847, PR #2999, PR #4324",
79
+ )
80
+ def test_cross_module_exception_translator():
81
+ with pytest.raises(KeyError):
82
+ # translator registered in cross_module_tests
83
+ m.throw_should_be_translated_to_key_error()
84
+
85
+
86
+ def test_python_call_in_catch():
87
+ d = {}
88
+ assert m.python_call_in_destructor(d) is True
89
+ assert d["good"] is True
90
+
91
+
92
+ def ignore_pytest_unraisable_warning(f):
93
+ unraisable = "PytestUnraisableExceptionWarning"
94
+ if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6
95
+ dec = pytest.mark.filterwarnings(f"ignore::pytest.{unraisable}")
96
+ return dec(f)
97
+ return f
98
+
99
+
100
+ # TODO: find out why this fails on PyPy, https://foss.heptapod.net/pypy/pypy/-/issues/3583
101
+ @pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False)
102
+ @ignore_pytest_unraisable_warning
103
+ def test_python_alreadyset_in_destructor(monkeypatch, capsys):
104
+ hooked = False
105
+ triggered = False
106
+
107
+ if hasattr(sys, "unraisablehook"): # Python 3.8+
108
+ hooked = True
109
+ # Don't take `sys.unraisablehook`, as that's overwritten by pytest
110
+ default_hook = sys.__unraisablehook__
111
+
112
+ def hook(unraisable_hook_args):
113
+ exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args
114
+ if obj == "already_set demo":
115
+ nonlocal triggered
116
+ triggered = True
117
+ default_hook(unraisable_hook_args)
118
+ return
119
+
120
+ # Use monkeypatch so pytest can apply and remove the patch as appropriate
121
+ monkeypatch.setattr(sys, "unraisablehook", hook)
122
+
123
+ assert m.python_alreadyset_in_destructor("already_set demo") is True
124
+ if hooked:
125
+ assert triggered is True
126
+
127
+ _, captured_stderr = capsys.readouterr()
128
+ assert captured_stderr.startswith("Exception ignored in: 'already_set demo'")
129
+ assert captured_stderr.rstrip().endswith("KeyError: 'bar'")
130
+
131
+
132
+ def test_exception_matches():
133
+ assert m.exception_matches()
134
+ assert m.exception_matches_base()
135
+ assert m.modulenotfound_exception_matches_base()
136
+
137
+
138
+ def test_custom(msg):
139
+ # Can we catch a MyException?
140
+ with pytest.raises(m.MyException) as excinfo:
141
+ m.throws1()
142
+ assert msg(excinfo.value) == "this error should go to py::exception<MyException>"
143
+
144
+ # Can we catch a MyExceptionUseDeprecatedOperatorCall?
145
+ with pytest.raises(m.MyExceptionUseDeprecatedOperatorCall) as excinfo:
146
+ m.throws1d()
147
+ assert (
148
+ msg(excinfo.value)
149
+ == "this error should go to py::exception<MyExceptionUseDeprecatedOperatorCall>"
150
+ )
151
+
152
+ # Can we translate to standard Python exceptions?
153
+ with pytest.raises(RuntimeError) as excinfo:
154
+ m.throws2()
155
+ assert msg(excinfo.value) == "this error should go to a standard Python exception"
156
+
157
+ # Can we handle unknown exceptions?
158
+ with pytest.raises(RuntimeError) as excinfo:
159
+ m.throws3()
160
+ assert msg(excinfo.value) == "Caught an unknown exception!"
161
+
162
+ # Can we delegate to another handler by rethrowing?
163
+ with pytest.raises(m.MyException) as excinfo:
164
+ m.throws4()
165
+ assert msg(excinfo.value) == "this error is rethrown"
166
+
167
+ # Can we fall-through to the default handler?
168
+ with pytest.raises(RuntimeError) as excinfo:
169
+ m.throws_logic_error()
170
+ assert (
171
+ msg(excinfo.value) == "this error should fall through to the standard handler"
172
+ )
173
+
174
+ # OverFlow error translation.
175
+ with pytest.raises(OverflowError) as excinfo:
176
+ m.throws_overflow_error()
177
+
178
+ # Can we handle a helper-declared exception?
179
+ with pytest.raises(m.MyException5) as excinfo:
180
+ m.throws5()
181
+ assert msg(excinfo.value) == "this is a helper-defined translated exception"
182
+
183
+ # Exception subclassing:
184
+ with pytest.raises(m.MyException5) as excinfo:
185
+ m.throws5_1()
186
+ assert msg(excinfo.value) == "MyException5 subclass"
187
+ assert isinstance(excinfo.value, m.MyException5_1)
188
+
189
+ with pytest.raises(m.MyException5_1) as excinfo:
190
+ m.throws5_1()
191
+ assert msg(excinfo.value) == "MyException5 subclass"
192
+
193
+ with pytest.raises(m.MyException5) as excinfo: # noqa: PT012
194
+ try:
195
+ m.throws5()
196
+ except m.MyException5_1 as err:
197
+ raise RuntimeError("Exception error: caught child from parent") from err
198
+ assert msg(excinfo.value) == "this is a helper-defined translated exception"
199
+
200
+
201
+ def test_nested_throws(capture):
202
+ """Tests nested (e.g. C++ -> Python -> C++) exception handling"""
203
+
204
+ def throw_myex():
205
+ raise m.MyException("nested error")
206
+
207
+ def throw_myex5():
208
+ raise m.MyException5("nested error 5")
209
+
210
+ # In the comments below, the exception is caught in the first step, thrown in the last step
211
+
212
+ # C++ -> Python
213
+ with capture:
214
+ m.try_catch(m.MyException5, throw_myex5)
215
+ assert str(capture).startswith("MyException5: nested error 5")
216
+
217
+ # Python -> C++ -> Python
218
+ with pytest.raises(m.MyException) as excinfo:
219
+ m.try_catch(m.MyException5, throw_myex)
220
+ assert str(excinfo.value) == "nested error"
221
+
222
+ def pycatch(exctype, f, *args): # noqa: ARG001
223
+ try:
224
+ f(*args)
225
+ except m.MyException as e:
226
+ print(e)
227
+
228
+ # C++ -> Python -> C++ -> Python
229
+ with capture:
230
+ m.try_catch(
231
+ m.MyException5,
232
+ pycatch,
233
+ m.MyException,
234
+ m.try_catch,
235
+ m.MyException,
236
+ throw_myex5,
237
+ )
238
+ assert str(capture).startswith("MyException5: nested error 5")
239
+
240
+ # C++ -> Python -> C++
241
+ with capture:
242
+ m.try_catch(m.MyException, pycatch, m.MyException5, m.throws4)
243
+ assert capture == "this error is rethrown"
244
+
245
+ # Python -> C++ -> Python -> C++
246
+ with pytest.raises(m.MyException5) as excinfo:
247
+ m.try_catch(m.MyException, pycatch, m.MyException, m.throws5)
248
+ assert str(excinfo.value) == "this is a helper-defined translated exception"
249
+
250
+
251
+ # TODO: Investigate this crash, see pybind/pybind11#5062 for background
252
+ @pytest.mark.skipif(
253
+ sys.platform.startswith("win32") and "Clang" in pybind11_tests.compiler_info,
254
+ reason="Started segfaulting February 2024",
255
+ )
256
+ def test_throw_nested_exception():
257
+ with pytest.raises(RuntimeError) as excinfo:
258
+ m.throw_nested_exception()
259
+ assert str(excinfo.value) == "Outer Exception"
260
+ assert str(excinfo.value.__cause__) == "Inner Exception"
261
+
262
+
263
+ # This can often happen if you wrap a pybind11 class in a Python wrapper
264
+ def test_invalid_repr():
265
+ class MyRepr:
266
+ def __repr__(self):
267
+ raise AttributeError("Example error")
268
+
269
+ with pytest.raises(TypeError):
270
+ m.simple_bool_passthrough(MyRepr())
271
+
272
+
273
+ def test_local_translator(msg):
274
+ """Tests that a local translator works and that the local translator from
275
+ the cross module is not applied"""
276
+ with pytest.raises(RuntimeError) as excinfo:
277
+ m.throws6()
278
+ assert msg(excinfo.value) == "MyException6 only handled in this module"
279
+
280
+ with pytest.raises(RuntimeError) as excinfo:
281
+ m.throws_local_error()
282
+ assert not isinstance(excinfo.value, KeyError)
283
+ assert msg(excinfo.value) == "never caught"
284
+
285
+ with pytest.raises(Exception) as excinfo:
286
+ m.throws_local_simple_error()
287
+ assert not isinstance(excinfo.value, cm.LocalSimpleException)
288
+ assert msg(excinfo.value) == "this mod"
289
+
290
+
291
+ def test_error_already_set_message_with_unicode_surrogate(): # Issue #4288
292
+ assert m.error_already_set_what(RuntimeError, "\ud927") == (
293
+ "RuntimeError: \\ud927",
294
+ False,
295
+ )
296
+
297
+
298
+ def test_error_already_set_message_with_malformed_utf8():
299
+ assert m.error_already_set_what(RuntimeError, b"\x80") == (
300
+ "RuntimeError: b'\\x80'",
301
+ False,
302
+ )
303
+
304
+
305
+ class FlakyException(Exception):
306
+ def __init__(self, failure_point):
307
+ if failure_point == "failure_point_init":
308
+ raise ValueError("triggered_failure_point_init")
309
+ self.failure_point = failure_point
310
+
311
+ def __str__(self):
312
+ if self.failure_point == "failure_point_str":
313
+ raise ValueError("triggered_failure_point_str")
314
+ return "FlakyException.__str__"
315
+
316
+
317
+ @pytest.mark.parametrize(
318
+ ("exc_type", "exc_value", "expected_what"),
319
+ [
320
+ (ValueError, "plain_str", "ValueError: plain_str"),
321
+ (ValueError, ("tuple_elem",), "ValueError: tuple_elem"),
322
+ (FlakyException, ("happy",), "FlakyException: FlakyException.__str__"),
323
+ ],
324
+ )
325
+ def test_error_already_set_what_with_happy_exceptions(
326
+ exc_type, exc_value, expected_what
327
+ ):
328
+ what, py_err_set_after_what = m.error_already_set_what(exc_type, exc_value)
329
+ assert not py_err_set_after_what
330
+ assert what == expected_what
331
+
332
+
333
+ def _test_flaky_exception_failure_point_init_before_py_3_12():
334
+ with pytest.raises(RuntimeError) as excinfo:
335
+ m.error_already_set_what(FlakyException, ("failure_point_init",))
336
+ lines = str(excinfo.value).splitlines()
337
+ # PyErr_NormalizeException replaces the original FlakyException with ValueError:
338
+ assert lines[:3] == [
339
+ "pybind11::error_already_set: MISMATCH of original and normalized active exception types:"
340
+ " ORIGINAL FlakyException REPLACED BY ValueError: triggered_failure_point_init",
341
+ "",
342
+ "At:",
343
+ ]
344
+ # Checking the first two lines of the traceback as formatted in error_string():
345
+ assert "test_exceptions.py(" in lines[3]
346
+ assert lines[3].endswith("): __init__")
347
+ assert lines[4].endswith(
348
+ "): _test_flaky_exception_failure_point_init_before_py_3_12"
349
+ )
350
+
351
+
352
+ def _test_flaky_exception_failure_point_init_py_3_12():
353
+ # Behavior change in Python 3.12: https://github.com/python/cpython/issues/102594
354
+ what, py_err_set_after_what = m.error_already_set_what(
355
+ FlakyException, ("failure_point_init",)
356
+ )
357
+ assert not py_err_set_after_what
358
+ lines = what.splitlines()
359
+ assert lines[0].endswith("ValueError[WITH __notes__]: triggered_failure_point_init")
360
+ assert lines[1] == "__notes__ (len=1):"
361
+ assert "Normalization failed:" in lines[2]
362
+ assert "FlakyException" in lines[2]
363
+
364
+
365
+ @pytest.mark.skipif(
366
+ "env.PYPY and sys.version_info[:2] < (3, 12)",
367
+ reason="PyErr_NormalizeException Segmentation fault",
368
+ )
369
+ def test_flaky_exception_failure_point_init():
370
+ if sys.version_info[:2] < (3, 12):
371
+ _test_flaky_exception_failure_point_init_before_py_3_12()
372
+ else:
373
+ _test_flaky_exception_failure_point_init_py_3_12()
374
+
375
+
376
+ def test_flaky_exception_failure_point_str():
377
+ what, py_err_set_after_what = m.error_already_set_what(
378
+ FlakyException, ("failure_point_str",)
379
+ )
380
+ assert not py_err_set_after_what
381
+ lines = what.splitlines()
382
+ n = 3 if env.PYPY and len(lines) == 3 else 5
383
+ assert (
384
+ lines[:n]
385
+ == [
386
+ "FlakyException: <MESSAGE UNAVAILABLE DUE TO ANOTHER EXCEPTION>",
387
+ "",
388
+ "MESSAGE UNAVAILABLE DUE TO EXCEPTION: ValueError: triggered_failure_point_str",
389
+ "",
390
+ "At:",
391
+ ][:n]
392
+ )
393
+
394
+
395
+ def test_cross_module_interleaved_error_already_set():
396
+ with pytest.raises(RuntimeError) as excinfo:
397
+ m.test_cross_module_interleaved_error_already_set()
398
+ assert str(excinfo.value) in (
399
+ "2nd error.", # Almost all platforms.
400
+ "RuntimeError: 2nd error.", # Some PyPy builds (seen under macOS).
401
+ )
402
+
403
+
404
+ def test_error_already_set_double_restore():
405
+ m.test_error_already_set_double_restore(True) # dry_run
406
+ with pytest.raises(RuntimeError) as excinfo:
407
+ m.test_error_already_set_double_restore(False)
408
+ assert str(excinfo.value) == (
409
+ "Internal error: pybind11::detail::error_fetch_and_normalize::restore()"
410
+ " called a second time. ORIGINAL ERROR: ValueError: Random error."
411
+ )
412
+
413
+
414
+ def test_pypy_oserror_normalization():
415
+ # https://github.com/pybind/pybind11/issues/4075
416
+ what = m.test_pypy_oserror_normalization()
417
+ assert "this_filename_must_not_exist" in what
418
+
419
+
420
+ def test_fn_cast_int_exception():
421
+ with pytest.raises(RuntimeError) as excinfo:
422
+ m.test_fn_cast_int(lambda: None)
423
+
424
+ assert str(excinfo.value).startswith(
425
+ "Unable to cast Python instance of type <class 'NoneType'> to C++ type"
426
+ )
427
+
428
+
429
+ def test_return_exception_void():
430
+ with pytest.raises(TypeError) as excinfo:
431
+ m.return_exception_void()
432
+ assert "Exception" in str(excinfo.value)