CATIA V5 Automation with Python Script - python

I'm a Python beginner and am attempting to do some automation in CATIA (Dassault Systemes CAD pacakge) with it, but I've run into an issue that I've been unable to solve despite searching extensively for a solution.
I'm trying to mimic the behavior of this VBA macro that was written within CATIAs native editor interface:
Sub CATMain()
Dim drawingDocument1 As DrawingDocument
Set drawingDocument1 = CATIA.ActiveDocument
Dim selection1 As Selection
Set selection1 = drawingDocument1.Selection
selection1.Search "CATDrwSearch.DrwDimension,all"
For i = 1 To selection1.Count
Dim Dimension1 As DrawingDimension
Set Dimension1 = selection1.Item(i).Value
Dim DimDimValue As DrawingDimValue
Set DimDimValue = Dimension1.GetValue
DimDimValue.SetFormatPrecision 1, 0.001
Next
selection1.Clear
End Sub
To do so I wrote this Python script:
import win32com.client
CATIA = win32com.client.Dispatch('CATIA.Application')
ad = CATIA.ActiveDocument
sel = ad.Selection
sel.Search("CATDrwSearch.DrwDimension,all")
for i in range(1, sel.Count2+1):
aDim = sel.Item2(i).Value
aDimValue = aDim.GetValue
aDimValue.SetFormatPrecision(1,0.001)
sel.Clear
Everything works except for the last operation within the for loop which returns the error:
Traceback (most recent call last):
<bound method DrawingDimension.GetValue of <win32com.gen_py.CATIA V5
DraftingInterfaces Object Library.DrawingDimension instance at 0x67582896>>
File "C:/...", line 15, in <module>
aDimValue.SetFormatPrecision(1,0.001)
AttributeError: 'function' object has no attribute 'SetFormatPrecision'
Note that I used makepy to early bind the COM object otherwise Python doesn't recognize it (returns COMObject [unknown]), but from what I understand that shouldn't impact the script behavior.
I haven't been able to troubleshoot the error successfully because everything I can find suggests the object should have the attribute SetFormatPrecision. I've tried a bunch of other attributes that it should have as well, and none of them work. Because I'm trying to operate on a COM object, I'm not aware of a way to get a comprehensive list of legal attributes, or a way to get any information on the type of object I have stored in aDimValue
I inspected the makepy output file and it does include a function definition for SetFormatPrecision so my guess is I have a syntax issue, but I'm at a loss for what it is.
I know it's a narrowly focused question, but I'm hoping somebody with knowledge of CATIA Object Libraries sees this. And although I don't expect it, if somebody wants to go the extra mile, there's documentation on CATIAs Object Libraries here:
http://catiadoc.free.fr/online/CAAScdBase/CAAScdAutomationHome.htm
Drafting > Drafting Reference > DrawingDimValue
to get to the specific object I think I'm working with in aDimValue
Any help is appreciated. Thanks.

aDim.GetValue returns the function object, rather than calling the function. Use aDim.GetValue(). Same with sel.Clear() on the last line.

Related

How to create and use objects from the Inventor COM API in python (pywin32)

