PyObject *PyRecord::tp_richcompare(PyObject *self, PyObject *other, int op) { PyObject *ret = NULL; if (op != Py_EQ && op != Py_NE) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } int success = op == Py_EQ ? TRUE : FALSE; if (self->ob_type != other->ob_type) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyRecord *pyself = (PyRecord *)self; PyRecord *pyother = (PyRecord *)other; if (!pyself->pri->IsMatchingType(pyother->pri)) { // Not matching types, so can't compare. Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } // Need to do a recursive compare, as some elements may be pointers // (eg, strings, objects) ULONG num_names; BSTR *strings = _GetFieldNames(pyself->pri, &num_names); if (strings==NULL) return NULL; for (ULONG i=0;i<num_names;i++) { ret = 0; PyObject *obattrname; obattrname=PyWinCoreString_FromString(strings[i]); if (obattrname==NULL) goto done; // There appear to be several problems here. This will leave an exception hanging // if an attribute is not found, and should probably return False if other does not // have an attr that self does ??? // MarkH: but is that possible in practice? For structures, // an attribute must be found, and the set must be identical // (we have already checked the 'type' is the same above) // (defense against COM errors etc would be nice though :) PyObject *self_sub = PyRecord::getattro(self, obattrname); if (!self_sub) { Py_DECREF(obattrname); goto done; } PyObject *other_sub = PyRecord::getattro(other, obattrname); if (!other_sub){ Py_DECREF(obattrname); Py_DECREF(self_sub); goto done; } int c = PyObject_RichCompareBool(self_sub, other_sub, op); Py_DECREF(self_sub); Py_DECREF(other_sub); Py_DECREF(obattrname); if (c == -1) goto done; if (c != success) { ret = PyBool_FromLong(c); goto done; } } ret = PyBool_FromLong(success); done: _FreeFieldNames(strings, num_names); return ret; }
bool SdfCopySpec( const SdfLayerHandle& srcLayer, const SdfPath& srcPath, const SdfLayerHandle& dstLayer, const SdfPath& dstPath, const SdfShouldCopyValueFn& shouldCopyValueFn, const SdfShouldCopyChildrenFn& shouldCopyChildrenFn) { if (!srcLayer || !dstLayer) { TF_CODING_ERROR("Invalid layer handle"); return false; } if (srcPath.IsEmpty() || dstPath.IsEmpty()) { TF_CODING_ERROR("Invalid empty path"); return false; } // Validate compatible source and destination path types. if ((srcPath.IsAbsoluteRootOrPrimPath() || srcPath.IsPrimVariantSelectionPath()) != (dstPath.IsAbsoluteRootOrPrimPath() || dstPath.IsPrimVariantSelectionPath()) || srcPath.IsPropertyPath() != dstPath.IsPropertyPath() || srcPath.IsTargetPath() != dstPath.IsTargetPath() || srcPath.IsMapperPath() != dstPath.IsMapperPath() || srcPath.IsMapperArgPath() != dstPath.IsMapperArgPath() || srcPath.IsExpressionPath() != dstPath.IsExpressionPath()) { TF_CODING_ERROR("Incompatible source and destination paths"); return false; } // For target paths (relationship targets and connections), verify the // destination spec already exists. See the documentation comment. if (dstPath.IsTargetPath() && !dstLayer->HasSpec(dstPath)) { TF_CODING_ERROR("Spec does not exist at destination target path"); return false; } // This function collects all of the data that will be copied for each // spec into this list, then applies it to the layer at the very end. // This allows us to do some analysis on the data first. _CopyEntryList dataToCopy; // Create a stack of source/dest copy requests, initially populated with // the passed parameters. The copy routine will add additional requests // as needed to handle children etc... and runs until the stack is empty. _CopyStack copyStack(1, _CopyStackEntry(srcPath, dstPath)); while (!copyStack.empty()) { const _CopyStackEntry toCopy = copyStack.front(); copyStack.pop_front(); // If the source path is empty, it indicates that the spec at the // destination path should be removed. Add an entry to the queue // to reflect that. if (toCopy.srcPath.IsEmpty()) { _SpecDataEntry removeEntry(toCopy.dstPath, SdfSpecTypeUnknown); dataToCopy.push_back(removeEntry); continue; } // Figure out the concrete type of the spec we're copying. The spec type // dictates copying behavior below. const SdfSpecType specType = srcLayer->GetSpecType(toCopy.srcPath); if (specType == SdfSpecTypeUnknown) { TF_CODING_ERROR("Cannot copy unknown spec at <%s> from layer <%s>", srcPath.GetText(), srcLayer->GetIdentifier().c_str()); return false; } _SpecDataEntry copyEntry(toCopy.dstPath, specType); // Determine what data is present for the current source and dest specs // and what needs to be copied. Divide the present fields into those // that contain values and those that index children specs. std::vector<TfToken> dstValueFields; std::vector<TfToken> dstChildrenFields; _GetFieldNames( dstLayer, toCopy.dstPath, &dstValueFields, &dstChildrenFields); std::vector<TfToken> srcValueFields; std::vector<TfToken> srcChildrenFields; _GetFieldNames( srcLayer, toCopy.srcPath, &srcValueFields, &srcChildrenFields); // From the list of value fields, retrieve all values that the copy // policy says we need to copy over to the destination. _ForEachField( srcValueFields, dstValueFields, [&](const TfToken& field, bool fieldInSrc, bool fieldInDst) { _AddFieldValueToCopy( specType, field, srcLayer, toCopy.srcPath, fieldInSrc, dstLayer, toCopy.dstPath, fieldInDst, shouldCopyValueFn, ©Entry.dataToCopy); }); // Add an entry for all of the data we're copying for this spec. dataToCopy.push_back(copyEntry); // Now add any children specs that need to be copied to our // copy stack. _ForEachField( srcChildrenFields, dstChildrenFields, [&](const TfToken& field, bool fieldInSrc, bool fieldInDst) { _ProcessChildField( field, srcLayer, toCopy.srcPath, fieldInSrc, dstLayer, toCopy.dstPath, fieldInDst, shouldCopyChildrenFn, ©Stack); }); } // Now that we have all the data we want to copy, set it into the // destination layer. SdfChangeBlock block; for (const _SpecDataEntry& specData : dataToCopy) { if (specData.specType == SdfSpecTypeUnknown) { _RemoveSpecFromLayer(dstLayer, specData); } else { _AddNewSpecToLayer(dstLayer, specData); } for (const _FieldValuePair& fieldValue : specData.dataToCopy) { dstLayer->SetField( specData.dstPath, fieldValue.first, fieldValue.second); } } return true; }
PyObject *PyRecord::tp_repr(PyObject *self) { ULONG i; PyRecord *pyrec = (PyRecord *)self; ULONG num_names; BSTR *strings = _GetFieldNames(pyrec->pri, &num_names); if (strings==NULL) return NULL; PyObject *obrepr=NULL, *obattrname; BOOL bsuccess=FALSE; PyObject *comma = PyWinCoreString_FromString(_T(", ")); PyObject *equals = PyWinCoreString_FromString(_T("=")); PyObject *closing_paren=PyWinCoreString_FromString(_T(")")); obrepr = PyWinCoreString_FromString(_T("com_struct(")); if (obrepr==NULL || comma==NULL || equals==NULL || closing_paren==NULL) goto done; for (i = 0; i < num_names && obrepr != NULL; i++) { obattrname=PyWinCoreString_FromString(strings[i]); if (obattrname==NULL) goto done; // must exit on error via loop_error from here... PyObject *sub_object = NULL; if (i > 0){ PyWinCoreString_Concat(&obrepr, comma); if (!obrepr) goto loop_error; } PyWinCoreString_Concat(&obrepr, obattrname); if (!obrepr) goto loop_error; PyWinCoreString_Concat(&obrepr, equals); if (!obrepr) goto loop_error; sub_object = PyRecord::getattro(self, obattrname); if (!sub_object) goto loop_error; PyWinCoreString_ConcatAndDel(&obrepr, PyObject_Repr(sub_object)); Py_DECREF(sub_object); Py_DECREF(obattrname); continue; // loop error handler. loop_error: Py_DECREF(obattrname); goto done; } PyWinCoreString_Concat(&obrepr, closing_paren); bsuccess=TRUE; done: Py_XDECREF(comma); Py_XDECREF(equals); Py_XDECREF(closing_paren); if (strings) _FreeFieldNames(strings, num_names); if (!bsuccess){ Py_XDECREF(obrepr); obrepr=NULL; } return obrepr; }