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
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()
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.
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.
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.
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)
I’m struggling with implementing the IFailuresPreprocessor interface and i’m not sure what i’m missing.
i’ve reviewed this thread and the one on stackoverflow. I’m trying to transcribe this example of using the SketchEditScope class to modify a floor. For some reason this seemed to work with Revit 2024 and Dynamo 2.18, but i’ve upgraded to Revit 2024.2 and Dynamo 2.19 and i get the following error:
TypeError: No constructor matches given arguments: ()['File "<string>", line 96, in <module>\n]
I think i have the syntax for defining the class correct (?) and have included the __namespace__ attribute as recommended. I tried explicitly defining a constructor but i don’t think this makes sense for this example because there are no additional arguments.
my python code:
#------------------IMPORTS------------------
import clr
# Include these lines to access python modules
import sys
import uuid
#sys.path.append(r'C:\Users\mclough\AppData\Local\python-3.8.3-embed-amd64\Lib\site-packages') # update this path with your user data
#clr.AddReference('ProtoGeometry')
#from Autodesk.DesignScript.Geometry import PolyCurve
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.Exceptions import * # enable this for debugging
#clr.AddReference('RevitAPIUI')
#from Autodesk.Revit.UI import *
clr.AddReference('System')
from System.Collections.Generic import List
# There are namespace overlaps between ProtoGeometry and RevitNodes
# Be sure to address these discrepancies
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
#-----------------FUNCTIONS-----------------
toList = lambda x: x if isinstance(x, list) else [x]
cast = lambda x: x.ToRevitType()
def polycurve_to_CurveArray (polycurve):
#boundariesLoop = List[CurveLoop]()
boundariesLoop = CurveArray()
crvs = polycurve.Curves()
for c in crvs:
#trace.append(" found curve as a "+str(type(c)))
c_converted = c.ToRevitType()
boundariesLoop.Append(c_converted)
#trace.append(" added as a "+str(type(c_converted)))
#trace.append(" boundaries as "+str(type(boundariesLoop)))
return boundariesLoop
#-----------------CLASSES-------------------
class FailuresPreprocessor(IFailuresPreprocessor):
__namespace__ = str(uuid.uuid4())
def PreprocessFailures(self, failuresAccessor):
return FailureProcessingResult.Continue
#------------------INPUTS-------------------
#Preparing input from dynamo to revit
element = UnwrapElement(IN[0])
curves = IN[1]
result = []
trace = []
boundariesLoop = List[CurveLoop]()
#fpp = FailuresPreprocessor()
#-------------------MAIN--------------------
#Do some action in a Transaction
#outer = curves.pop(0)
#inner = curves
bl = [polycurve_to_CurveArray (c) for c in curves]
skid = element.SketchId
sketch = doc.GetElement(skid)
ses = SketchEditScope(doc, "modify-floor-curves")
if ses.IsPermitted:
ses.Start(skid)
t = Transaction(doc,"update-sketch-boundary")
t.Start()
d_elems = sketch.GetAllElements()
[doc.Delete(e) for e in d_elems]
trace.append(bl)
[doc.Create.NewModelCurveArray(b, sketch.SketchPlane) for b in bl]
t.Commit()
ses.Commit(FailuresPreprocessor())
else:
trace.append(f"SketchEditScope is not permitted")
trace.append(f"IsModifiable: {doc.IsModifiable}")
trace.append(f"IsReadOnly: {doc.IsReadOnly}")
trace.append(f"IsSketchEditingSupported: {ses.IsSketchEditingSupported}")
#------------------OUTPUT-------------------
OUT = ses, sketch, result, trace
since revit 2024.1 PythonNet bridge (PythonNet 2.5) for the CPython3 engine was compiled with NetStandard2.0 as target (in order to prepare for the transition to Net8) which broke several features of the old version of PythonNet which mainly uses the .NetFramework as support.
The integration of Pythonnet 3.0 will undoubtedly correct the problem in the future (to be checked, because the integration of PythonNet 3 does not seem easy)