I'm attempting to use Autodesk Inventor's COM API to create a python script that will generate PDFs of a selection on Inventor Drawings, these PDFs will then be processed in particular ways that aren't important to my question. I'm using pywin32 to access the COM API, but I'm not particularly familiar with how COM APIs are used, and the pywin32 module.
This is the extent of the documentation for Inventor's API that I have been able to find (diagram of API Object Model Reference Document), and I have not been able to find documentation for the individual objects listed. As such, I'm basing my understanding of the use of these objects on what I can find from examples online (all in VB or iLogic - Inventor's own simple built-in language).
A big issue I'm coming up against is in creating the objects I'd like to use. Simplified example below:
from win32com.client import *
# user chooses file paths for open and save here...
drawing_filepath = ""
# Open Inventor application, and set visible (so I can tell it's opened for now)
app = Dispatch('Inventor.Application')
app.Visible = True
# Open the file to be saved as a pdf (returns a Document object)
app.Documents.Open(drawing_filepath)
# Cast the opened Document object to a DrawingDocument object (it is guaranteed to be a drawing)
drawing = CastTo(app.ActiveDocument, "DrawingDocument")
# Create and setup a print manager (so can use "Adobe PDF" printer to convert the drawings to PDF)
print_manager = ??? # How can I create this object
# I've tried:
# print_manager = Dispatch("Inventor.Application.Documents.DrawingDocument.DrawingPrintManager") #"Invalid class string"
# print_manager = drawing.DrawingPrintManager() #"object has no attribute 'DrawingPrintManger'
# print_manager = drawing.DrawingPrintManager # same as above
# print_manager = drawing.PrintManger # worked in the end
print_manager.Printer = "Adobe PDF"
print_manager.NumberOfCopies = 1
print_manager.ScaleMode = print_manager.PrintScaleModeEnum.kPrintFullScale
print_manager.PaperSize = print_manager.PrintSizeEnum.kPaperSizeA3
# Print PDF
print_manager.SubmitPrint()
So I can't figure out how to create a DrawingPrintManager to use! You can see I've avoided this issue when creating my DrawingDocument object, as I just happened to know that there is an ActiveDocument attribute that I can get from the application itself.
I also:
don't know what the full list of attributes and methods for DrawingPrintManager are, so I don't know how to set a save location
don't know for sure that the two Enums I'm trying to use are actually defined within DrawingPrintManager, but I can figure that out once I actually have a DrawingPrintManager to work with
If anyone with more experience in using COM APIs or pywin32 can help me out, I'd be really appreciative. And the same if anyone can point me towards any actual documentation of Inventor's API Objects, which would make things a lot easier.
Thanks
Edit: After posting I've almost immediately found that I can get a PrintManager (can't tell if a PrintManager or DrawingPrintManager) by accessing drawing.PrintManager rather than drawing.DrawingPrintManager.
This is a workaround however as it doesn't answer my question of how to create objects within pywin32.
My problem moving forward is finding where I can access the PrintScaleModeEnum and PrintSizeEnum objects, and finding how to set the save location of the printed PDF (which I think will be a a separate question, as it's probably unrelated to the COM API).
I'm not familiar with python and pywin32, but I try to answer your questions.
Documentation of Inventor API is available in local installation "C:\Users\Public\Documents\Autodesk\Inventor 2020\Local Help" or online https://help.autodesk.com/view/INVNTOR/2020/ENU/
Generaly you are not able to create new instances of Inventor API objects. You must obtain them as a result of appropriate method or property value.
For example:
You CAN'T do this
doc = new Inventor.Document()
You MUST do this
doc = app.Documents.Add(...)
With print manager is this
print_manager = drawing.PrintManger
# this returns object of type Inventor.DrawingPrintManager
# when drawing is of type Inventor.DrawingDocument
See this for more details

Gurobi Python Error (NoneType has no len())

I need to write an optimization file for Gurobi (Python) that is a modified version of a classic TSP. I tried to run the example file from their website:
examples.gurobi.com/traveling-salesman-problem/
I always get the following error:
TypeError: object of type 'NoneType' has no len()
What do I need to change?
Thx
Full code: https://www.dropbox.com/s/ewisx805b3o2wq5/beispiel_opt.py?dl=0
I can confirm the error with the example code from Gurobi's website. At the first look the problem seems to be inside the subtour function, that returns None if sum(lengths) == n and the missing check for if tour is None inside the subtourlim function.
Instead of providing a fix for the specific code, I first checked the examples that Gurobi installs inside the specific installation directory:
Mac: /Library/gurobi810/mac64/examples/python/
Linux: /opt/gurobi800/linux64/examples/python/
Windows: c:\gurobi800\win64\examples\python\
And surprisingly the tsp.py from there runs without any errors. Note also that the two mentioned functions are revised. So I guess the example from the website is just a old version of the code.

comtypes: in call_with_inout, ctypes TypeError: 'c_double' object is not iterable

Im working with Agilent IVI drivers in Python 2.7.9 and can't seem to get 'proven' code to work on a particular Windows 7 machine. It executes successfully on other machines.
While this issue seems rather limited to one instrument, it appears to be a broader Python issue, so I turn to Stack Overflow for help. Any help or insight would be great.
The following code
# Import the TLB
from comtypes.client import GetModule, CreateObject
GetModule('AgInfiniium.dll')
# Pull in the coefficients and classes, we'll need those
from comtypes.gen.AgilentInfiniiumLib import *
# Instantiate the driver
OScope = CreateObject('AgilentInfiniium.AgilentInfiniium')
# Make constants of our settings
Address = "TCPIP0::10.254.0.222::INSTR"
resetOScope = False
# Open a connection to the scope
OScope.Initialize(Address,False,resetOScope,'')
# Make a measurement
print OScope.Measurements.Item("Channel1").ReadWaveformMeasurement(
MeasFunction=AgilentInfiniiumMeasurementAmplitude, MaxTime=10)
yields the following error:
Traceback (most recent call last):
File "P:\Aperture\Validation\WMI_BGA_Board\TestMatrixCode\scopeTest2.py", line 29, in <module>
print OScope.Measurements.Item("Channel1").ReadWaveformMeasurement(MeasFunction=AgilentInfiniiumMeasurementAmplitude ,MaxTime=10)
File "C:\Python27\lib\site-packages\comtypes-1.1.0-py2.7.egg\comtypes\__init__.py", line 656, in call_with_inout
rescode = list(rescode)
TypeError: 'c_double' object is not iterable
In my limited debugging attempts, I have seen that this call_with_inout
function tries to convert my Python arguments into arguments for the following C++ function:
public void ReadWaveformMeasurement(
AgilentInfiniiumMeasurementEnum MeasFunction,
AgilentInfiniiumTimeOutEnum MaxTime,
ref double pMeasurement)
It's creating some kind of variable for the pMeasurement pointer that ends up being type c_double, and then complains that it's not iterable.
At this point, this seems like it's local to this machine. I've gone to the extent of uninstalling Python, reinstalling the Agilent driver, and trying two versions of comtypes (1.1.0 and 1.1.1). Yet the problem persists. Any ideas? Thanks.

Google Spreadsheets API: 'SpreadsheetsClient' object has no attribute 'update_cell'

For some reason, when I'm trying to update one cell using the Google Spreadsheets API in Python, like so:
import gdata.spreadsheets.client
import gdata.gauth
gd_client = gdata.spreadsheets.client.SpreadsheetsClient()
gd_client.auth_token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
wksht_id = od6
gd_client.update_cell(spreadsheet_k, wksht_id, 3, 17, 'TEST')
I get this error:
AttributeError: 'SpreadsheetsClient' object has no attribute 'update_cell'
Even though in the source code for client.py, update_cell is very clearly a method for the SpreadsheetsClient class: https://code.google.com/p/gdata-python-client/source/browse/src/gdata/spreadsheets/client.py
This cell has something in it, if that makes any difference. But that's not where the error is coming from. I just have no idea why this isn't working. Maybe something to do with different versions of the API?
What am I not seeing?
Figured it out! Turns out the source code was updated with the update_cell method but the gdata downloads were never given this method for some reason. You have to go to the source code and copy the method over to your own copy of gdata, or use this workaround: https://gist.github.com/egor83/4634422

Loading a document on OpenOffice using an external Python program

I'm trying to create a python program (using pyUNO ) to make some changes on a OpenOffice calc sheet.
I've launched previously OpenOffice on "accept" mode to be able to connect from an external program. Apparently, should be as easy as:
import uno
# get the uno component context from the PyUNO runtime
localContext = uno.getComponentContext()
# create the UnoUrlResolver
resolver = localContext.ServiceManager.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext)
# connect to the running office
ctx = resolver.resolve("uno:socket,host=localhost,port=2002;"
"urp;StarOffice.ComponentContext")
smgr = ctx.ServiceManager
# get the central desktop object
DESKTOP =smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
#The calling it's not exactly this way, just to simplify the code
DESKTOP.loadComponentFromURL('file.ods')
But I get an AttributeError when I try to access loadComponentFromURL. If I make a dir(DESKTOP), I've see only the following attributes/methods:
['ActiveFrame', 'DispatchRecorderSupplier', 'ImplementationId', 'ImplementationName',
'IsPlugged', 'PropertySetInfo', 'SupportedServiceNames', 'SuspendQuickstartVeto',
'Title', 'Types', 'addEventListener', 'addPropertyChangeListener',
'addVetoableChangeListener', 'dispose', 'disposing', 'getImplementationId',
'getImplementationName', 'getPropertySetInfo', 'getPropertyValue',
'getSupportedServiceNames', 'getTypes', 'handle', 'queryInterface',
'removeEventListener', 'removePropertyChangeListener', 'removeVetoableChangeListener',
'setPropertyValue', 'supportsService']
I've read that there are where a bug doing the same, but on OpenOffice 3.0 (I'm using OpenOffice 3.1 over Red Hat5.3). I've tried to use the workaround stated here, but they don't seems to be working.
Any ideas?
It has been a long time since I did anything with PyUNO, but looking at the code that worked last time I ran it back in '06, I did my load document like this:
def urlify(path):
return uno.systemPathToFileUrl(os.path.realpath(path))
desktop.loadComponentFromURL(
urlify(tempfilename), "_blank", 0, ())
Your example is a simplified version, and I'm not sure if you've removed the extra arguments intentionally or not intentionally.
If loadComponentFromURL isn't there, then the API has changed or there's something else wrong, I've read through your code and it looks like you're doing all the same things I have.
I don't believe that the dir() of the methods on the desktop object will be useful, as I think there's a __getattr__ method being used to proxy through the requests, and all the methods you've printed out are utility methods used for the stand-in object for the com.sun.star.frame.Desktop.
I think perhaps the failure could be that there's no method named loadComponentFromURL that has exactly 1 argument. Perhaps giving the 4 argument version will result in the method being found and used. This could simply be an impedance mismatch between Python and Java, where Java has call-signature method overloading.
This looks like issue 90701: http://www.openoffice.org/issues/show_bug.cgi?id=90701
See also http://piiis.blogspot.com/2008/10/pyuno-broken-in-ooo-30-with-system.html and http://udk.openoffice.org/python/python-bridge.html

Categories