Skip to content

Commit 5cb74bd

Browse files
committed
nanobind: fix py::str(accessor) reinterpret bug (wrap in py::object so PyObject_Str runs) across numpy/pandas/udf/replacement paths
1 parent a65adc0 commit 5cb74bd

6 files changed

Lines changed: 8 additions & 8 deletions

File tree

src/duckdb_py/map.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static py::object FunctionCall(NumpyResultConversion &conversion, const vector<I
5252
if (!py::isinstance<PandasDataFrame>(df)) {
5353
throw InvalidInputException(
5454
"Expected the UDF to return an object of type 'pandas.DataFrame', found '%s' instead",
55-
py::cast<std::string>(py::str(df.attr("__class__"))));
55+
py::cast<std::string>(py::str(py::object(df.attr("__class__")))));
5656
}
5757
if (PandasDataFrame::IsPyArrowBacked(df)) {
5858
throw InvalidInputException(

src/duckdb_py/numpy/numpy_bind.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ void NumpyBind::Bind(ClientContext &context, py::handle df, vector<PandasColumnB
1515
auto df_columns = py::list(df.attr("keys")());
1616
auto df_types = py::list();
1717
for (auto item : py::cast<py::dict>(df)) {
18-
if (py::cast<std::string>(py::str(item.second.attr("dtype").attr("char"))) == "U") {
18+
if (py::cast<std::string>(py::str(py::object(item.second.attr("dtype").attr("char")))) == "U") {
1919
df_types.attr("append")(py::str("string"));
2020
continue;
2121
}
22-
df_types.attr("append")(py::str(item.second.attr("dtype")));
22+
df_types.attr("append")(py::str(py::object(item.second.attr("dtype"))));
2323
}
2424
auto get_fun = df.attr("__getitem__");
2525
if (py::len(df_columns) == 0 || py::len(df_types) == 0 || py::len(df_columns) != py::len(df_types)) {
@@ -53,7 +53,7 @@ void NumpyBind::Bind(ClientContext &context, py::handle df, vector<PandasColumnB
5353
}
5454
duckdb_col_type = LogicalType::ENUM(enum_entries_vec, size);
5555
auto pandas_col = uniq.attr("__getitem__")(1);
56-
bind_data.internal_categorical_type = py::cast<std::string>(py::str(pandas_col.attr("dtype")));
56+
bind_data.internal_categorical_type = py::cast<std::string>(py::str(py::object(pandas_col.attr("dtype"))));
5757
bind_data.pandas_col = std::make_unique<PandasNumpyColumn>(NumpyArray(pandas_col));
5858
} else {
5959
bind_data.pandas_col = std::make_unique<PandasNumpyColumn>(NumpyArray(column));

src/duckdb_py/pyexpression.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ std::shared_ptr<DuckDBPyExpression> DuckDBPyExpression::StarExpression(py::objec
319319
std::shared_ptr<DuckDBPyExpression> DuckDBPyExpression::ColumnExpression(const py::args &names) {
320320
vector<Identifier> column_names;
321321
if (names.size() == 1) {
322-
string column_name = py::cast<std::string>(py::str(names[0]));
322+
string column_name = py::cast<std::string>(py::str(py::object(names[0])));
323323
if (column_name == "*") {
324324
return StarExpression();
325325
}

src/duckdb_py/python_replacement_scan.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ static unique_ptr<TableRef> TryReplacement(py::dict &dict, const string &name, C
225225
if (!result) {
226226
std::string location = py::cast<std::string>(current_frame.attr("f_code").attr("co_filename"));
227227
location += ":";
228-
location += py::cast<std::string>(py::str(current_frame.attr("f_lineno")));
228+
location += py::cast<std::string>(py::str(py::object(current_frame.attr("f_lineno"))));
229229
ThrowScanFailureError(entry, name, location);
230230
}
231231
return result;

src/duckdb_py/python_udf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ static bool NumpyDeprecatesAccessToCore(const py::tuple &numpy_version) {
400400
if (numpy_version.empty()) {
401401
return false;
402402
}
403-
if (py::cast<std::string>(py::str(numpy_version[0])) == string("2")) {
403+
if (py::cast<std::string>(py::str(py::object(numpy_version[0]))) == string("2")) {
404404
//! Starting with numpy version 2.0.0 the use of 'core' is deprecated.
405405
return true;
406406
}

src/duckdb_py/typing/pytype.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ static bool FromNumpyType(const py::object &type, LogicalType &result) {
140140
if (!py::hasattr(obj, "dtype")) {
141141
return false;
142142
}
143-
string type_str = py::cast<std::string>(py::str(obj.attr("dtype")));
143+
string type_str = py::cast<std::string>(py::str(py::object(obj.attr("dtype"))));
144144
if (type_str == "bool") {
145145
result = LogicalType::BOOLEAN;
146146
} else if (type_str == "int8") {

0 commit comments

Comments
 (0)