Exemple #1
0
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;
}
Exemple #2
0
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, &copyEntry.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, &copyStack);
            });
    }

    // 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;
}
Exemple #3
0
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;
}