Skip to content

Commit 6be7e46

Browse files
Add __call__ to CxxWrapper
1 parent 533ab95 commit 6be7e46

2 files changed

Lines changed: 47 additions & 12 deletions

File tree

src/libsemigroups_pybind11/detail/cxx_wrapper.py

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,21 @@ def __init__(
6666
optional_kwargs=(),
6767
**kwargs,
6868
) -> None:
69-
if len(args) == 1 and len(kwargs) == 0 and type(args[0]) in self._all_wrapped_cxx_types:
69+
if (
70+
len(args) == 1
71+
and len(kwargs) == 0
72+
and type(args[0]) in self._all_wrapped_cxx_types
73+
):
7074
# Copy constructor like construction directly from cxx object
7175
self._cxx_obj = args[0]
7276
self.py_template_params = self.py_template_params_from_cxx_obj()
7377
return
7478

75-
if not len(required_kwargs) <= len(kwargs) <= len(required_kwargs) + len(optional_kwargs):
79+
if (
80+
not len(required_kwargs)
81+
<= len(kwargs)
82+
<= len(required_kwargs) + len(optional_kwargs)
83+
):
7684
raise TypeError(
7785
f"expected between {len(required_kwargs)} and "
7886
f"{len(required_kwargs) + len(optional_kwargs)} "
@@ -111,7 +119,9 @@ def __getattr__(self: Self, name: str):
111119
def cxx_fn_wrapper(*args) -> Any:
112120
if len(args) == 1 and isinstance(args[0], list):
113121
args = args[0]
114-
return getattr(self._cxx_obj, name)([to_cxx(x) for x in args])
122+
return getattr(self._cxx_obj, name)(
123+
[to_cxx(x) for x in args]
124+
)
115125
return getattr(self._cxx_obj, name)(*(to_cxx(x) for x in args))
116126

117127
return cxx_fn_wrapper
@@ -126,14 +136,27 @@ def __copy__(self: Self) -> Self:
126136
if self._cxx_obj is not None:
127137
if hasattr(self._cxx_obj, "__copy__"):
128138
return to_py(self._cxx_obj.__copy__())
129-
raise NotImplementedError(f"{type(self._cxx_obj)} has no member named __copy__")
139+
raise NotImplementedError(
140+
f"{type(self._cxx_obj)} has no member named __copy__"
141+
)
130142
raise NameError("_cxx_obj has not been defined")
131143

132-
def __eq__(self: Self, that) -> bool:
144+
def __eq__(self: Self, that: Self) -> bool:
133145
if self._cxx_obj is not None:
134146
if hasattr(self._cxx_obj, "__eq__"):
135147
return self._cxx_obj.__eq__(that._cxx_obj)
136-
raise NotImplementedError(f"{type(self._cxx_obj)} has no member named __eq__")
148+
raise NotImplementedError(
149+
f"{type(self._cxx_obj)} has no member named __eq__"
150+
)
151+
raise NameError("_cxx_obj has not been defined")
152+
153+
def __call__(self: Self, *args) -> Any:
154+
if self._cxx_obj is not None:
155+
if callable(self._cxx_obj):
156+
return self._cxx_obj.__call__(*args)
157+
raise NotImplementedError(
158+
f"{type(self._cxx_obj)} has no member named __call__"
159+
)
137160
raise NameError("_cxx_obj has not been defined")
138161

139162
def py_template_params_from_cxx_obj(self: Self) -> tuple:
@@ -152,9 +175,9 @@ def init_cxx_obj(self: Self, *args) -> None:
152175
defined.
153176
"""
154177
assert self.py_template_params is not None
155-
self._cxx_obj = self._py_template_params_to_cxx_type[self.py_template_params](
156-
*(to_cxx(x) for x in args)
157-
)
178+
self._cxx_obj = self._py_template_params_to_cxx_type[
179+
self.py_template_params
180+
](*(to_cxx(x) for x in args))
158181

159182

160183
# TODO proper annotations
@@ -170,13 +193,17 @@ def cxx_mem_fn_wrapper(self, *args):
170193
# TODO move the first if-clause into to_cxx?
171194
if len(args) == 1 and isinstance(args[0], list):
172195
args = [[to_cxx(x) for x in args[0]]]
173-
result = getattr(to_cxx(self), cxx_mem_fn.__name__)(*(to_cxx(x) for x in args))
196+
result = getattr(to_cxx(self), cxx_mem_fn.__name__)(
197+
*(to_cxx(x) for x in args)
198+
)
174199
if result is to_cxx(self):
175200
return self
176201
if type(result) in _CXX_WRAPPED_TYPE_TO_PY_TYPE:
177202
cached_val = f"_cached_return_value_{cxx_mem_fn.__name__}"
178203
# TODO use args too in cached_val?
179-
if hasattr(self, cached_val) and result is to_cxx(getattr(self, cached_val)):
204+
if hasattr(self, cached_val) and result is to_cxx(
205+
getattr(self, cached_val)
206+
):
180207
return getattr(self, cached_val)
181208
result = _CXX_WRAPPED_TYPE_TO_PY_TYPE[type(result)](result)
182209
setattr(self, cached_val, result)
@@ -210,7 +237,9 @@ def copy_cxx_mem_fns(cxx_class: pybind11_type, py_class: CxxWrapper) -> None:
210237
that call the cxx member function on the _cxx_obj.
211238
"""
212239
for py_meth_name in dir(cxx_class):
213-
if (not py_meth_name.startswith("_")) and py_meth_name not in dir(py_class):
240+
if (not py_meth_name.startswith("_")) and py_meth_name not in dir(
241+
py_class
242+
):
214243
setattr(
215244
py_class,
216245
py_meth_name,

tests/test_sims.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,12 @@ def test_sims_refiner_faithful_return_policy():
597597
assert srf.init([[0, 1], [0]]) is srf
598598

599599

600+
def test_sims_refiner_faithful_call():
601+
srf = SimsRefinerFaithful()
602+
wg = WordGraph(2, [[0, 1]])
603+
assert srf(wg)
604+
605+
600606
def test_sims_refiner_ideals_return_policy():
601607
sri = SimsRefinerIdeals()
602608
assert sri.presentation() is sri.presentation()

0 commit comments

Comments
 (0)