How to Enable ISelection filter in CPython3

Hello Dynamites!

Happy new year 2025

I’m facing some issues with the CPython while I’m using the Iselection filter. I have been using the same code in ironPython2 and its perfectly working fine. But there’s a challenge in CPython3 for which I would require your assistance in resolving the issues.

Error Message:
**Warning: TypeError : interface takes exactly one argument **
[’ File “”, line 48, in \n’]

Below I have attached the code & error message for reference

import clr

import sys
sys.path.append('C:\Program Files\IronPython 3.4\Lib')

clr.AddReference('System')
from System.Collections.Generic import List

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference('RevitAPI')
clr.AddReference('RevitAPIUI')

from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = uiapp.ActiveUIDocument

def tolist(obj1):
    if hasattr(obj1, "__iter__") : return obj1
    else: return [obj1]

run = IN[0]

if run:
	class DuctSelFilter(ISelectionFilter):
	    def AllowElement(self, elm):
	        if elm.Category.Name == "Ducts":
	            return True
	        else:
	            return False
	
	filter = DuctSelFilter()
	
	TransactionManager.Instance.EnsureInTransaction(doc)
	
	pick = uidoc.Selection.PickObjects(ObjectType.Element,filter, "Select Duct Elements")
	
	outputElms = []
	for elm in pick:
	    outputElms.append(doc.GetElement(elm.ElementId))

	TransactionManager.Instance.TransactionTaskDone()
	OUT = outputElms
	
else:
	OUT = "Toggle Run button"


Hi,
you have all the explanations in this post concerning your problem

cordially
christian.stan

Here is a solution (work on all Revit version except 2024)

For more information, see my blog post

import clr
import sys

clr.AddReference('System')
from System.Collections.Generic import List

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference('RevitAPI')
clr.AddReference('RevitAPIUI')

from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = uiapp.ActiveUIDocument

def tolist(obj1):
    if hasattr(obj1, "__iter__") : return obj1
    else: return [obj1]

run = IN[0]

if run:
    class Custom_SelectionElem:
        def __new__(cls, *args, **kwargs):
            cls.args = args
            # name of namespace : "CustomNameSpace" + "_" + shortUUID (8 characters)
            # IMPORTANT NOTE Each time you modify this class, you must change the namesapce name.
            cls.__namespace__ = "Custom_SelectionElem_tEfYX0DHE"
            try:
                module_type = __import__(cls.__namespace__)
                return module_type._Custom_SelectionElem(*cls.args)
            except ImportError as ex:
                print(ex)
                class _Custom_SelectionElem(ISelectionFilter):
                    __namespace__ = cls.__namespace__
                    #
                    def __init__(self, bic):
                        super().__init__()
                        self.bic = bic
                        
                    def AllowElement(self, e):
                        if e.Category.Id == ElementId(self.bic):
                            return True
                        else:
                            return False
                    def AllowReference(self, ref, point):
                        return True 
                        
                return _Custom_SelectionElem(*cls.args)
    
    filter = Custom_SelectionElem(BuiltInCategory.OST_DuctCurves)
    
    refs = uidoc.Selection.PickObjects(ObjectType.Element,filter, "Select Duct Elements")
    
    OUT = [doc.GetElement(ref) for ref in refs]
    
else:
    OUT = "Toggle Run button"
3 Likes

Got it, Thank you :+1:

1 Like

although its temporary, for the time being it helps. Thanks @c.poupin

1 Like