| 2826 | } |
| 2827 | |
| 2828 | bool RunCallbacks( |
| 2829 | const FastPathOpExecInfo& op_exec_info, PyObject* args, |
| 2830 | const std::vector<tensorflow::Safe_PyObjectPtr>* const flattened_inputs, |
| 2831 | const std::vector<tensorflow::Safe_PyObjectPtr>* const flattened_attrs, |
| 2832 | PyObject* flattened_result) { |
| 2833 | if (!op_exec_info.run_callbacks) return true; |
| 2834 | |
| 2835 | tensorflow::Safe_PyObjectPtr inputs(PyTuple_New(flattened_inputs->size())); |
| 2836 | for (size_t i = 0; i < flattened_inputs->size(); i++) { |
| 2837 | PyObject* input = (*flattened_inputs)[i].get(); |
| 2838 | Py_INCREF(input); |
| 2839 | PyTuple_SET_ITEM(inputs.get(), i, input); |
| 2840 | } |
| 2841 | |
| 2842 | int num_non_inferred_attrs = PyTuple_GET_SIZE(args) - |
| 2843 | op_exec_info.op_def->input_arg_size() - |
| 2844 | kFastPathExecuteInputStartIndex; |
| 2845 | int num_attrs = flattened_attrs->size() + num_non_inferred_attrs; |
| 2846 | tensorflow::Safe_PyObjectPtr attrs(PyTuple_New(num_attrs)); |
| 2847 | |
| 2848 | for (int i = 0; i < num_non_inferred_attrs; i++) { |
| 2849 | auto* attr = |
| 2850 | PyTuple_GET_ITEM(args, kFastPathExecuteInputStartIndex + |
| 2851 | op_exec_info.op_def->input_arg_size() + i); |
| 2852 | Py_INCREF(attr); |
| 2853 | PyTuple_SET_ITEM(attrs.get(), i, attr); |
| 2854 | } |
| 2855 | for (int i = num_non_inferred_attrs; i < num_attrs; i++) { |
| 2856 | PyObject* attr_or_name = |
| 2857 | flattened_attrs->at(i - num_non_inferred_attrs).get(); |
| 2858 | Py_INCREF(attr_or_name); |
| 2859 | PyTuple_SET_ITEM(attrs.get(), i, attr_or_name); |
| 2860 | } |
| 2861 | |
| 2862 | if (op_exec_info.run_gradient_callback) { |
| 2863 | if (!RecordGradient(op_exec_info.op_name, inputs.get(), attrs.get(), |
| 2864 | flattened_result, op_exec_info.name)) { |
| 2865 | return false; |
| 2866 | } |
| 2867 | } |
| 2868 | |
| 2869 | if (op_exec_info.run_post_exec_callbacks) { |
| 2870 | tensorflow::Safe_PyObjectPtr callback_args( |
| 2871 | Py_BuildValue("OOOOO", op_exec_info.op_name, inputs.get(), attrs.get(), |
| 2872 | flattened_result, op_exec_info.name)); |
| 2873 | for (Py_ssize_t i = 0; i < PyList_Size(op_exec_info.callbacks); i++) { |
| 2874 | PyObject* callback_fn = PyList_GET_ITEM(op_exec_info.callbacks, i); |
| 2875 | if (!PyCallable_Check(callback_fn)) { |
| 2876 | PyErr_SetString( |
| 2877 | PyExc_TypeError, |
| 2878 | Printf("expected a function for " |
| 2879 | "post execution callback in index %ld, got %s instead", |
| 2880 | i, callback_fn->ob_type->tp_name) |
| 2881 | .c_str()); |
| 2882 | return false; |
| 2883 | } |
| 2884 | PyObject* callback_result = |
| 2885 | PyObject_CallObject(callback_fn, callback_args.get()); |
no test coverage detected