@@ -1241,12 +1241,19 @@ std::unique_ptr<DuckDBPyRelation> DuckDBPyConnection::ReadCSV(const py::object &
12411241 child_list_t <Value> struct_fields;
12421242 py::dict dtype_dict = py::cast<py::dict>(dtype);
12431243 for (auto kv : dtype_dict) { // nanobind dict iteration yields std::pair<handle,handle> by value
1244- std::shared_ptr<DuckDBPyType> sql_type;
1245- if (!py::try_cast (kv.second , sql_type)) {
1246- struct_fields.emplace_back (py::cast<std::string>(py::str (kv.first )),
1247- Value (py::cast<std::string>(py::str (kv.second ))));
1244+ auto key = py::cast<std::string>(py::str (kv.first ));
1245+ auto value_obj = py::borrow<py::object>(kv.second );
1246+ if (py::isinstance<py::str>(value_obj)) {
1247+ // A type string -- pass through for DuckDB to parse.
1248+ struct_fields.emplace_back (key, Value (py::cast<std::string>(value_obj)));
12481249 } else {
1249- struct_fields.emplace_back (py::cast<std::string>(py::str (kv.first )), Value (sql_type->ToString ()));
1250+ // A DuckDBPyType instance, or a Python type object (int/str/...). nanobind's shared_ptr caster
1251+ // strips the implicit-convert flag, so build the DuckDBPyType via its registered constructor.
1252+ if (!py::isinstance<DuckDBPyType>(value_obj)) {
1253+ value_obj = py::type<DuckDBPyType>()(value_obj);
1254+ }
1255+ auto sql_type = py::cast<std::shared_ptr<DuckDBPyType>>(value_obj);
1256+ struct_fields.emplace_back (key, Value (sql_type->ToString ()));
12501257 }
12511258 }
12521259 auto dtype_struct = Value::STRUCT (std::move (struct_fields));
@@ -1255,11 +1262,12 @@ std::unique_ptr<DuckDBPyRelation> DuckDBPyConnection::ReadCSV(const py::object &
12551262 vector<Value> list_values;
12561263 py::list dtype_list = py::cast<py::list>(dtype);
12571264 for (auto child : dtype_list) {
1265+ auto child_obj = py::borrow<py::object>(child);
12581266 std::shared_ptr<DuckDBPyType> sql_type;
1259- if (!py::try_cast (child, sql_type)) {
1260- list_values.push_back (Value (py::cast<std::string>(child)));
1261- } else {
1267+ if (!py::isinstance<py::str>(child_obj) && DuckDBPyType::TryConvert (child_obj, sql_type)) {
12621268 list_values.push_back (sql_type->ToString ());
1269+ } else {
1270+ list_values.push_back (Value (py::cast<std::string>(py::str (child_obj))));
12631271 }
12641272 }
12651273 bind_parameters[" dtypes" ] = Value::LIST (LogicalType::VARCHAR , std::move (list_values));
0 commit comments