Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of 'com_record' as a subclassable Python type. #2437

Merged
merged 17 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ https://mhammond.github.io/pywin32_installers.html.
Coming in build 309, as yet unreleased
--------------------------------------

* Changed the implementation of 'com_record' to a subclassable Python type (2437#, #2361, @geppi)
* Removed param `hIcon` from `win32comext.shell.ShellExecuteEx`. It was unusable since Windows Vista (#2423, @Avasam)
* Fixed `nbios.NCBStruct` packing (#2406, @Avasam)
* Restored axdebug builds on Python 3.10 (#2416, @Avasam)
* Fix for Python 3.12 interpreter crashes when accessing a COM Record field (#2415, @geppi)
* Pythonwin: Bumped Scintilla from 1.77 to 4.4.6. The full changelog can be found here: https://www.scintilla.org/ScintillaHistory.html
* Fixed `ddeclient` and `ddeserver` demos import error (#2290, @Avasam)
* The `EvtSubscribe_push` demo now actually demonstrates the callback action and the event context being filled. (#2281, @Avasam)
Expand Down
41 changes: 41 additions & 0 deletions com/win32com/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,47 @@ def Record(name, object):
)


# Registration function for com_record subclasses.
def register_record_class(cls):
"""
Register a subclass of com_record to enable creation of the represented record objects.

A subclass of com_record requires the following class attributes to be instantiable:

TLBID : The GUID of the containing TypeLibrary as a string.
MJVER : The major version number of the TypeLibrary as an integer.
MNVER : The minor version number of the TypeLibrary as an integer.
LCID : The LCID of the TypeLibrary as an integer.
GUID : The GUID of the COM Record as a string.

with GUID strings in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} notation.

To instantiate such a subclasses it has to be registered via this function.
"""
if not issubclass(cls, pythoncom.com_record):
raise TypeError("Only subclasses of 'com_record' can be registered.")
try:
TLBID = cls.TLBID
MJVER = cls.MJVER
MNVER = cls.MNVER
LCID = cls.LCID
GUID = cls.GUID
except AttributeError as e:
raise AttributeError(f"Class {cls.__name__} cannot be instantiated.") from e
try:
_ = pythoncom.GetRecordFromGuids(TLBID, MJVER, MNVER, LCID, GUID)
except Exception as e:
raise TypeError(f"Class {cls.__name__} cannot be instantiated.") from e
# Since the class can be instantiated we know that it represents a valid COM Record
# in a properly registered TypeLibrary and that it has a 'GUID' class attribute.
if cls.GUID in pythoncom.RecordClasses:
raise ValueError(
f"Record class with same GUID {cls.GUID} "
f"is already registered with name '{pythoncom.RecordClasses[cls.GUID].__name__}'."
)
pythoncom.RecordClasses[cls.GUID] = cls


############################################
# The base of all makepy generated classes
############################################
Expand Down
Loading