OKpy - Upgrading Scripts to Cpython. Revit 2025+

Hello everyone,

I’m currently trying to upgrade an OkPy script from IronPython to CPython for Revit 2025, and I’m encountering an issue. Specifically, the .Add method for adding to a list no longer works in CPython, and I’ve been struggling to figure out why.

Here’s the situation: the original script—used to create a new revision and then add it to a sheet—worked perfectly in IronPython. It appended the new revision to a list of existing revisions. However, this functionality is now broken in CPython, and I haven’t been able to resolve it.

I’ve searched online and used ChatGPT, but haven’t found a definitive solution. If anyone can shed light on this or offer a working approach in CPython, I’d really appreciate it.

I’ve tried replacing the .Add method with .append. While the script runs without errors, it doesn’t behave as expected. Instead of adding the new revision to the existing list of revisions on the sheet, it creates a new revision but replaces the current list—removing all previous revisions from the sheet, even if the “Revision Issued” box was checked in the revision manager.

Additionally, if there are any tutorials, courses, videos, or forum posts that clearly explain the differences and nuances between IronPython and CPython—especially in the context of Revit scripting—that would be extremely helpful. I’ve tried Googling, but I might not be using the right search terms.

Thanks in advance!

import clr
clr.AddReference(‘RevitAPI’)
clr.AddReference(“RevitAPIUI”)
from Autodesk.Revit.DB import*
from Autodesk.Revit.UI import*
from System.Collections.Generic import List

#The current uidoc, doc, uiapp, and app are stored in the following variables
doc = currentdoc
app = app
uidoc = uidoc
uiapp = uiapp
inputs = inputs

sheets = inputs[“MyInput1”]
revnotes = inputs[“MyInput2”]
dclissuedby = inputs[“MyInput3”]
SequenceType = inputs[“MyInput4”]
Counter = 0

##Create Transaction##
transaction = Transaction(doc)
transaction.Start(“OkPy - Sheet Revisions”)
for sheet in sheets:
sheet_number = sheet.SheetNumber
new_revision = Revision.Create(doc)
new_revision.RevisionNumberingSequenceId = SequenceType
new_revision.Description = sheet_number +" "+ revnotes
new_revision.IssuedBy = dclissuedby
revision_id_list = sheet.GetAdditionalRevisionIds()
revision_id_list.Add(new_revision.Id)
addrev = sheet.SetAdditionalRevisionIds(revision_id_list)
Counter = Counter + 1

transaction.Commit()

message = TaskDialog
mtext = str(Counter) + " Number of Sheets Revised"
message.Show(“Batch Revisions”, mtext)

1 Like

Hey there @jonny89 ! :slight_smile:

It appears that GetAdditionalRevisionIds() is returning a python “list” , which would indeed work with “append” instead of “Add” , but then isn’t the right type of argument for SetAdditionalRevisionIds().

The fix for the problem you’re having here is to convert that list into a .Net List before you start using “Add” on it , so basically doing this :

revision_id_list = sheet.GetAdditionalRevisionIds()
revision_id_netList = List[ElementId](revision_id_list)
revision_id_netList.Add(new_revision.Id)
addrev = sheet.SetAdditionalRevisionIds(revision_id_netList)

I’m very surprised by the return type of GetAdditionalRevisionIds() ! hopefully when we move to pythonnet 3 this will be more predicatable. We’re currently using pythonnet 2.5 to avoid any conflict with the version that ships with Dynamo..

Hey there @jonny89 ! just following up on this to make sure you were able to solve your issue. Cheers!

Hi, I think I’m getting a similar error but not sure how to resolve. This method works fine in Revit 23 but not Revit 25. Any help would be appreciated.

import clr
clr.AddReference(‘RevitAPI’)
from Autodesk.Revit.DB import *
clr.AddReference(‘RevitAPIUI’)
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import ObjectType, ISelectionFilter
from Autodesk.Revit.DB import ElementId, BuiltInCategory

#The current uidoc, doc, uiapp, and app are stored in the following variables

doc = currentdoc
app = app
uidoc = uidoc
uiapp = uiapp

#Define a selection filter class

class MEPSpacesSelectionFilter(ISelectionFilter):
def AllowElement(self, element):

#Ensure element has a category and check if it belongs to the MEP Spaces category

if element.Category is not None:
return element.Category.Id.IntegerValue == int(BuiltInCategory.OST_MEPSpaces)
return False

def AllowReference(self, reference, moving):
    return False

#Create an instance of the selection filter

filter = MEPSpacesSelectionFilter()

#Use the filter to pick an object

try:
sel = uidoc.Selection.PickObject(ObjectType.Element, filter, “Select MEP Spaces”)
sel_mepspace = doc.GetElement(sel.ElementId)

except Exception as e:

#Print the error message

print("Error: " + str(e))

==========    run started at 19/12/2025 15:46:59   ==========

TypeError : interface takes exactly one argument

==========    run completed at 19/12/2025 15:46:59  ==========
1 Like

Hey there @Greyboots ! :slight_smile:

this is a PythonNet 3 interface implementation thing . In Revit 2023 you had IronPython. in Revit 2025 we ship CPython3 wit hPythonNet (which is really a good engine!).

import clr
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
clr.AddReference("RevitAPIUI")
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import ObjectType, ISelectionFilter
from Autodesk.Revit.DB import ElementId, BuiltInCategory

doc = __currentdoc__
app = __app__
uidoc = __uidoc__
uiapp = __uiapp__

class MEPSpacesSelectionFilter(ISelectionFilter):
    __namespace__ = "OkPyFilters"  # Required for PythonNet 3
    
    def AllowElement(self, element):    
        if element.Category is not None:
            return element.Category.Id.IntegerValue == int(BuiltInCategory.OST_MEPSpaces)
        return False
    # Changed 'moving' to 'position' here 
    def AllowReference(self, reference, position): 
        return False

filter = MEPSpacesSelectionFilter()

try:
    sel = uidoc.Selection.PickObject(ObjectType.Element, filter, "Select MEP Spaces")
    sel_mepspace = doc.GetElement(sel.ElementId)
except Exception as e:
    print("Error: " + str(e))

The code above should be working fine !

Apologies for the delay in coming back as I’ve been working on other development. I get another error, any help would be appreciated thankyou.

Traceback (most recent call last):
Error at line 14, in
TypeError: Duplicate type name within an assembly.