| 723 | } |
| 724 | |
| 725 | int PyModule::load_subclass_of(const char* base_class, PyObject** py_class) |
| 726 | { |
| 727 | // load the base class |
| 728 | PyObject *mgr_module = PyImport_ImportModule("mgr_module"); |
| 729 | if (!mgr_module) { |
| 730 | error_string = peek_pyerror(); |
| 731 | derr << "Module not found: 'mgr_module'" << dendl; |
| 732 | derr << handle_pyerror(true, module_name, "PyModule::load_subclass_of") << dendl; |
| 733 | return -EINVAL; |
| 734 | } |
| 735 | auto mgr_module_type = PyObject_GetAttrString(mgr_module, base_class); |
| 736 | Py_DECREF(mgr_module); |
| 737 | if (!mgr_module_type) { |
| 738 | error_string = peek_pyerror(); |
| 739 | derr << "Unable to import MgrModule from mgr_module" << dendl; |
| 740 | derr << handle_pyerror(true, module_name, "PyModule::load_subclass_of") << dendl; |
| 741 | return -EINVAL; |
| 742 | } |
| 743 | |
| 744 | // find the sub class |
| 745 | PyObject *plugin_module = PyImport_ImportModule(module_name.c_str()); |
| 746 | if (!plugin_module) { |
| 747 | error_string = peek_pyerror(); |
| 748 | derr << "Module not found: '" << module_name << "'" << dendl; |
| 749 | derr << handle_pyerror(true, module_name, "PyModule::load_subclass_of") << dendl; |
| 750 | Py_DECREF(mgr_module_type); |
| 751 | return -ENOENT; |
| 752 | } |
| 753 | auto locals = PyModule_GetDict(plugin_module); |
| 754 | Py_DECREF(plugin_module); |
| 755 | PyObject *key, *value; |
| 756 | Py_ssize_t pos = 0; |
| 757 | *py_class = nullptr; |
| 758 | while (PyDict_Next(locals, &pos, &key, &value)) { |
| 759 | if (!PyType_Check(value)) { |
| 760 | continue; |
| 761 | } |
| 762 | if (!PyObject_IsSubclass(value, mgr_module_type)) { |
| 763 | continue; |
| 764 | } |
| 765 | if (PyObject_RichCompareBool(value, mgr_module_type, Py_EQ)) { |
| 766 | continue; |
| 767 | } |
| 768 | auto class_name = PyUnicode_AsUTF8(key); |
| 769 | if (*py_class) { |
| 770 | derr << __func__ << ": ignoring '" |
| 771 | << module_name << "." << class_name << "'" |
| 772 | << ": only one '" << base_class |
| 773 | << "' class is loaded from each plugin" << dendl; |
| 774 | continue; |
| 775 | } |
| 776 | *py_class = value; |
| 777 | dout(4) << __func__ << ": found class: '" |
| 778 | << module_name << "." << class_name << "'" << dendl; |
| 779 | } |
| 780 | Py_DECREF(mgr_module_type); |
| 781 | |
| 782 | return *py_class ? 0 : -EINVAL; |
nothing calls this directly
no test coverage detected