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

Revert "Apply pep8 on _memberspec.py" #409

Merged
merged 1 commit into from
Dec 17, 2022
Merged
Changes from all 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
146 changes: 33 additions & 113 deletions comtypes/_memberspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,9 @@
from comtypes import TYPE_CHECKING

if TYPE_CHECKING:
from comtypes import _CData # NOQA
from comtypes import _CData
from typing import (
Any,
Callable,
Dict,
Iterator,
List,
Optional,
Tuple,
Type,
Union as _UnionT
Any, Callable, Dict, Iterator, List, Optional, Tuple, Type, Union as _UnionT
)
PositionalParamFlagType = Tuple[int, Optional[str]]
OptionalParamFlagType = Tuple[int, Optional[str], Any]
Expand Down Expand Up @@ -48,11 +40,9 @@ def _unpack_argspec(idl, typ, name=None, defval=_NOTHING):

def _resolve_argspec(items):
# type: (Tuple[ArgSpecElmType, ...]) -> Tuple[Tuple[ParamFlagType, ...], Tuple[Type[_CData], ...]]
"""
Unpacks and converts from argspec to paramflags and argtypes.
"""Unpacks and converts from argspec to paramflags and argtypes.

- paramflags is a sequence of
`(pflags: int, argname: str, | None[, defval: Any])`.
- paramflags is a sequence of `(pflags: int, argname: str, | None[, defval: Any])`.
- argtypes is a sequence of `type[_CData]`.
"""
from comtypes.automation import VARIANT
Expand All @@ -69,8 +59,7 @@ def _resolve_argspec(items):
elif typ is ctypes.POINTER(VARIANT):
defval = ctypes.pointer(VARIANT.missing)
else:
# msg = ("'optional' only allowed for VARIANT and
# VARIANT*, not for %s" % typ.__name__)
# msg = ("'optional' only allowed for VARIANT and VARIANT*, not for %s" % typ.__name__)
# warnings.warn(msg, IDLWarning, stacklevel=2)
defval = typ()
if defval is _NOTHING:
Expand All @@ -84,7 +73,6 @@ def _resolve_argspec(items):
class _MemberSpec(object):
"""Specifier of a slot of method or property."""
__slots__ = ("name", "idlflags", "restype")

def __init__(self, name, idlflags, restype):
self.name = name # type: str
self.idlflags = idlflags # type: Tuple[_UnionT[str, int], ...]
Expand All @@ -110,14 +98,7 @@ def __iter__(self):
# for backward compatibility:
# A function that returns this object used to return a `tuple`.
# So it is implemented as unpackable as well.
for item in (
self.restype,
self.name,
self.argtypes,
self.paramflags,
self.idlflags,
self.doc
):
for item in (self.restype, self.name, self.argtypes, self.paramflags, self.idlflags, self.doc):
yield item


Expand All @@ -142,13 +123,7 @@ def __iter__(self):
# for backward compatibility:
# A function that returns this object used to return a `tuple`.
# So it is implemented as unpackable as well.
for item in (
self.what,
self.name,
self.idlflags,
self.restype,
self.argspec
):
for item in (self.what, self.name, self.idlflags, self.restype, self.argspec):
yield item


Expand All @@ -166,7 +141,6 @@ def _fix_inout_args(func, argtypes, paramflags):
# version is used where the bug is fixed.
SIMPLETYPE = type(ctypes.c_int)
BYREFTYPE = type(ctypes.byref(ctypes.c_int()))

def call_with_inout(self, *args, **kw):
args = list(args)
# Indexed by order in the output
Expand All @@ -181,13 +155,13 @@ def call_with_inout(self, *args, **kw):
name = info[1]
# [in, out] parameters are passed as pointers,
# this is the pointed-to type:
atyp = argtypes[i]._type_ # NOQA
atyp = argtypes[i]._type_

# Get the actual parameter, either as positional or
# keyword arg.
try:
try:
v = args[i] # NOQA
v = args[i]
except IndexError:
v = kw[name]
except KeyError:
Expand All @@ -212,7 +186,6 @@ def call_with_inout(self, *args, **kw):
else:
v = atyp.from_param(v)
assert not isinstance(v, BYREFTYPE)

outargs[outnum] = v
outnum += 1
if len(args) > i:
Expand All @@ -228,12 +201,10 @@ def call_with_inout(self, *args, **kw):
if len(outargs) == 1:
rescode = rescode.__ctypes_from_outparam__()
return rescode

rescode = list(rescode)
for outnum, o in outargs.items():
rescode[outnum] = o.__ctypes_from_outparam__()
return rescode

return call_with_inout


Expand All @@ -255,29 +226,22 @@ def add_propputref(self, name, doc, nargs, func):

def __iter__(self):
# type: () -> Iterator[Tuple[str, Optional[str], int, Optional[Callable[..., Any]], Optional[Callable[..., Any]]]]
for (
(name, doc, nargs), (fget, propput, propputref)
) in self._data.items():
for (name, doc, nargs), (fget, propput, propputref) in self._data.items():
if propput is not None and propputref is not None:
# Create a setter method that examines the argument type
# and calls 'propputref' if it is an Object (in the VB
# sense), or call 'propput' otherwise.
put, putref = propput, propputref

def put_or_putref(self, *args): # NOQA
if comtypes._is_object(args[-1]): # NOQA
def put_or_putref(self, *args):
if comtypes._is_object(args[-1]):
return putref(self, *args)

return put(self, *args)

fset = put_or_putref

elif propputref is not None:
fset = propputref
else:
fset = propput

yield (name, doc, nargs, fget, fset) # NOQA
yield (name, doc, nargs, fget, fset)


class PropertyGenerator(object):
Expand Down Expand Up @@ -312,13 +276,8 @@ def __iter__(self):
# Hm, must be a descriptor where the __get__ method
# returns a bound object having __getitem__ and
# __setitem__ methods.
prop = named_property(
"%s.%s" % (self._cls_name, name),
fget,
fset,
doc
)
yield (name, prop) # NOQA
prop = named_property("%s.%s" % (self._cls_name, name), fget, fset, doc)
yield (name, prop)

def to_propget_keys(self, m):
# type: (_MemberSpec) -> Tuple[str, Optional[str], int]
Expand Down Expand Up @@ -381,8 +340,7 @@ def __init__(self, cls_name, vtbl_offset, iid):
self._vtbl_offset = vtbl_offset
self._iid = iid
self._props = ComPropertyGenerator(cls_name)
# sequence of
# (name: str, func: Callable, raw_func: Callable, is_prop: bool)
# sequence of (name: str, func: Callable, raw_func: Callable, is_prop: bool)
self._mths = [] # type: List[Tuple[str, Callable[..., Any], Callable[..., Any], bool]]
self._member_index = 0

Expand All @@ -396,32 +354,23 @@ def add(self, m):
# If the method returns a HRESULT, we pass the interface iid,
# so that we can request error info for the interface.
iid = self._iid if m.restype == ctypes.HRESULT else None

# low level
raw_func = proto(vidx, m.name, None, iid)
# high level
func = self._fix_args(m, proto(vidx, m.name, m.paramflags, iid))

raw_func = proto(vidx, m.name, None, iid) # low level
func = self._fix_args(m, proto(vidx, m.name, m.paramflags, iid)) # high level
func.__doc__ = m.doc
func.__name__ = m.name # for pyhelp

is_prop = m.is_prop()
if is_prop:
self._props.add(m, func)

self._mths.append((m.name, func, raw_func, is_prop))
self._member_index += 1

def _fix_args(self, m, func): # NOQA
def _fix_args(self, m, func):
# type: (_ComMemberSpec, Callable[..., Any]) -> Callable[..., Any]
"""
This is a workaround. See `_fix_inout_args` docstring and comments.
"""
"""This is a workaround. See `_fix_inout_args` docstring and comments."""
if m.paramflags:
dirflags = [(p[0] & 3) for p in m.paramflags]
dirflags = [(p[0]&3) for p in m.paramflags]
if 3 in dirflags:
return _fix_inout_args(func, m.argtypes, m.paramflags)

return func

def methods(self):
Expand All @@ -435,91 +384,68 @@ class DispMemberGenerator(object):
def __init__(self, cls_name):
# type: (str) -> None
self._props = DispPropertyGenerator(cls_name)
# sequence of
# (name: str, func_or_prop: Callable | property, is_prop: bool)
# sequence of (name: str, func_or_prop: Callable | property, is_prop: bool)
self._items = [] # type: List[Tuple[str, _UnionT[Callable[..., Any], property], bool]]

def add(self, m):
# type: (_DispMemberSpec) -> None
if m.what == "DISPPROPERTY": # DISPPROPERTY
# XXX does not yet work for properties with parameters
assert not m.argspec
assert not m.argspec # XXX does not yet work for properties with parameters
is_prop = True
accessor = self._make_disp_property(m)
self._items.append((m.name, accessor, is_prop))
else: # DISPMETHOD
func = self._make_disp_method(m)
func.__name__ = m.name

is_prop = m.is_prop()
if is_prop:
self._props.add(m, func)
else:
self._items.append((m.name, func, is_prop))

def _make_disp_property(self, m): # NOQA
def _make_disp_property(self, m):
# type: (_DispMemberSpec) -> property
# XXX doc string missing in property
memid = m.memid

def fget(obj):
return obj.Invoke(memid, _invkind=2) # DISPATCH_PROPERTYGET

return obj.Invoke(memid, _invkind=2) # DISPATCH_PROPERTYGET
if "readonly" in m.idlflags:
return property(fget)

def fset(obj, value):
# Detect whether to use DISPATCH_PROPERTYPUT or
# DISPATCH_PROPERTYPUTREF
invkind = 8 if comtypes._is_object(value) else 4 # NOQA

invkind = 8 if comtypes._is_object(value) else 4
return obj.Invoke(memid, value, _invkind=invkind)

return property(fget, fset)

# Should the funcs/mths we create have restype and/or argtypes attributes?
def _make_disp_method(self, m): # NOQA
def _make_disp_method(self, m):
# type: (_DispMemberSpec) -> Callable[..., Any]
memid = m.memid
if "propget" in m.idlflags:
def getfunc(obj, *args, **kw):
# DISPATCH_PROPERTYGET
return obj.Invoke(memid, _invkind=2, *args, **kw)

return obj.Invoke(memid, _invkind=2, *args, **kw) # DISPATCH_PROPERTYGET
return getfunc

elif "propput" in m.idlflags:
def putfunc(obj, *args, **kw):
# DISPATCH_PROPERTYPUT
return obj.Invoke(memid, _invkind=4, *args, **kw)

return obj.Invoke(memid, _invkind=4, *args, **kw) # DISPATCH_PROPERTYPUT
return putfunc

elif "propputref" in m.idlflags:
def putreffunc(obj, *args, **kw):
# DISPATCH_PROPERTYPUTREF
return obj.Invoke(memid, _invkind=8, *args, **kw)

return obj.Invoke(memid, _invkind=8, *args, **kw) # DISPATCH_PROPERTYPUTREF
return putreffunc

# a first attempt to make use of the restype. Still, support for
# named arguments and default argument values should be added.
if hasattr(m.restype, "__com_interface__"):
interface = m.restype.__com_interface__ # type: ignore

def comitffunc(obj, *args, **kw):
result = obj.Invoke(memid, _invkind=1, *args, **kw)
if result is None:
return

return result.QueryInterface(interface)

return comitffunc

def func(obj, *args, **kw):
# DISPATCH_METHOD
return obj.Invoke(memid, _invkind=1, *args, **kw)

return obj.Invoke(memid, _invkind=1, *args, **kw) # DISPATCH_METHOD
return func

def items(self):
Expand All @@ -543,29 +469,24 @@ def __init__(self, name, fget, fset, instance):
def __getitem__(self, index):
if self.fget is None:
raise TypeError("unsubscriptable object")

if isinstance(index, tuple):
return self.fget(self.instance, *index)

elif index == comtypes._all_slice: # NOQA
elif index == comtypes._all_slice:
return self.fget(self.instance)

else:
return self.fget(self.instance, index)

def __call__(self, *args):
if self.fget is None:
raise TypeError("object is not callable")

return self.fget(self.instance, *args)

def __setitem__(self, index, value):
if self.fset is None:
raise TypeError("object does not support item assignment")

if isinstance(index, tuple):
self.fset(self.instance, *(index + (value,)))
elif index == comtypes._all_slice: # NOQA
elif index == comtypes._all_slice:
self.fset(self.instance, value)
else:
self.fset(self.instance, index, value)
Expand All @@ -589,7 +510,6 @@ def __init__(self, name, fget=None, fset=None, doc=None):
def __get__(self, instance, owner=None):
if instance is None:
return self

return bound_named_property(self.name, self.fget, self.fset, instance)

# Make this a data descriptor
Expand Down