Skip to content

Commit 3a183d4

Browse files
authored
fix: improve str exceptions and consistency with python (#3826)
* Improve str exceptions * Revert macro change just in case * Make clang-tidy happy * Fix one more clang-tidy issue * Refactor duplicate method
1 parent 7742be0 commit 3a183d4

File tree

1 file changed

+15
-19
lines changed

1 file changed

+15
-19
lines changed

include/pybind11/pytypes.h

+15-19
Original file line numberDiff line numberDiff line change
@@ -1243,8 +1243,8 @@ class str : public object {
12431243
}
12441244
char *buffer = nullptr;
12451245
ssize_t length = 0;
1246-
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) {
1247-
pybind11_fail("Unable to extract string contents! (invalid type)");
1246+
if (PyBytes_AsStringAndSize(temp.ptr(), &buffer, &length) != 0) {
1247+
throw error_already_set();
12481248
}
12491249
return std::string(buffer, (size_t) length);
12501250
}
@@ -1299,14 +1299,7 @@ class bytes : public object {
12991299
explicit bytes(const pybind11::str &s);
13001300

13011301
// NOLINTNEXTLINE(google-explicit-constructor)
1302-
operator std::string() const {
1303-
char *buffer = nullptr;
1304-
ssize_t length = 0;
1305-
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length)) {
1306-
pybind11_fail("Unable to extract bytes contents!");
1307-
}
1308-
return std::string(buffer, (size_t) length);
1309-
}
1302+
operator std::string() const { return string_op<std::string>(); }
13101303

13111304
#ifdef PYBIND11_HAS_STRING_VIEW
13121305
// enable_if is needed to avoid "ambiguous conversion" errors (see PR #3521).
@@ -1318,15 +1311,18 @@ class bytes : public object {
13181311
// valid so long as the `bytes` instance remains alive and so generally should not outlive the
13191312
// lifetime of the `bytes` instance.
13201313
// NOLINTNEXTLINE(google-explicit-constructor)
1321-
operator std::string_view() const {
1314+
operator std::string_view() const { return string_op<std::string_view>(); }
1315+
#endif
1316+
private:
1317+
template <typename T>
1318+
T string_op() const {
13221319
char *buffer = nullptr;
13231320
ssize_t length = 0;
1324-
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length)) {
1325-
pybind11_fail("Unable to extract bytes contents!");
1321+
if (PyBytes_AsStringAndSize(m_ptr, &buffer, &length) != 0) {
1322+
throw error_already_set();
13261323
}
13271324
return {buffer, static_cast<size_t>(length)};
13281325
}
1329-
#endif
13301326
};
13311327
// Note: breathe >= 4.17.0 will fail to build docs if the below two constructors
13321328
// are included in the doxygen group; close here and reopen after as a workaround
@@ -1337,13 +1333,13 @@ inline bytes::bytes(const pybind11::str &s) {
13371333
if (PyUnicode_Check(s.ptr())) {
13381334
temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(s.ptr()));
13391335
if (!temp) {
1340-
pybind11_fail("Unable to extract string contents! (encoding issue)");
1336+
throw error_already_set();
13411337
}
13421338
}
13431339
char *buffer = nullptr;
13441340
ssize_t length = 0;
1345-
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) {
1346-
pybind11_fail("Unable to extract string contents! (invalid type)");
1341+
if (PyBytes_AsStringAndSize(temp.ptr(), &buffer, &length) != 0) {
1342+
throw error_already_set();
13471343
}
13481344
auto obj = reinterpret_steal<object>(PYBIND11_BYTES_FROM_STRING_AND_SIZE(buffer, length));
13491345
if (!obj) {
@@ -1355,8 +1351,8 @@ inline bytes::bytes(const pybind11::str &s) {
13551351
inline str::str(const bytes &b) {
13561352
char *buffer = nullptr;
13571353
ssize_t length = 0;
1358-
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(b.ptr(), &buffer, &length)) {
1359-
pybind11_fail("Unable to extract bytes contents!");
1354+
if (PyBytes_AsStringAndSize(b.ptr(), &buffer, &length) != 0) {
1355+
throw error_already_set();
13601356
}
13611357
auto obj = reinterpret_steal<object>(PyUnicode_FromStringAndSize(buffer, length));
13621358
if (!obj) {

0 commit comments

Comments
 (0)