"TypeError" When Trying to Get Block Table Record of Model Space

Has anyone seen this error before? All I did was add the following code to a generic python code block:

bt = t.GetObject(db.BlockTableId, OpenMode.ForWrite)
btr = t.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)

And I am getting this odd “Type Error: No Method matches given arguments for OnExit: (<class ‘Autodesk.AutoCAD.ApplicationServices.DocumentLock’>, <class ‘type’>”

I can use:

list(bt)

to see a list of blockIDs but I can’t seem to do much with them. I also get an error when I try to do something like:

modelSpace = [block for block in bt if "Model" in block.Name][0]

It seems like the error is saying there is an issue with the document lock, I have no idea why this would be an issue.

This is a goofy thing with how Python.NET handles virtual indexers. You can use this instead:

bt.get_Item(BlockTableRecord.ModelSpace)

or

bt.get_Item("*Model_Space")

4 Likes

Thanks Zachri, I knew you’d come help!

That worked great thanks! I’ll be sure to reference this going forward. But now I’m trying to iterate over the block table record. I remember previously you stated that the block table record:

When I do this:

with adoc.LockDocument():
    with adoc.Database as db:
        with db.TransactionManager.StartTransaction() as t:
            bt = t.GetObject(db.BlockTableId, OpenMode.ForWrite)
            btr = bt.get_Item(BlockTableRecord.ModelSpace)
            
            objectIDs = []
            for oid in btr:
                oid.append(objectID)

            t.Commit()
            pass

I get the exact same TypeError as previously mentioned. But this method worked fine in the last python script I wrote that replaced blocks across sheets. It’s really confusing! I was also able to iterate through the “Block Table” as if it was a list in the last script without issue. I’m not sure what has changed here except that I’m already in an active dwg.

Also, I seem to find the following code:

btr = t.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)

throughout the forum. Did this work previously but doesn’t now for some reason?

I haven’t tested, but I think your issue is here:

oid.append(objectID)

I think you want it like this instead:

objectIDs.append(oid)

Yep, most of that was probably written when things were still on IronPython, but Python.NET is a different animal. If you try that code in an earlier version of Civil 3D then it should still work.

You’re totally right that I messed up my syntax, the list should be prior to the “.”. I fixed this. However, the python script (and my dwg) actually crashes prior to even running the append step. It is crashing when attempting to iterate over the block table record.

The:

for oid in btr:

step.

This seems like very odd behavior. I am tempted to reinstall C3D. I was able to iterate across the block table and block table record just fine prior.

Okay. I see that

bt.get_Item(BlockTableRecord.ModelSpace)

or

bt.get_Item("*Model_Space")

returns an object ID, not the block table reference its self, so I have to pass that into:

t.GetObject()

This works:

with adoc.LockDocument():
    with adoc.Database as db:
        with db.TransactionManager.StartTransaction() as t:
            bt = t.GetObject(db.BlockTableId, OpenMode.ForWrite)
            btrID = bt.get_Item("*Model_Space")
            btr = t.GetObject(btrID, OpenMode.ForWrite)
            
            objectIDs = []
            for oid in btr:
                objectIDs.append(oid)

            t.Commit()
            pass

Thanks Zachri.

1 Like

Hi,

I happen to have exactly the same error, but when experimenting with adding propertysets in Civil3D.
I have used the examples and refactored them for my use case.


def create_ps_definitions_sql(set, properties, t, db):
    """Creates a property set by list input.
    """
    psdef = None
    psdefid = None
    newps = False
    dpsd = DictionaryPropertySetDefinitions(db)
    try:
        if not dpsd.Has(set[0], t):
            psdef = PropertySetDefinition()
            psdefid = psded.Id
            dpsd.AddNewRecord(set[0], psdef)
            newps = True
        else:
            psdefid = dpsd.GetAt(set[0])
            psdef = t.GetObject(psdefid, OpenMode.ForWrite)

        psdef.AppliesToAll = True
        psdef.Description = set[1]
        definitions = psdef.Definitions
        for prop in properties:
            pd = PropertyDefinition()
            pd.Automatic = False
            pd.DataType = DataType.Parse(DataType,
                    "Text", True)
            pd.DefaultData = ""
            pd.Description = prop[1]
            pd.Name = prop[0]
            if not definitions.Contains(pd):
                definitions.Add(pd)
        if newps:
            t.AddNewlyCreatedDBObject(psdef, True)
    except Exception as ex:
        MessageBox.Show('Create Property Set\r\n{}'.format(ex))
                
# run script

dataEnteringNode = IN

adoc = acapp.DocumentManager.MdiActiveDocument
    
with adoc.LockDocument():
    with adoc.Database as db:

        with db.TransactionManager.StartTransaction() as t:
            for combo in dataEnteringNode:
                create_ps_definitions_sql(combo[0], combo[1], t, db)
            t.Commit()
            pass

OUT = None

I know the code is definitely not yet optimal, but first I wanted to get it running and get rid of that error before implementing more functionality.

Have you got any idea what might go wrong?

thanks in advance

You’re calling indexers pretty often in the code, so it could be any of those. Try replacing those per the post above.

1 Like