I am using COM Objects within python to expose programmable interfaces to 3rd party software. This is achieved through using Dispatch
from win32com.client
. My project has also been making use of type hinting from python.3.7, however I am unsure as to how you would define the type of these COM objects for the purposes of type hinting. The question relates to all the COM objects I have, with a real example being a Microsoft Direct X Recordset: Dispatch("ADODB.Recordset")
.
from win32com.client import Dispatch
def create_my_com_object_instance(input_arg: Dict[str, Union[str, float, int]]) -> <type_of_com_object_here>:
my_instance = Dispatch("ADODB.Recordset")
# Set attributes/call methods of this instance here ...
return my_instance
In the above code snippet I would replace 'type_of_com_object_here' with the COM object type.
My first thought was just to call type()
on the instance and use the returned type:
x = Dispatch("ADODB.Recordset")
x
Out[1]: <win32com.gen_py.Microsoft ActiveX Data Objects 6.1 Library._Recordset instance at 0x83848456>
type(x)
Out[2]: win32com.gen_py.B691E011-1797-432E-907A-4D8C69339129x0x6x1._Recordset._Recordset
x.__class__
Out[3]: win32com.gen_py.B691E011-1797-432E-907A-4D8C69339129x0x6x1._Recordset._Recordset
This does not return a suitable type for defining the COM Object. I believe that I could create an abstract base class using TypeVar('T')
and Generic[]
, however I am unsure if there is a more pythonic/better alternative available.
Thanks
I'm afraid you're unfortunately running into one of the limits of typing in Python. In particular:
Dispatch
really does dispatch to arbitrary objects).So, I recommend one of the following three approaches:
If you want to assume absolutely nothing about the returned type and treat it as just an opaque blob, have the return type be just object
. This is the most restrictive and type safe option, since a PEP 484 compliant type checker will let the caller only use methods that are present in all Python objects, such as __str__
or __eq__
.
If you want to assume absolutely nothing about the returned type but also impose no restrictions on its use, have the return type be Any, the dynamic type. This is the most permissive and unsafe operation: you are saying the output is some dynamic type and telling the type checker to let the caller use the returned object however they please.
This is the "default option", so to speak: since there are no type stubs available for pywin32, the type checker will fall back to assuming Dispatch(...)
has a return type of Any.
If you know for certain the returned type will always have some specific methods or attributes available, you have the return type be a Protocol. Protocols basically let you do structural subtyping: any class that happens to implement the protocol methods and attributes is considered a subtype of that protocol, even if the class isn't inheriting from the protocol in any way. Protocols are basically like Go's interfaces, if you're familiar with Go.
You may want to create a dedicated create_adodb_recordset(...)
function here, so you can more fully customize the return type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With