| 525 | } |
| 526 | |
| 527 | bool SetOpAttrScalar( |
| 528 | TFE_Context* ctx, TFE_Op* op, const char* key, PyObject* py_value, |
| 529 | TF_AttrType type, |
| 530 | tensorflow::gtl::FlatMap<string, tensorflow::int64>* attr_list_sizes, |
| 531 | TF_Status* status) { |
| 532 | if (type == TF_ATTR_STRING) { |
| 533 | tensorflow::StringPiece value; |
| 534 | if (!ParseStringValue(key, py_value, status, &value)) return false; |
| 535 | TFE_OpSetAttrString(op, key, value.data(), value.size()); |
| 536 | } else if (type == TF_ATTR_INT) { |
| 537 | int64_t value; |
| 538 | if (!ParseInt64Value(key, py_value, status, &value)) return false; |
| 539 | TFE_OpSetAttrInt(op, key, value); |
| 540 | // attr_list_sizes is set for all int attributes (since at this point we are |
| 541 | // not aware if that attribute might be used to calculate the size of an |
| 542 | // output list or not). |
| 543 | if (attr_list_sizes != nullptr) (*attr_list_sizes)[key] = value; |
| 544 | } else if (type == TF_ATTR_FLOAT) { |
| 545 | float value; |
| 546 | if (!ParseFloatValue(key, py_value, status, &value)) return false; |
| 547 | TFE_OpSetAttrFloat(op, key, value); |
| 548 | } else if (type == TF_ATTR_BOOL) { |
| 549 | unsigned char value; |
| 550 | if (!ParseBoolValue(key, py_value, status, &value)) return false; |
| 551 | TFE_OpSetAttrBool(op, key, value); |
| 552 | } else if (type == TF_ATTR_TYPE) { |
| 553 | int value; |
| 554 | if (!ParseTypeValue(key, py_value, status, &value)) return false; |
| 555 | TFE_OpSetAttrType(op, key, static_cast<TF_DataType>(value)); |
| 556 | } else if (type == TF_ATTR_SHAPE) { |
| 557 | if (py_value == Py_None) { |
| 558 | TFE_OpSetAttrShape(op, key, nullptr, -1, status); |
| 559 | } else { |
| 560 | if (!PySequence_Check(py_value)) { |
| 561 | TF_SetStatus(status, TF_INVALID_ARGUMENT, |
| 562 | tensorflow::strings::StrCat( |
| 563 | "Expecting None or sequence value for attr", key, |
| 564 | ", got ", py_value->ob_type->tp_name) |
| 565 | .c_str()); |
| 566 | return false; |
| 567 | } |
| 568 | const auto num_dims = TensorShapeNumDims(py_value); |
| 569 | if (num_dims == -1) { |
| 570 | TFE_OpSetAttrShape(op, key, nullptr, -1, status); |
| 571 | return true; |
| 572 | } |
| 573 | std::unique_ptr<int64_t[]> dims(new int64_t[num_dims]); |
| 574 | for (int i = 0; i < num_dims; ++i) { |
| 575 | tensorflow::Safe_PyObjectPtr inner_py_value( |
| 576 | PySequence_ITEM(py_value, i)); |
| 577 | if (inner_py_value.get() == Py_None) { |
| 578 | dims[i] = -1; |
| 579 | } else if (!ParseDimensionValue(key, inner_py_value.get(), status, |
| 580 | &dims[i])) { |
| 581 | return false; |
| 582 | } |
| 583 | } |
| 584 | TFE_OpSetAttrShape(op, key, dims.get(), num_dims, status); |
no test coverage detected