| 120 | } |
| 121 | |
| 122 | inline object import_or_getattr(const std::string &fully_qualified_name, |
| 123 | const std::string &append_to_exception_message) { |
| 124 | std::istringstream stream(fully_qualified_name); |
| 125 | std::string part; |
| 126 | |
| 127 | if (!std::getline(stream, part, '.') || part.empty()) { |
| 128 | std::string msg = "Invalid fully-qualified name `"; |
| 129 | msg += fully_qualified_name; |
| 130 | msg += "`"; |
| 131 | msg += append_to_exception_message; |
| 132 | throw value_error(msg); |
| 133 | } |
| 134 | |
| 135 | auto curr_scope = reinterpret_steal<object>(PyImport_ImportModule(part.c_str())); |
| 136 | if (!curr_scope) { |
| 137 | std::string msg = "Failed to import top-level module `"; |
| 138 | msg += part; |
| 139 | msg += "`"; |
| 140 | msg += append_to_exception_message; |
| 141 | raise_from(PyExc_ImportError, msg.c_str()); |
| 142 | throw error_already_set(); |
| 143 | } |
| 144 | |
| 145 | // Now recursively getattr or import remaining parts |
| 146 | std::string curr_path = part; |
| 147 | while (std::getline(stream, part, '.')) { |
| 148 | if (part.empty()) { |
| 149 | std::string msg = "Invalid fully-qualified name `"; |
| 150 | msg += fully_qualified_name; |
| 151 | msg += "`"; |
| 152 | msg += append_to_exception_message; |
| 153 | throw value_error(msg); |
| 154 | } |
| 155 | std::string next_path = curr_path; |
| 156 | next_path += "."; |
| 157 | next_path += part; |
| 158 | auto next_scope |
| 159 | = reinterpret_steal<object>(PyObject_GetAttrString(curr_scope.ptr(), part.c_str())); |
| 160 | if (!next_scope) { |
| 161 | error_fetch_and_normalize stored_getattr_error("getattr"); |
| 162 | // Try importing the next level |
| 163 | next_scope = reinterpret_steal<object>(PyImport_ImportModule(next_path.c_str())); |
| 164 | if (!next_scope) { |
| 165 | error_fetch_and_normalize stored_import_error("import"); |
| 166 | std::string msg = "Failed to import or getattr `"; |
| 167 | msg += part; |
| 168 | msg += "` from `"; |
| 169 | msg += curr_path; |
| 170 | msg += "`"; |
| 171 | msg += append_to_exception_message; |
| 172 | msg += "\n-------- getattr exception --------\n"; |
| 173 | msg += stored_getattr_error.error_string(); |
| 174 | msg += "\n-------- import exception --------\n"; |
| 175 | msg += stored_import_error.error_string(); |
| 176 | throw import_error(msg.c_str()); |
| 177 | } |
| 178 | } |
| 179 | curr_scope = next_scope; |
no test coverage detected