Skip to content
34 changes: 20 additions & 14 deletions comtypes/test/test_typeannotator.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,20 @@ def _create_typedesc_disp_interface(self) -> typedesc.DispInterface:
itf = typedesc.DispInterface("IDispDerived", idispatch_type, guid, [], None)
ham = typedesc.DispProperty(0, "ham", BSTR_type, ["readonly"], None)
bacon = typedesc.DispMethod(
472, 1, "bacon", VARIANT_BOOL_type, ["hidden"], None
472, 1, "bacon", VARIANT_BOOL_type, ["hidden"], "bacon's \\ help"
)
bacon.add_argument(VARIANT_type, "and", ["in"], None)
bacon.add_argument(VARIANT_type, "foo", ["in"], None)
get_spam = typedesc.DispMethod(6, 2, "spam", VARIANT_type, ["propget"], None)
get_spam = typedesc.DispMethod(
6, 2, "spam", VARIANT_type, ["propget"], "spam help"
)
get_spam.add_argument(VARIANT_type, "arg1", ["in", "optional"], None)
put_spam = typedesc.DispMethod(6, 4, "spam", void_type, ["propput"], None)
put_spam = typedesc.DispMethod(
6, 4, "spam", void_type, ["propput"], "spam setter"
)
put_spam.add_argument(VARIANT_type, "arg1", ["in", "optional"], None)
put_spam.add_argument(VARIANT_type, "arg2", ["in"], None)
except_ = typedesc.DispProperty(1, "except", BSTR_type, ["readonly"], None)
except_ = typedesc.DispProperty(1, "except", BSTR_type, ["readonly"], "help")
raise_ = typedesc.DispMethod(
474, 1, "raise", VARIANT_BOOL_type, ["hidden"], None
)
Expand Down Expand Up @@ -70,11 +74,11 @@ def test_disp_interface(self):
" @property # dispprop\n"
" def ham(self) -> hints.Incomplete: ...\n"
" pass # @property # dispprop\n"
" pass # avoid using a keyword for def except(self) -> hints.Incomplete: ...\n" # noqa
" def bacon(self, *args: hints.Any, **kwargs: hints.Any) -> hints.Incomplete: ...\n" # noqa
" def _get_spam(self, arg1: hints.Incomplete = ..., /) -> hints.Incomplete: ...\n" # noqa
' pass # avoid using a keyword for def except(self) -> hints.Incomplete: """help"""; ...\n' # noqa
' def bacon(self, *args: hints.Any, **kwargs: hints.Any) -> hints.Incomplete: """bacon\'s \\\\ help"""; ...\n' # noqa
' def _get_spam(self, arg1: hints.Incomplete = ..., /) -> hints.Incomplete: """spam help"""; ...\n' # noqa
" def _set_spam(self, arg1: hints.Incomplete = ..., /, *args: hints.Unpack[tuple[hints.Incomplete]]) -> hints.Incomplete: ...\n" # noqa
" spam = hints.named_property('spam', _get_spam, _set_spam)\n"
' spam = hints.named_property(\'spam\', _get_spam, _set_spam); """spam help"""\n'
" pass # avoid using a keyword for def raise(self, foo: hints.Incomplete, bar: hints.Incomplete = ..., /) -> hints.Incomplete: ...\n" # noqa
" def _get_def(self, arg1: hints.Incomplete = ..., /) -> hints.Incomplete: ...\n" # noqa
" def _set_def(self, arg1: hints.Incomplete = ..., /, *args: hints.Unpack[tuple[hints.Incomplete]]) -> hints.Incomplete: ...\n" # noqa
Expand Down Expand Up @@ -105,13 +109,15 @@ def _create_typedesc_com_interface(self) -> typedesc.ComInterface:
2, 1610678269, "spam", HRESULT_type, ["propget"], None
)
get_ham = typedesc.ComMethod(
2, 1610678270, "ham", HRESULT_type, ["propget"], None
2, 1610678270, "ham", HRESULT_type, ["propget"], "ham help"
)
put_ham = typedesc.ComMethod(
4, 1610678270, "ham", HRESULT_type, ["propput"], None
4, 1610678270, "ham", HRESULT_type, ["propput"], "ham setter"
)
put_ham.add_argument(VARIANT_type, "arg1", ["in"], None)
bacon = typedesc.ComMethod(1, 1610678271, "bacon", HRESULT_type, [], None)
bacon = typedesc.ComMethod(
1, 1610678271, "bacon", HRESULT_type, [], "bacon's \\ help"
)
bacon.add_argument(VARIANT_type, "foo", ["in"], None)
bacon.add_argument(VARIANT_type, "or", ["in"], None)
global_ = typedesc.ComMethod(
Expand All @@ -138,10 +144,10 @@ def test_com_interface(self):
expected = (
" def _get_spam(self) -> hints.Hresult: ...\n"
" spam = hints.normal_property(_get_spam)\n"
" def _get_ham(self) -> hints.Hresult: ...\n"
' def _get_ham(self) -> hints.Hresult: """ham help"""; ...\n'
" def _set_ham(self, arg1: hints.Incomplete) -> hints.Hresult: ...\n"
" ham = hints.normal_property(_get_ham, _set_ham)\n"
" def bacon(self, *args: hints.Any, **kwargs: hints.Any) -> hints.Hresult: ...\n" # noqa
' ham = hints.normal_property(_get_ham, _set_ham); """ham help"""\n'
' def bacon(self, *args: hints.Any, **kwargs: hints.Any) -> hints.Hresult: """bacon\'s \\\\ help"""; ...\n' # noqa
" def _get_global(self) -> hints.Hresult: ...\n"
" pass # avoid using a keyword for global = hints.normal_property(_get_global)\n" # noqa
" def _get_class(self, arg1: hints.Incomplete) -> hints.Hresult: ...\n"
Expand Down
3 changes: 0 additions & 3 deletions comtypes/tools/codegenerator/codegenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from comtypes import typeinfo
from comtypes.tools import tlbparser, typedesc
from comtypes.tools.codegenerator import heads, namespaces, packing
from comtypes.tools.codegenerator.comments import ComInterfaceBodyImplCommentWriter
from comtypes.tools.codegenerator.helpers import (
ASSUME_STRINGS,
ComMethodGenerator,
Expand Down Expand Up @@ -662,8 +661,6 @@ def ComInterfaceBody(self, body: typedesc.ComInterfaceBody) -> None:
raise TypeError("what's this?")

print("]", file=ofi)
print(file=self.stream)
ComInterfaceBodyImplCommentWriter(self.stream).write(body)

def DispInterface(self, itf: typedesc.DispInterface) -> None:
self.generate(itf.get_head())
Expand Down
79 changes: 0 additions & 79 deletions comtypes/tools/codegenerator/comments.py

This file was deleted.

61 changes: 46 additions & 15 deletions comtypes/tools/codegenerator/typeannotator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class _MethodTypeDesc(Protocol):
arguments: list[tuple[Any, str, list[str], Optional[Any]]]
idlflags: list[str]
name: str
doc: Optional[str]


_T_MTD = TypeVar("_T_MTD", bound=_MethodTypeDesc)
Expand All @@ -19,6 +20,9 @@ class _MethodAnnotator(abc.ABC, Generic[_T_MTD]):
def __init__(self, method: _T_MTD) -> None:
self.method = method

def is_put_or_putref(self) -> bool:
return "propput" in self.method.idlflags or "propputref" in self.method.idlflags

@property
def inarg_specs(self) -> Sequence[tuple[Any, str, Optional[Any]]]:
index = 0
Expand Down Expand Up @@ -99,7 +103,11 @@ def _patch_dunder(self, name: str) -> None:
self._define_member(f"__iter__ = hints.to_dunder_iter({name})")

def _define_named_prop(
self, mem_name: str, getter: Optional[str] = None, setter: Optional[str] = None
self,
mem_name: str,
getter: Optional[str] = None,
setter: Optional[str] = None,
doc: Optional[str] = None,
) -> None:
if getter and setter:
content = (
Expand All @@ -113,10 +121,16 @@ def _define_named_prop(
return
if keyword.iskeyword(mem_name):
content = f"pass # avoid using a keyword for {content}"
if doc is not None:
content = f"{content}; {_to_docstr(doc)}"
self._define_member(content)

def _define_normal_prop(
self, mem_name: str, getter: Optional[str] = None, setter: Optional[str] = None
self,
mem_name: str,
getter: Optional[str] = None,
setter: Optional[str] = None,
doc: Optional[str] = None,
) -> None:
if getter and setter:
content = f"{mem_name} = hints.normal_property({getter}, {setter})"
Expand All @@ -128,6 +142,8 @@ def _define_normal_prop(
return
if keyword.iskeyword(mem_name):
content = f"pass # avoid using a keyword for {content}"
if doc is not None:
content = f"{content}; {_to_docstr(doc)}"
self._define_member(content)

def _define_member(self, content: str) -> None:
Expand All @@ -140,29 +156,33 @@ def _gen_prop_get(self, name: str, fget: _T_MTD) -> None:
getter_anno = self.to_method_annotator(fget)
self._define_member(getter_anno.getvalue(f"_get_{name}"))
if getter_anno.inarg_specs:
self._define_named_prop(name, f"_get_{name}")
self._define_named_prop(name, f"_get_{name}", doc=fget.doc)
else:
self._define_normal_prop(name, f"_get_{name}")
self._define_normal_prop(name, f"_get_{name}", doc=fget.doc)

def _gen_prop_get_put(self, name: str, fget: _T_MTD, fput: _T_MTD) -> None:
getter_anno = self.to_method_annotator(fget)
setter_anno = self.to_method_annotator(fput)
self._define_member(getter_anno.getvalue(f"_get_{name}"))
self._define_member(setter_anno.getvalue(f"_set_{name}"))
if getter_anno.inarg_specs:
self._define_named_prop(name, f"_get_{name}", f"_set_{name}")
self._define_named_prop(name, f"_get_{name}", f"_set_{name}", doc=fget.doc)
else:
self._define_normal_prop(name, f"_get_{name}", f"_set_{name}")
self._define_normal_prop(name, f"_get_{name}", f"_set_{name}", doc=fget.doc)

def _gen_prop_get_putref(self, name: str, fget: _T_MTD, fputref: _T_MTD) -> None:
getter_anno = self.to_method_annotator(fget)
setter_anno = self.to_method_annotator(fputref)
self._define_member(getter_anno.getvalue(f"_get_{name}"))
self._define_member(setter_anno.getvalue(f"_setref_{name}"))
if getter_anno.inarg_specs:
self._define_named_prop(name, f"_get_{name}", f"_setref_{name}")
self._define_named_prop(
name, f"_get_{name}", f"_setref_{name}", doc=fget.doc
)
else:
self._define_normal_prop(name, f"_get_{name}", f"_setref_{name}")
self._define_normal_prop(
name, f"_get_{name}", f"_setref_{name}", doc=fget.doc
)

def _gen_prop_get_put_putref(
self, name: str, fget: _T_MTD, fput: _T_MTD, fputref: _T_MTD
Expand All @@ -175,9 +195,9 @@ def _gen_prop_get_put_putref(
self._define_member(putref_anno.getvalue(f"_setref_{name}"))
setter = f"hints.put_or_putref(_set_{name}, _setref_{name})"
if getter_anno.inarg_specs:
self._define_named_prop(name, f"_get_{name}", setter)
self._define_named_prop(name, f"_get_{name}", setter, doc=fget.doc)
else:
self._define_normal_prop(name, f"_get_{name}", setter)
self._define_normal_prop(name, f"_get_{name}", setter, doc=fget.doc)

def _gen_prop_put(self, name: str, fput: _T_MTD) -> None:
setter_anno = self.to_method_annotator(fput)
Expand Down Expand Up @@ -234,6 +254,10 @@ def _generate_trailing_params(specs: Sequence[tuple[Any, str, Optional[Any]]]) -
return f"*args: hints.Unpack[{params}]"


def _to_docstr(doc: str) -> str:
return '"""' + doc.replace("\\", "\\\\").replace('"', '\\"') + '"""'


class ComMethodAnnotator(_MethodAnnotator[typedesc.ComMethod]):
def _iter_outarg_specs(self) -> Iterator[tuple[Any, str]]:
for typ, name, flags, _ in self.method.arguments:
Expand Down Expand Up @@ -270,7 +294,10 @@ def getvalue(self, name: str) -> str:
else:
out = "tuple[" + ", ".join(outargs) + "]"
in_ = ("self, " + ", ".join(inargs)) if inargs else "self"
content = f"def {name}({in_}) -> {out}: ..."
if self.method.doc is not None and not self.is_put_or_putref():
content = f"def {name}({in_}) -> {out}: {_to_docstr(self.method.doc)}; ..."
else:
content = f"def {name}({in_}) -> {out}: ..."
if keyword.iskeyword(name):
content = f"pass # avoid using a keyword for {content}"
return content
Expand Down Expand Up @@ -323,10 +350,11 @@ def getvalue(self, name: str) -> str:
if inargs:
inargs.append("/")
out = _to_outtype(self.method.returns)
if inargs:
content = f"def {name}(self, {', '.join(inargs)}) -> {out}: ..."
in_ = ("self, " + ", ".join(inargs)) if inargs else "self"
if self.method.doc is not None and not self.is_put_or_putref():
content = f"def {name}({in_}) -> {out}: {_to_docstr(self.method.doc)}; ..."
else:
content = f"def {name}(self) -> {out}: ..."
content = f"def {name}({in_}) -> {out}: ..."
if keyword.iskeyword(name):
content = f"pass # avoid using a keyword for {content}"
return content
Expand Down Expand Up @@ -359,7 +387,10 @@ def generate(self) -> str:
for mem in props:
out = _to_outtype(mem.typ)
decorator = "@property # dispprop"
content = f"def {mem.name}(self) -> {out}: ..."
if mem.doc is not None:
content = f"def {mem.name}(self) -> {out}: {_to_docstr(mem.doc)}; ..."
else:
content = f"def {mem.name}(self) -> {out}: ..."
if keyword.iskeyword(mem.name):
decorator = f"pass # {decorator}"
content = f"pass # avoid using a keyword for {content}"
Expand Down
2 changes: 1 addition & 1 deletion comtypes/tools/typedesc.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def add_argument(
class DispProperty:
# dispatchable COM property, parsed from typelib
def __init__(
self, dispid: int, name: str, typ: Any, idlflags: list[str], doc: Optional[Any]
self, dispid: int, name: str, typ: Any, idlflags: list[str], doc: Optional[str]
) -> None:
self.dispid = dispid
self.name = name
Expand Down
Loading