Cant sucessfully implement the IFailuresPreprocessor interface

Hello, i’ve been trying to develop a code to ignore all warnings that is generated when i try to join multiple walls in a project

it seems like i have an issue with the implementation of the IFailuresPreprocessor Interface

class JoinFailureAdvancedHandler(IFailuresPreprocessor):
	def PreprocessFailures(failuresAccessor):
		failMessages = failuresAccessor.GetFailureMessages()
		if failMessages.Count == 0:
			return FailureProcessingResult.Continue
		transName = failuresAccessor.GetTransactionName()
		if transName == "Wall Join Operation":
			if failuresAccessor.GetSeverity() == FailureSeverity.Warning:
				for currentMessage in failMessages:
					failuresAccessor.ResolveFailure(currentMessage)
				failuresAccessor.DeleteAllWarnings()	
				return FailureProcessingResult.ProceedWithCommit
				
		return FailureProcessingResult.Continue

It is not deleting the warnings generated in the document when i try to join then. And it even blocks me from ignoring then… only allowing me to cancel the warning, thus, rolling back the join operation transaction

t = Transaction(doc)
t.Start("Wall Join Operation")
joinFailOp = t.GetFailureHandlingOptions()
handler = JoinFailureAdvancedHandler()
joinFailOp.SetFailuresPreprocessor(handler)
t.SetFailureHandlingOptions(joinFailOp)
.
.
.
#Join Operation
.
.
.
t.Commit()

the join operation code has been tested and it works… But what it doesnt work is the handler for the joining operation.

Does anyone has any idea of what is wrong with my code?
Thank you !

Do you guys have any thoughts about this ?
Thanks
@jacob.small
@Kulkul
@john_pierson
@Dimitar_Venkov

hello @ramoon.bandeira
you are missing the instance of the class on the method (self), suddenly a parameter is missing from the PreprocessFailures fonction (method)

2 examples of classes with a double wall creation

class DuplicateMarkSwallower(IFailuresPreprocessor):
	def PreprocessFailures(self, a):
		failures = a.GetFailureMessages()
		for  f in failures:
			id = f.GetFailureDefinitionId()
			if BuiltInFailures.OverlapFailures.WallsOverlap == id:
				a.DeleteWarning(f)	
		return FailureProcessingResult.Continue
		
class CreateFailureAdvancedHandler(IFailuresPreprocessor):
	def PreprocessFailures(self, failuresAccessor):
		failMessages = failuresAccessor.GetFailureMessages()
		if failMessages.Count == 0:
			return FailureProcessingResult.Continue
		transName = failuresAccessor.GetTransactionName()
		if transName == "Wall Create Operation":
			if failuresAccessor.GetSeverity() == FailureSeverity.Warning:
				for currentMessage in failMessages:
					failuresAccessor.DeleteWarning(currentMessage)	
		return FailureProcessingResult.Continue

level = UnwrapElement(IN[1])	
TransactionManager.Instance.ForceCloseTransaction()
with Transaction(doc) as t:
	t.Start("Wall Create Operation")
	failureOptions = t.GetFailureHandlingOptions()
	failureOptions.SetFailuresPreprocessor(CreateFailureAdvancedHandler())
	#OR exemple with GetFailureDefinitionId()
	#failureOptions.SetFailuresPreprocessor(DuplicateMarkSwallower())
	t.SetFailureHandlingOptions(failureOptions)
	#
	#
	line = Line.CreateBound(XYZ.Zero, 10 * XYZ.BasisX)
	for i in range(0,2):
		wall = Wall.Create(doc, line, level.Id, False)
	#
	#
	t.Commit()
4 Likes

Oh my god… i have no words to describe how thankfull i am for this.

This was driving me nuts. And as always… it was such a simple thing!

Thanks a lot man!!!

1 Like

Hi Cyril!
Just tried that code in Dynamo CPython3 Mode. It hangs on failureOptions.SetFailuresPreprocessor(CreateFailureAdvancedHandler())

The exception seems to indicate that CreateFailureAdvancedHandler() needs an argument to function. Works just fine in IronPython2 without one. Any idea on how to make it work in CPython3?

Still, got some practice with Objects in Python. Silver lining.

Would need to see the error itself, but you may need to define the namespace for the class.

Unfortunately, this workaround work one time per Revit session

you can get around this by importing uuid, and generate a unique guid for each run. Not ideal, but it works.

1 Like

Thanks, I’ll have a look.

I imagine using the code above in Python 3 would reproduce the error in any environment.
The exception was “Class needs exactly 1 argument” or something like that.

Not at my cpu so I can’t test, but see if the above resolves things for you.

it works, but becomes unstable when there are too many calls (Memory increased and Revit crash)

this may be solved with PythonNet 3x, alternately we can use IronPython3 engine

Can’t say I have seen such an issue - I’m pretty sure I have utilized the same graph with the uuid call for over 4 hours of development lasting upwards of 200 times while authoring without any problems.

interesting, I will redo a test of loading families with IFamilyOptions interface

1 Like

It’s frustrated to see that this might be again a Pythonversion problem (related to CPython3) .

@c.poupin @jacob.small Thx for all your constructive sharing of experience for this topic.
Is there any new from your sides to handle this “interface takes exactly one argument.” problem :).

Adding a “namespace” indeed only works once per Revit, which is really annoying when I need to handle multiple .rvt (doc)

Use a randomly generated GUID for each run, and in my experience the code runs consistently and repeatedly with that change.

2 Likes