Skip to content

Commit 32f8a30

Browse files
📝 Add docstrings to claude/conversion-provider-delegation-xzn0F
Docstrings generation was requested by @timosachsenberg. * #243 (comment) The following files were modified: * `autowrap/ConversionProvider.py`
1 parent 8b5ebfb commit 32f8a30

File tree

1 file changed

+148
-24
lines changed

1 file changed

+148
-24
lines changed

autowrap/ConversionProvider.py

Lines changed: 148 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -132,31 +132,41 @@ def input_conversion(
132132
def output_conversion(
133133
self, cpp_type: CppType, input_cpp_var: str, output_py_var: str
134134
) -> Optional[Union[Code, str]]:
135+
"""
136+
Generate code that converts a C++ value to a Python value.
137+
138+
Parameters:
139+
cpp_type (CppType): The C++ type of the value to convert.
140+
input_cpp_var (str): Name of the C++ variable holding the value to be converted.
141+
output_py_var (str): Name of the Python variable that should receive the converted value.
142+
143+
Returns:
144+
A code snippet (as `Code` or `str`) that assigns or produces a Python representation of `input_cpp_var` into `output_py_var`, or `None` if no conversion is necessary.
145+
"""
135146
raise NotImplementedError()
136147

137148
def supports_delegation(self) -> bool:
138149
"""
139-
Return True if this converter should be invoked when the type
140-
is an element inside a container (e.g., std::vector).
141-
142-
By default, Cython handles conversion of standard types inside
143-
containers automatically. When this returns True, container
144-
converters will delegate to this converter instead.
150+
Indicates whether this converter should be used for elements contained within container types.
151+
152+
When `True`, container converters (for example, std::vector) will delegate per-element conversion to this converter instead of relying on the container's default/automatic conversion handling.
153+
154+
Returns:
155+
bool: `True` if elements should be delegated to this converter, `False` otherwise.
145156
"""
146157
return False
147158

148159
@staticmethod
149160
def _code_for_instantiate_object_from_iter(cpp_type: CppType, it: str) -> str:
150161
"""
151-
Code for new object instantiation from iterator (double deref for iterator-ptr)
152-
153-
Note that if cpp_type is a pointer and the iterator therefore refers to
154-
an STL object of std::vector< _FooObject* >, then we need the base type
155-
to instantiate a new object and dereference twice.
156-
157-
Example output:
158-
shared_ptr[ _FooObject ] (new _FooObject (*foo_iter) )
159-
shared_ptr[ _FooObject ] (new _FooObject (**foo_iter_ptr) )
162+
Create C++ expression code that constructs a shared_ptr to a new instance created from an iterator.
163+
164+
Parameters:
165+
cpp_type (CppType): The target C++ type to instantiate. If `cpp_type` is a reference, its base type is used; if it is a pointer, the iterator is assumed to yield pointers and the generated expression will dereference twice.
166+
it (str): Expression referring to the iterator value (as a string) to be dereferenced when constructing the new object.
167+
168+
Returns:
169+
str: A C++ code snippet that calls `new` and wraps the result in `shared_ptr[...]`, using `deref(it)` or `deref(deref(it))` as appropriate.
160170
"""
161171

162172
if cpp_type.is_ref:
@@ -1562,6 +1572,34 @@ def _perform_recursion(
15621572
*a,
15631573
**kw
15641574
):
1575+
"""
1576+
Recursively generates and assembles code snippets for converting nested containers (typically nested std::vector) from Python to C++.
1577+
1578+
This helper performs a single level of recursion for nested container element conversion: it invokes the appropriate element converter for the inner element type, incorporates that converter's pre-call (topmost) and post-call (bottommost/cleanup) code into the caller's code blocks, and appends the necessary loop and push_back mechanics to build the outer container from inner results. It mutates the provided Code objects to accumulate pre-call code (code/topmost_code) and post-call cleanup code (cleanup_code/bottommost_code) for the overall conversion and does not return a value.
1579+
1580+
Parameters:
1581+
cpp_type: CppType
1582+
The full CppType of the container being converted (used to decide reference/const semantics for post-call behavior).
1583+
tt: CppType
1584+
The element CppType for this recursion level (the type to be handled by the invoked converter).
1585+
arg_num: str
1586+
Base argument identifier (used to name temporaries for this recursion level).
1587+
item: str
1588+
Name of the Python-side iteration variable for the current recursion level; becomes the argument passed to the inner converter.
1589+
topmost_code: Code or None
1590+
Code block that should receive top-level (pre-call) snippets. If None, this function treats itself as the topmost recursion and writes into `code`.
1591+
bottommost_code: Code or None
1592+
Code block that should receive bottom-level (post-call) snippets. If None, this function treats itself as the outermost recursion for cleanup placement.
1593+
code: Code
1594+
Code block used to accumulate the main pre-call construction (e.g., outer loop and inner loop bodies).
1595+
cleanup_code: Code
1596+
Code block used to accumulate post-call cleanup and any result-copying logic.
1597+
recursion_cnt: int
1598+
Current recursion depth (0 for outermost). Used to name intermediate temporaries used for multi-level replacement and cleanup.
1599+
*a, **kw:
1600+
Formatting/templating context forwarded to Code.add calls (contains mapping keys such as argument_var, temp_var, it, etc.).
1601+
1602+
"""
15651603
converter = self.cr.get(tt)
15661604
py_type = converter.matching_python_type(tt)
15671605
rec_arg_num = "%s_rec" % arg_num
@@ -1680,7 +1718,15 @@ def _perform_recursion(
16801718
bottommost_code.content.extend(bottommost_code_callback.content)
16811719

16821720
def _has_delegating_converter(self, element_type: CppType) -> bool:
1683-
"""Check if element type has a converter that supports delegation."""
1721+
"""
1722+
Determine whether the registered converter for the given element type opts into delegation.
1723+
1724+
Parameters:
1725+
element_type (CppType): The C++ type to look up in the converter registry.
1726+
1727+
Returns:
1728+
bool: `True` if a converter is registered for `element_type` and its `supports_delegation()` returns `True`, `False` otherwise.
1729+
"""
16841730
if not hasattr(self, "cr"):
16851731
return False
16861732
try:
@@ -1698,13 +1744,30 @@ def input_conversion(
16981744
bottommost_code: Optional[Code] = None,
16991745
recursion_cnt: int = 0,
17001746
) -> Tuple[Code, str, Code]:
1701-
"""Do the input conversion for a std::vector<T>
1702-
1703-
In this case, the template argument is tt (or "inner").
1704-
1705-
It is possible to nest or recurse multiple vectors (like in
1706-
std::vector< std::vector< T > > which is detected since the template
1707-
argument of tt itself is not None).
1747+
"""
1748+
Convert a Python sequence argument into a C++ libcpp_vector suitable for passing to C++.
1749+
1750+
This generates the Cython pre-call code, the expression to use in the C++ call, and the post-call cleanup for converting a Python iterable (argument_var) into a temporary libcpp_vector corresponding to cpp_type (a std::vector<T>). The method handles:
1751+
- element types that are enums, wrapped C++ classes, shared_ptr<T>, nested std::vector<T> recursion, and element converters that support delegation;
1752+
- producing top-level declarations when recursion requires them;
1753+
- producing a cleanup step that writes back to the original Python container when the parameter is a non-const reference.
1754+
1755+
Parameters:
1756+
cpp_type (CppType): The std::vector type to convert (template argument T is inspected).
1757+
argument_var (str): Name of the Python variable containing the input sequence.
1758+
arg_num (int): Numerical index used to create unique temporary/local identifiers.
1759+
topmost_code (Optional[Code]): Optional Code object to which declarations that must appear at function top-level are appended when recursing.
1760+
bottommost_code (Optional[Code]): Optional Code object used to append cleanup code at the bottom-level when recursing.
1761+
recursion_cnt (int): Current recursion depth for nested vector conversion; 0 for the top level.
1762+
1763+
Returns:
1764+
Tuple[Code, str, Code]: A 3-tuple of (pre-call code, call-expression, cleanup code):
1765+
- pre-call Code: Cython code that prepares and fills a temporary libcpp_vector corresponding to cpp_type.
1766+
- call-expression (str): Expression to pass to the generated C++ call (typically the temp vector or deref(temp)).
1767+
- cleanup Code: Code to run after the call to perform any necessary write-back or cleanup (e.g., replace original Python contents for non-const ref parameters, or delete temporaries).
1768+
1769+
Raises:
1770+
Exception: If recursion for the given nested template structure is not implemented or required resources are missing (for example, when nested recursion is requested but a ConverterRegistry instance is not available on self).
17081771
"""
17091772
# If we are inside a recursion, we expect the top-most and bottom most code to be present...
17101773
if recursion_cnt > 1:
@@ -2010,6 +2073,25 @@ def call_method(self, res_type: CppType, cy_call_str: str, with_const: bool = Tr
20102073
return "_r = %s" % (cy_call_str)
20112074

20122075
def output_conversion(self, cpp_type: CppType, input_cpp_var: str, output_py_var: str) -> Code:
2076+
"""
2077+
Convert a C++ libcpp_vector value into a Python list, handling special element types.
2078+
2079+
This generates Cython code that fills the Python variable named by `output_py_var`
2080+
from the C++ container `input_cpp_var`, with special handling for:
2081+
- enum element types (produces ints),
2082+
- wrapped C++ classes (produces Python wrapper instances),
2083+
- shared_ptr elements wrapping a single base type (produces wrapper instances),
2084+
- element converters that support delegation (calls the element converter's output_conversion),
2085+
and a fallback that lets Cython perform a direct container-to-list conversion for plain STL element types.
2086+
2087+
Parameters:
2088+
cpp_type (CppType): The C++ libcpp_vector type (must have one template arg).
2089+
input_cpp_var (str): Name of the C++ variable containing the libcpp_vector to convert.
2090+
output_py_var (str): Name of the Python variable to assign the resulting list to.
2091+
2092+
Returns:
2093+
Code: A Code object containing the generated Cython code that produces `output_py_var`.
2094+
"""
20132095
(tt,) = cpp_type.template_args
20142096
inner = self.converters.cython_type(tt)
20152097

@@ -2535,12 +2617,33 @@ class StdStringUnicodeConverter(StdStringConverter):
25352617
"""
25362618

25372619
def get_base_types(self) -> List[str]:
2620+
"""
2621+
Base C++ type names handled by this converter.
2622+
2623+
Returns:
2624+
base_types (List[str]): A list containing the single base type name "libcpp_utf8_string".
2625+
"""
25382626
return ["libcpp_utf8_string"]
25392627

25402628
def supports_delegation(self) -> bool:
2629+
"""
2630+
Indicates that this converter allows its conversion logic to be applied to elements inside container converters.
2631+
2632+
Returns:
2633+
`true` if the converter supports delegation to element-wise conversion inside containers, `false` otherwise.
2634+
"""
25412635
return True
25422636

25432637
def matching_python_type(self, cpp_type: CppType) -> str:
2638+
"""
2639+
Return the simple Python type name used for runtime checks for the given C++ type.
2640+
2641+
Parameters:
2642+
cpp_type (CppType): The C++ type being queried.
2643+
2644+
Returns:
2645+
A string containing the Python runtime type name (e.g., "bytes", "str", "int"), or an empty string when no single Python type is appropriate.
2646+
"""
25442647
return "" # TODO can we use "basestring"?
25452648

25462649
def matching_python_type_full(self, cpp_type: CppType) -> str:
@@ -2577,12 +2680,33 @@ class StdStringUnicodeOutputConverter(StdStringUnicodeConverter):
25772680
"""
25782681

25792682
def get_base_types(self) -> List[str]:
2683+
"""
2684+
Provide the base type names that this converter can handle.
2685+
2686+
Returns:
2687+
List[str]: A list containing the base type name "libcpp_utf8_output_string".
2688+
"""
25802689
return ["libcpp_utf8_output_string"]
25812690

25822691
def supports_delegation(self) -> bool:
2692+
"""
2693+
Indicates that this converter allows its conversion logic to be applied to elements inside container converters.
2694+
2695+
Returns:
2696+
`true` if the converter supports delegation to element-wise conversion inside containers, `false` otherwise.
2697+
"""
25832698
return True
25842699

25852700
def matching_python_type_full(self, cpp_type: CppType) -> str:
2701+
"""
2702+
Return the full Python type annotation used for C++ UTF-8 output strings.
2703+
2704+
Parameters:
2705+
cpp_type (CppType): The C++ type representation (ignored; output is always `str`).
2706+
2707+
Returns:
2708+
str: The Python type annotation `"str"`.
2709+
"""
25862710
return "str" # python3
25872711

25882712
def output_conversion(
@@ -3838,4 +3962,4 @@ def setup_converter_registry(classes_to_wrap, enums_to_wrap, instance_map):
38383962
# ...
38393963
#
38403964
# special_converters.append(MyConverter())
3841-
#
3965+
#

0 commit comments

Comments
 (0)