diff --git a/comtypes/_post_coinit/unknwn.py b/comtypes/_post_coinit/unknwn.py index 00624a46..84cc48c7 100644 --- a/comtypes/_post_coinit/unknwn.py +++ b/comtypes/_post_coinit/unknwn.py @@ -101,41 +101,40 @@ def __new__(cls, name, bases, namespace): _pointer_type_cache[new_cls] = p if new_cls._case_insensitive_: - new_cls._patch_to_ptr_type(p, True) - else: - new_cls._patch_to_ptr_type(p, False) + new_cls._patch_case_insensitive_to_ptr_type(p) + new_cls._patch_reference_fix_to_ptrptr_type(p) return new_cls @staticmethod - def _patch_to_ptr_type(p, case_insensitive) -> None: - if case_insensitive: - - @patcher.Patch(p) - class CaseInsensitive(object): - # case insensitive attributes for COM methods and properties - def __getattr__(self, name): - """Implement case insensitive access to methods and properties""" - try: - fixed_name = self.__map_case__[name.lower()] - except KeyError: - raise AttributeError(name) - if fixed_name != name: # prevent unbounded recursion - return getattr(self, fixed_name) - raise AttributeError(name) - - # __setattr__ is pretty heavy-weight, because it is called for - # EVERY attribute assignment. Settings a non-com attribute - # through this function takes 8.6 usec, while without this - # function it takes 0.7 sec - 12 times slower. - # - # How much faster would this be if implemented in C? - def __setattr__(self, name, value): - """Implement case insensitive access to methods and properties""" - object.__setattr__( - self, self.__map_case__.get(name.lower(), name), value - ) + def _patch_case_insensitive_to_ptr_type(p: Type) -> None: + @patcher.Patch(p) + class CaseInsensitive(object): + # case insensitive attributes for COM methods and properties + def __getattr__(self, name): + """Implement case insensitive access to methods and properties""" + try: + fixed_name = self.__map_case__[name.lower()] + except KeyError: + raise AttributeError(name) # Should we use exception-chaining? + if fixed_name != name: # prevent unbounded recursion + return getattr(self, fixed_name) + raise AttributeError(name) + + # __setattr__ is pretty heavy-weight, because it is called for + # EVERY attribute assignment. Settings a non-com attribute + # through this function takes 8.6 usec, while without this + # function it takes 0.7 sec - 12 times slower. + # + # How much faster would this be if implemented in C? + def __setattr__(self, name, value): + """Implement case insensitive access to methods and properties""" + object.__setattr__( + self, self.__map_case__.get(name.lower(), name), value + ) + @staticmethod + def _patch_reference_fix_to_ptrptr_type(p: Type) -> None: @patcher.Patch(POINTER(p)) class ReferenceFix(object): def __setitem__(self, index, value): @@ -158,11 +157,11 @@ def __setitem__(self, index, value): # CopyComPointer should do if index != 0. if bool(value): value.AddRef() - super(POINTER(p), self).__setitem__(index, value) + super(POINTER(p), self).__setitem__(index, value) # type: ignore return from _ctypes import CopyComPointer - CopyComPointer(value, self) + CopyComPointer(value, self) # type: ignore def __setattr__(self, name, value): if name == "_methods_":