The enhanced API interface¶
This page gives a good introduction in how to get started with the core functionality that is provided by ltapy.
Before you begin, make sure that ltapy is installed properly on your system.
To use the Python interface to the LightTools API you first have to create a connection to LightTools.
Connection capabilities¶
Connecting to a LightTools session is simple. The Session
object enables you to connect either to a
running LightTools session or to start a new instance of LightTools
and connect to that session:
>>> import ltapy.session
>>> ses = ltapy.session.Session(pid=4711)
>>> lt = ses.lt
The above, connects Python with a running LightTools session that has the given process ID (PID). If no PID is given, a connection to an arbitrary LightTools session will be established.
You can start a new instance of LightTools and connect to that session by specifying the version string of the desired LightTools version. This requires, of course, that the wanted version of LightTools is installed on your system:
>>> import ltapy.session
>>> ses = ltapy.session.Session.new(version="8.5.0")
>>> lt = ses.lt
In either case you have now an enhanced LightTools API object called
lt
:
>>> lt
<win32com.gen_py.LightTools 4.0 Type Library.ILTAPI4 instance at 0x137756456>
In addition to the standard LightTools API functions, the enhanced LightTools API object provides automatic error handling and an advanced DbList() interface.
Automatic error handling¶
Most LightTools API functions return a status code to indicate wether the LightTools command completed successfully or not. If the command was executed without error, the returned value is zero, or otherwise, greater than zero if an error occured.
The following code example could be from an appliation such as Visual Basic (VB), using the standard LightTools API. The database access in the highlighted line results in an error (indicated by the non-zero status code) because there is a typo in the given data access key:
>>> logfile = lt.DbGet("LENS_MANAGER[1]", "LogFileName", status)
>>> Debug.Print(status)
0
>>> logfile = lt.DbGet("LENS_MANAGER[1]", "LoggFileName", status)
>>> Debug.Print(status)
33
If you want to make sure that your program is working correctly you would have to check the return status of each LightTools command that gets executed within your program. This might be reasonable for small scripts but is, for sure, a tedious and error prone task for larger programs with many API function calls.
To overcome this issue, the Python interface to the LightTools API provides builtin, automatic error handling:
>>> logfile = lt.DbGet("LENS_MANAGER[1]", "LoggFileName")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "E:\Repos\ltapy\ltapy\_ltapi.py", line 199, in wrapper
return _process_return_value(lt, func_name, return_value)
File "E:\Repos\ltapy\ltapy\_ltapi.py", line 261, in _process_return_value
raise error.APIError(lt, status)
ltapy.error.APIError: [33] ltStatusInvalidFunctionString:
As before, the API function call did not succeed. But this time a
custom APIError
exception is raised
and notifys you that something went wrong. This feature eliminates the
need to check the return status of LightTools API function calls and
ensures that errors never can pass silently.
Note
The Python interface does not use the status
parameter, that
is required by corresponding LightTools API functions. The
status
parameter has a default value of 0
and must not be
provided by you.
Advanced DbList() interface¶
You can access the LightTools database via the corresponding data
access functions. The DbList
function together with the API
functions that operate on the object list (e.g. ListAtPos()
,
ListNext()
, ListSize()
, …) play a central role when you want
to loop and scan through the LightTools database.
For example, this is how you get the names of all existing solids using the above mentioned data access functions:
>>> objlist = lt.DbList("COMPONENTS[1]", "SOLID")
>>> objsize = lt.ListSize(objlist)
>>> for i in range(objsize):
... objkey = lt.ListNext(objlist)
... objname = lt.DbGet(objkey, "NAME")
... print(objname)
Cube_1
Sphere_2
Ellipsoid_3
Toroid_4
Cylinder_5
With the above code, you can get your job done. But there are some drawbacks that make things unnecessary complicated:
- You have to remember all the names of the API functions that operate
on the object list (e.g.
ListAtPos()
,ListNext()
,ListSize()
, …). - The code is verbose, i.e. you have to write a lot of boilerplate code just to get a small task done (like looping through all the solids in the database).
- The object list does not support direct iteration. You have to loop
manually through the list items by using the
range
function.
To overcome these issues, ltapy provides an advanced DbList
object. It offers a simpler and more “pythonic” interface to the
object list. Looping through the LightTools database gets as simple as
that:
>>> for solid in lt.DbList("COMPONENTS[1]", "SOLID"):
... name = lt.DbGet(solid, "NAME")
... print(name)
Cube_1
Sphere_2
Ellipsoid_3
Toroid_4
Cylinder_5
Nice, right? The advanced DbList
object is essentially a wrapper
object that replaces the original DbList
function. It provides
some new functionality which is described in the following:
As seen above, you create an object list with the (wrapped) DbList
API function:
>>> solids = lt.DbList("COMPONENTS[1]", "SOLID")
The value of the DbList
object is still the (encrypted) key to the
object list. This ensures backward compatiblity to API functions that
operate on the object list:
>>> solids
'@TP100039'
If you need more information you can print the contents of the object list:
>>> solids.show()
Data Key: COMPONENTS[1]
Filter: SOLID
List Key: @TP100039
List Items: 5 items, 0 to 4
0 @Qs100034 Cube_1
1 @Dh100035 Sphere_2
2 @db100036 Ellipsoid_3
3 @KG100037 Toroid_4
4 @Fn100038 Cylinder_5
The builtin len
function returns the size of the object list:
>>> len(solids)
5
The key feature is that the DbList
object now supports direct
iteration over the items of the object list:
>>> for solid in solids:
... print(solid)
@Qs100034
@Dh100035
@db100036
@KG100037
@Fn100038
You can conveniently access individual list elements via square
bracket notation. integer
, sclice
or string
are valid list
indices:
>>> solids[0]
'@Qs100034'
>>> solids[-1]
'@Fn100038'
>>> solids["Sphere_2"]
'@Dh100035'
>>> solids[1:]
['@Dh100035', '@db100036', '@KG100037', '@Fn100038']
Membership testing is also supported:
>>> "Toroid_4" in solids
True
As you have seen, the DbList
object provides an improved interface
to LightTools object lists and its related API functions. The whole
functionality for data access is implemented iternally which allows
you to use the object in the same way as a builtin Python container
type object.
Note
Backward compatibility to the original LightTools API functions is
given. This means that you can still pass the DbList
object to
API functions that require an object list key as input argument.