| 696 | } |
| 697 | |
| 698 | Status VisitDict(PyObject* obj) { |
| 699 | PyObject* key_obj; |
| 700 | PyObject* value_obj; |
| 701 | Py_ssize_t pos = 0; |
| 702 | |
| 703 | while (PyDict_Next(obj, &pos, &key_obj, &value_obj)) { |
| 704 | std::string key; |
| 705 | if (PyUnicode_Check(key_obj)) { |
| 706 | RETURN_NOT_OK(internal::PyUnicode_AsStdString(key_obj, &key)); |
| 707 | } else if (PyBytes_Check(key_obj)) { |
| 708 | key = internal::PyBytes_AsStdString(key_obj); |
| 709 | } else { |
| 710 | return Status::TypeError("Expected dict key of type str or bytes, got '", |
| 711 | Py_TYPE(key_obj)->tp_name, "'"); |
| 712 | } |
| 713 | // Get or create visitor for this key |
| 714 | TypeInferrer* visitor; |
| 715 | auto it = struct_field_index_.find(key); |
| 716 | if (it == struct_field_index_.end()) { |
| 717 | // New field - add to vector and index |
| 718 | size_t new_index = struct_inferrers_.size(); |
| 719 | struct_inferrers_.emplace_back( |
| 720 | key, TypeInferrer(pandas_null_sentinels_, validate_interval_, make_unions_)); |
| 721 | struct_field_index_.emplace(std::move(key), new_index); |
| 722 | visitor = &struct_inferrers_.back().second; |
| 723 | } else { |
| 724 | // Existing field - retrieve from vector |
| 725 | visitor = &struct_inferrers_[it->second].second; |
| 726 | } |
| 727 | |
| 728 | // We ignore termination signals from child visitors for now |
| 729 | // |
| 730 | // TODO(wesm): keep track of whether type inference has terminated for |
| 731 | // the child visitors to avoid doing unneeded work |
| 732 | bool keep_going = true; |
| 733 | RETURN_NOT_OK(visitor->Visit(value_obj, &keep_going)); |
| 734 | } |
| 735 | |
| 736 | // We do not terminate visiting dicts since we want the union of all |
| 737 | // observed keys |
| 738 | ++struct_count_; |
| 739 | return Status::OK(); |
| 740 | } |
| 741 | |
| 742 | Status GetStructType(std::shared_ptr<DataType>* out) { |
| 743 | std::vector<std::shared_ptr<Field>> fields; |
nothing calls this directly
no test coverage detected