Skip to content

Commit

Permalink
Reserving blank lines in the generated modules (part 3 of #745). (#748)
Browse files Browse the repository at this point in the history
* Remove unused stuff in `tools.codegenerator.heads` and `tools.generator.codegenerator`.

* Small fixes for f-strings.

* Fix `E713` in `tools/codegenerator/comments.py`.
  • Loading branch information
junkmd authored Jan 18, 2025
1 parent 5a42b3a commit e868707
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 930 deletions.
195 changes: 9 additions & 186 deletions comtypes/tools/codegenerator/codegenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import comtypes
from comtypes import typeinfo
from comtypes.tools import tlbparser, typedesc
from comtypes.tools.codegenerator import namespaces, packing, typeannotator
from comtypes.tools.codegenerator import heads, namespaces, packing
from comtypes.tools.codegenerator.comments import ComInterfaceBodyImplCommentWriter
from comtypes.tools.codegenerator.helpers import (
ASSUME_STRINGS,
Expand Down Expand Up @@ -124,8 +124,8 @@ def _generate_typelib_path(self, filename):
path = self._make_relative_path(filename, comtypes.gen.__path__[0])
self.imports.add("os")
definition = (
f"os.path.normpath(\n"
f" os.path.abspath(os.path.join(os.path.dirname(__file__),\n"
"os.path.normpath(\n"
" os.path.abspath(os.path.join(os.path.dirname(__file__),\n"
f" {path!r})))"
)
self.declarations.add("typelib_path", definition)
Expand Down Expand Up @@ -214,7 +214,7 @@ def generate_wrapper_code(
print(self._make_dunder_all_part(), file=output)
print(file=output)
if tlib_mtime is not None:
print("_check_version(%r, %f)" % (version, tlib_mtime), file=output)
print(f"_check_version({version!r}, {tlib_mtime:f})", file=output)
return output.getvalue()

def generate_friendly_code(self, modname: str) -> str:
Expand Down Expand Up @@ -284,13 +284,6 @@ def need_VARIANT_imports(self, value):
if "datetime.datetime(" in text:
self.imports.add("datetime")

def _to_docstring(self, orig: str, depth: int = 1) -> str:
# increasing `depth` by one increases indentation by one
indent = " " * depth
# some chars are replaced to avoid causing a `SyntaxError`
repled = orig.replace("\\", r"\\").replace('"', r"'")
return f'{indent}"""{repled}"""'

def ArrayType(self, tp: typedesc.ArrayType) -> None:
self.generate(get_real_type(tp.typ))
self.generate(tp.typ)
Expand Down Expand Up @@ -343,88 +336,8 @@ def StructureHead(self, head: typedesc.StructureHead) -> None:
self.more.add(struct)
if head.struct.location:
self.last_item_class = False
print(f"# {head.struct.location}", file=self.stream)
basenames = [self._to_type_name(b) for b in head.struct.bases]
if basenames:
self.imports.add("comtypes", "GUID")

if not self.last_item_class:
print(file=self.stream)
print(file=self.stream)

self.last_item_class = True

method_names = [
m.name for m in head.struct.members if type(m) is typedesc.Method
]
print(
f"class {head.struct.name}({', '.join(basenames)}):",
file=self.stream,
)
print(
" _iid_ = GUID('{}') # please look up iid and fill in!",
file=self.stream,
)
if "Enum" in method_names:
print(" def __iter__(self):", file=self.stream)
print(" return self.Enum()", file=self.stream)
elif method_names == "Next Skip Reset Clone".split():
print(" def __iter__(self):", file=self.stream)
print(" return self", file=self.stream)
print(file=self.stream)
print(" def next(self):", file=self.stream)
print(" arr, fetched = self.Next(1)", file=self.stream)
print(" if fetched == 0:", file=self.stream)
print(" raise StopIteration", file=self.stream)
print(" return arr[0]", file=self.stream)

print(file=self.stream)
print(file=self.stream)

else:
methods = [m for m in head.struct.members if type(m) is typedesc.Method]

if methods:
# Hm. We cannot generate code for IUnknown...
if not self.last_item_class:
print(file=self.stream)

self.last_item_class = True
print("assert 0, 'cannot generate code for IUnknown'", file=self.stream)
print(file=self.stream)
print(file=self.stream)
print(f"class {head.struct.name}(_com_interface):", file=self.stream)
print(" pass", file=self.stream)
print(file=self.stream)
print(file=self.stream)
elif type(head.struct) == typedesc.Structure:
if not self.last_item_class:
print(file=self.stream)
print(file=self.stream)

self.last_item_class = True

print(f"class {head.struct.name}(Structure):", file=self.stream)
if hasattr(head.struct, "_recordinfo_"):
print(
f" _recordinfo_ = {head.struct._recordinfo_!r}",
file=self.stream,
)
else:
print(" pass", file=self.stream)
print(file=self.stream)
print(file=self.stream)
elif type(head.struct) == typedesc.Union:
if not self.last_item_class:
print(file=self.stream)
print(file=self.stream)

self.last_item_class = True

print(f"class {head.struct.name}(Union):", file=self.stream)
print(" pass", file=self.stream)
print(file=self.stream)
print(file=self.stream)
heads.StructureHeadWriter(self.stream).write(head, basenames)
self.names.add(head.struct.name)

def Structure(self, struct: typedesc.Structure) -> None:
Expand Down Expand Up @@ -574,19 +487,7 @@ def TypeLib(self, lib: typedesc.TypeLib) -> None:

self.last_item_class = True

print("class Library(object):", file=self.stream)
if lib.doc:
print(self._to_docstring(lib.doc), file=self.stream)

if lib.name:
print(f" name = {lib.name!r}", file=self.stream)

print(
f" _reg_typelib_ = ({lib.guid!r}, {lib.major!r}, {lib.minor!r})",
file=self.stream,
)
print(file=self.stream)
print(file=self.stream)
heads.LibraryHeadWriter(self.stream).write(lib)
self.names.add("Library")

def External(self, ext: typedesc.External) -> None:
Expand Down Expand Up @@ -640,24 +541,7 @@ def CoClass(self, coclass: typedesc.CoClass) -> None:

self.last_item_class = True

print(f"class {coclass.name}(CoClass):", file=self.stream)
if coclass.doc:
print(self._to_docstring(coclass.doc), file=self.stream)
print(f" _reg_clsid_ = GUID({coclass.clsid!r})", file=self.stream)
print(f" _idlflags_ = {coclass.idlflags}", file=self.stream)
if self.filename is not None:
print(" _typelib_path_ = typelib_path", file=self.stream)
# X print
# >> self.stream, "POINTER(%s).__ctypes_from_outparam__ = wrap" % coclass.name

libid = coclass.tlibattr.guid
wMajor, wMinor = coclass.tlibattr.wMajorVerNum, coclass.tlibattr.wMinorVerNum
print(
f" _reg_typelib_ = ({str(libid)!r}, {wMajor}, {wMinor})",
file=self.stream,
)
print(file=self.stream)
print(file=self.stream)
heads.CoClassHeadWriter(self.stream, self.filename).write(coclass)

for itf, _ in coclass.interfaces:
self.generate(itf.get_head())
Expand Down Expand Up @@ -737,16 +621,6 @@ def _is_known_interface(
return self.known_interfaces[item.name] == item.iid
return False

def _is_enuminterface(self, itf: typedesc.ComInterface) -> bool:
# Check if this is an IEnumXXX interface
if not itf.name.startswith("IEnum"):
return False
member_names = [mth.name for mth in itf.members]
for name in ("Next", "Skip", "Reset", "Clone"):
if name not in member_names:
return False
return True

def ComInterfaceHead(self, head: typedesc.ComInterfaceHead) -> None:
if head.itf.base is None:
# we don't beed to generate IUnknown
Expand All @@ -763,43 +637,7 @@ def ComInterfaceHead(self, head: typedesc.ComInterfaceHead) -> None:

self.last_item_class = True

print(f"class {head.itf.name}({basename}):", file=self.stream)
if head.itf.doc:
print(self._to_docstring(head.itf.doc), file=self.stream)

print(" _case_insensitive_ = True", file=self.stream)
print(f" _iid_ = GUID({head.itf.iid!r})", file=self.stream)
print(f" _idlflags_ = {head.itf.idlflags}", file=self.stream)

if self._is_enuminterface(head.itf):
print(file=self.stream)
print(" def __iter__(self):", file=self.stream)
print(" return self", file=self.stream)
print(file=self.stream)

print(" def __next__(self):", file=self.stream)
print(" item, fetched = self.Next(1)", file=self.stream)
print(" if fetched:", file=self.stream)
print(" return item", file=self.stream)
print(" raise StopIteration", file=self.stream)
print(file=self.stream)

print(" def __getitem__(self, index):", file=self.stream)
print(" self.Reset()", file=self.stream)
print(" self.Skip(index)", file=self.stream)
print(" item, fetched = self.Next(1)", file=self.stream)
print(" if fetched:", file=self.stream)
print(" return item", file=self.stream)
print(" raise IndexError(index)", file=self.stream)

annotations = typeannotator.ComInterfaceMembersAnnotator(head.itf).generate()
if annotations:
print(file=self.stream)
print(" if TYPE_CHECKING: # commembers", file=self.stream)
print(annotations, file=self.stream)

print(file=self.stream)
print(file=self.stream)
heads.ComInterfaceHeadWriter(self.stream).write(head, basename)

def ComInterfaceBody(self, body: typedesc.ComInterfaceBody) -> None:
# The base class must be fully generated, including the
Expand Down Expand Up @@ -843,22 +681,7 @@ def DispInterfaceHead(self, head: typedesc.DispInterfaceHead) -> None:

self.last_item_class = True

print(f"class {head.itf.name}({basename}):", file=self.stream)
if head.itf.doc:
print(self._to_docstring(head.itf.doc), file=self.stream)
print(" _case_insensitive_ = True", file=self.stream)
print(f" _iid_ = GUID({head.itf.iid!r})", file=self.stream)
print(f" _idlflags_ = {head.itf.idlflags}", file=self.stream)
print(" _methods_ = []", file=self.stream)

annotations = typeannotator.DispInterfaceMembersAnnotator(head.itf).generate()
if annotations:
print(file=self.stream)
print(" if TYPE_CHECKING: # dispmembers", file=self.stream)
print(annotations, file=self.stream)

print(file=self.stream)
print(file=self.stream)
heads.DispInterfaceHeadWriter(self.stream).write(head, basename)

def DispInterfaceBody(self, body: typedesc.DispInterfaceBody) -> None:
# make sure we can generate the body
Expand Down
2 changes: 1 addition & 1 deletion comtypes/tools/codegenerator/comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def write(self, body: typedesc.ComInterfaceBody) -> None:
# m.arguments is a sequence of tuples:
# (argtype, argname, idlflags, docstring)
# Some typelibs have unnamed method parameters!
inargs = [a[1] or "<unnamed>" for a in m.arguments if not "out" in a[2]]
inargs = [a[1] or "<unnamed>" for a in m.arguments if "out" not in a[2]]
outargs = [a[1] or "<unnamed>" for a in m.arguments if "out" in a[2]]
if "propget" in m.idlflags:
methods.setdefault(m.name, [0, inargs, outargs, m.doc])[0] |= 1
Expand Down
Loading

0 comments on commit e868707

Please sign in to comment.