{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# litgen options\n", "\n", "litgen uses numerous options which can be found here: [litgen/options.py](https://github.com/pthom/litgen/blob/main/src/litgen/options.py).\n", "\n", "\n", "## Note about regexes\n", "Many options use regexes: see the note about their usage in the [options.py](https://github.com/pthom/litgen/blob/main/src/litgen/options.py) file:\n", "\n", "\n", "regexes can support several alternatives: separate them by \"|\". \n", "\n", "For example, in order to match an exact function name (`YourFunctionName`), as well as functions ending with `_private`, use a regex like this:\n", "\n", " r\"^YourFunctionName$|_private$\",\n", "\n", "_Tips:_\n", "- If a regex string is empty, it will not match anything (this is specific to litgen)\n", "- To match everything, use r\".*\"\n", "- It is advised to prefix your regex strings with \"r\" (in order to use raw strings)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## litgen main options\n", "\n", "Below, we show the content of litgen/options.py:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " \n", " \n", "
from __future__ import annotations\n",
"\n",
"from typing import Any, Callable, List\n",
"\n",
"from codemanip import code_utils\n",
"from codemanip.code_replacements import RegexReplacementList\n",
"\n",
"from srcmlcpp import SrcmlcppOptions\n",
"\n",
"from litgen.internal.template_options import TemplateFunctionsOptions, TemplateClassOptions\n",
"from litgen.internal.class_iterable_info import ClassIterablesInfos\n",
"\n",
"\n",
"class Blah:\n",
" values: List[int] = []\n",
"\n",
"\n",
"class LitgenOptions:\n",
" """Numerous options to configure litgen code generation.\n",
"\n",
" (include / excludes, indentation, c++ to python translation settings, function parameters\n",
" adaptations, etc.)"""\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Note about regexes below:\n",
" # =========================\n",
" # - regexes can support several alternatives: separate them by "|"\n",
" # For example, in order to match an exact function name, as well as functions ending with "_private",\n",
" # use a regex like this:\n",
" # r"^YourFunctionName$|_private$",\n",
" # - If a regex string is empty, it will not match anything\n",
" # - To match everything, use r".*"\n",
" # - It is advised to prefix your regex strings with "r" (in order to use raw strings)\n",
" # ------------------------------------------------------------------------------\n",
"\n",
" ################################################################################\n",
" # <srcmlcpp options>\n",
" ################################################################################\n",
" # There are interesting options to set in SrcmlcppOptions (see srcmlcpp/srcmlcpp_options.py)\n",
" #\n",
" # Notably:\n",
" # * fill srcmlcpp_options.functions_api_prefixes: the prefix(es) that denotes exported dll functions\n",
" # * also set LitgenOptions.fn_exclude_non_api=True if you want to exclude non api functions and methods\n",
" srcmlcpp_options: SrcmlcppOptions\n",
"\n",
" ################################################################################\n",
" # <Layout settings for the generated python stub code>\n",
" ################################################################################\n",
" # <show the original location and or signature of elements as a comment>\n",
" original_location_flag_show = False\n",
" # if showing location, how many parent folders shall be shown\n",
" # (if -1, show the full path)\n",
" original_location_nb_parent_folders = 0\n",
" # If True, the complete C++ original signature will be show as a comment in the python stub (pyi)\n",
" original_signature_flag_show = False\n",
" # Size of an indentation in the python stubs\n",
" python_indent_size = 4\n",
" python_ident_with_tabs: bool = False\n",
" # Insert as many empty lines in the python stub as found in the header file, keep comments layout, etc.\n",
" python_reproduce_cpp_layout: bool = True\n",
" # The generated code will try to adhere to this max length (if negative, this is ignored)\n",
" python_max_line_length = 88\n",
" # Strip (remove) empty comment lines\n",
" python_strip_empty_comment_lines: bool = False\n",
" # Run black formatter\n",
" python_run_black_formatter: bool = False\n",
" python_black_formatter_line_length: int = 88\n",
"\n",
" ################################################################################\n",
" # <Layout settings for the C++ generated pydef code>\n",
" ################################################################################\n",
" # Spacing option in C++ code\n",
" cpp_indent_size: int = 4\n",
" cpp_indent_with_tabs: bool = False\n",
"\n",
" ################################################################################\n",
" # <names translation from C++ to python>\n",
" ################################################################################\n",
" # Convert variables, functions and namespaces names to snake_case (class, structs, and enums names are always preserved)\n",
" python_convert_to_snake_case: bool = True\n",
" # List of code replacements when going from C++ to Python\n",
" # Notes:\n",
" # - by default, type_replacements is prefilled with standard_type_replacements()\n",
" # type_replacements will be applied to all types (including class and enum names)\n",
" # - by default, value_replacements is prefilled with standard_value_replacements()\n",
" # - by default, comments_replacements is prefilled with standard_comments_replacements()\n",
" # - by default, the others are empty\n",
" # - type_replacements, var_names_replacements and function_names_replacements enable you\n",
" # to modify the outputted python code\n",
" type_replacements: RegexReplacementList # = cpp_to_python.standard_type_replacements() by default\n",
" var_names_replacements: RegexReplacementList # = RegexReplacementList() by default (i.e. empty)\n",
" namespace_names_replacements: RegexReplacementList # = RegexReplacementList() by default (i.e. empty)\n",
" function_names_replacements: RegexReplacementList # = RegexReplacementList() by default (i.e. empty)\n",
" value_replacements: RegexReplacementList # = cpp_to_python.standard_value_replacements() by default\n",
" comments_replacements: RegexReplacementList # = cpp_to_python.standard_comment_replacements() by default\n",
" macro_name_replacements: RegexReplacementList # = RegexReplacementList() by default (i.e. empty)\n",
"\n",
" ################################################################################\n",
" # <functions and method adaptations>\n",
" ################################################################################\n",
"\n",
" # Exclude certain functions and methods by a regex on their name\n",
" fn_exclude_by_name__regex: str = ""\n",
"\n",
" # Exclude certain functions and methods by a regex on any of their parameter type and/or return type\n",
" # (those should be decorated type)\n",
" # For example:\n",
" # options.fn_exclude_by_param_type__regex = "^char\\s*$|^unsigned\\s+char$|Callback$"\n",
" # would exclude all functions having params of type "char *", "unsigned char", "xxxCallback"\n",
" #\n",
" # Note: this is distinct from `fn_params_exclude_types__regex` which removes params\n",
" # from the function signature, but not the function itself.\n",
" fn_exclude_by_param_type__regex: str = ""\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Exclude some params by name or type\n",
" # ------------------------------------------------------------------------------\n",
" # Remove some params from the python published interface. A param can only be removed if it has a default value\n",
" # in the C++ signature\n",
" fn_params_exclude_names__regex: str = ""\n",
" fn_params_exclude_types__regex: str = ""\n",
"\n",
" # fn_exclude_non_api:\n",
" # if srcmlcpp_options.functions_api_prefixes is filled, and fn_exclude_non_api=True,\n",
" # then only functions with an api marker will be exported.\n",
" fn_exclude_non_api: bool = True\n",
" # fn_non_api_comment:\n",
" # if fn_exclude_non_api is False, a comment can be added to non api functions in the stub file\n",
" fn_non_api_comment: str = "(private API)"\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Templated functions options\n",
" # ------------------------------------------------------------------------------\n",
" # Template function must be instantiated for the desired types.\n",
" # See https://pybind11.readthedocs.io/en/stable/advanced/functions.html#binding-functions-with-template-parameters\n",
" #\n",
" # fn_template_options:\n",
" # of type Dict[ TemplatedFunctionNameRegexStr (aka str), List[CppTypeName] ]\n",
" #\n",
" # For example,\n",
" # 1. This line:\n",
" # options.fn_template_options.add_specialization(r"template^", ["int", double"])\n",
" # would instantiate all template functions whose name end with "template" with "int" and "double"\n",
" # 2. This line:\n",
" # options.fn_template_options.add_specialization(r".*", ["int", float"])\n",
" # would instantiate all template functions (whatever their name) with "int" and "float"\n",
" # 3. This line:\n",
" # options.fn_template_options.add_ignore(r".*")\n",
" # would ignore all template functions (they will not be exported)\n",
" fn_template_options: TemplateFunctionsOptions\n",
" # if fn_template_decorate_in_stub is True, then there will be some\n",
" # decorative comments in the stub file, in order to visually group\n",
" # the generated functions together\n",
" fn_template_decorate_in_stub: bool = True\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Vectorize functions options\n",
" # ------------------------------------------------------------------------------\n",
" # Numeric functions (i.e. function accepting and returning only numeric params or py::array), can be vectorized\n",
" # i.e. they will accept numpy arrays as an input.\n",
" # See https://pybind11.readthedocs.io/en/stable/advanced/pycpp/numpy.html#vectorizing-functions\n",
" # and https://github.com/pybind/pybind11/blob/master/tests/test_numpy_vectorize.cpp\n",
" #\n",
" # * fn_vectorize__regex and fn_namespace_vectorize__regex contain a regexes\n",
" # on functions names + namespace names for which this transformation will be applied.\n",
" #\n",
" # For example, to vectorize all function of the namespace MathFunctions, apply these options:\n",
" # options.fn_namespace_vectorize__regex: str = r"MathFunctions^$"\n",
" # options.fn_vectorize__regex = r".*"\n",
" #\n",
" # * fn_vectorize_prefix and fn_vectorize_suffix will be added to the vectorized functions names\n",
" # (they can be empty, in which case the vectorized function will be a usable overload with the same name)\n",
" fn_vectorize__regex: str = r""\n",
" fn_namespace_vectorize__regex: str = r""\n",
" fn_vectorize_prefix: str = ""\n",
" fn_vectorize_suffix: str = ""\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Return policy\n",
" # ------------------------------------------------------------------------------\n",
" # Force the function that match those regexes to use `pybind11::return_value_policy::reference`\n",
" #\n",
" # Note:\n",
" # you can also write "// py::return_value_policy::reference" as an end of line comment after the function.\n",
" # See packages/litgen/integration_tests/mylib/include/mylib/return_value_policy_test.h as an example\n",
" fn_return_force_policy_reference_for_pointers__regex: str = ""\n",
" fn_return_force_policy_reference_for_references__regex: str = ""\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Force overload\n",
" # ------------------------------------------------------------------------------\n",
" # Force using py::overload for functions that matches these regexes\n",
" fn_force_overload__regex: str = ""\n",
" # Force using a lambda for functions that matches these regexes\n",
" # (useful when pybind11 is confused and gives error like\n",
" # error: no matching function for call to object of type 'const detail::overload_cast_impl<...>'\n",
" fn_force_lambda__regex: str = ""\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # C style buffers to py::array\n",
" # ------------------------------------------------------------------------------\n",
" #\n",
" # Signatures with a C buffer like this:\n",
" # MY_API inline void add_inside_array(uint8_t* array, size_t array_size, uint8_t number_to_add)\n",
" # may be transformed to:\n",
" # void add_inside_array(py::array & array, uint8_t number_to_add) (c++ bound signature)\n",
" # def add_inside_array(array: numpy.ndarray, number_to_add: int) -> None (python)\n",
" #\n",
" # It also works for templated buffers:\n",
" # MY_API template<typename T> void mul_inside_array(T* array, size_t array_size, double factor)\n",
" # will be transformed to:\n",
" # void mul_inside_array(py::array & array, double factor) (c++ bound signature)\n",
" # def mul_inside_array(array: numpy.ndarray, factor: float) -> None (python)\n",
" # (and factor will be down-casted to the target type)\n",
" #\n",
" # fn_params_buffer_replace_by_array_regexes contains a regex on functions names\n",
" # for which this transformation will be applied.\n",
" # Set it to r".*" to apply this to all functions, set it to "" to disable it\n",
" #\n",
" fn_params_replace_buffer_by_array__regex: str = r""\n",
"\n",
" # fn_params_buffer_types: list of numeric types that are considered as possible buffers.\n",
" # You can customize this list in your own options by removing items from it,\n",
" # but you *cannot* add new types or new synonyms (typedef for examples); since the conversion between\n",
" # py::array and native relies on these *exact* names!\n",
" #\n",
" # By default, fn_params_buffer_types will contain those types:\n",
" fn_params_buffer_types: str = code_utils.join_string_by_pipe_char(\n",
" [\n",
" "uint8_t",\n",
" "int8_t",\n",
" "uint16_t",\n",
" "int16_t",\n",
" "uint32_t",\n",
" "int32_t",\n",
" "np_uint_l", # Platform dependent: "uint64_t" on *nixes, "uint32_t" on windows\n",
" "np_int_l", # Platform dependent: "int64_t" on *nixes, "int32_t" on windows\n",
" "float",\n",
" "double",\n",
" "long double",\n",
" "long long",\n",
" ]\n",
" )\n",
"\n",
" # fn_params_buffer_template_types: list of templated names that are considered as possible templated buffers\n",
" # By default, only template<typename T> or template<typename NumericType> are accepted\n",
" fn_params_buffer_template_types: str = code_utils.join_string_by_pipe_char(["T", "NumericType"])\n",
"\n",
" # fn_params_buffer_size_names__regex: possible names for the size of the buffer\n",
" # = ["nb", "size", "count", "total", "n"] by default\n",
" fn_params_buffer_size_names__regex: str = code_utils.join_string_by_pipe_char(\n",
" [\n",
" code_utils.make_regex_var_name_contains_word("nb"),\n",
" code_utils.make_regex_var_name_contains_word("size"),\n",
" code_utils.make_regex_var_name_contains_word("count"),\n",
" code_utils.make_regex_var_name_contains_word("total"),\n",
" code_utils.make_regex_var_name_contains_word("n"),\n",
" ]\n",
" )\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # C style arrays functions and methods parameters\n",
" # ------------------------------------------------------------------------------\n",
" #\n",
" # Signatures like\n",
" # void foo_const(const int input[2])\n",
" # may be transformed to:\n",
" # void foo_const(const std::array<int, 2>& input) (c++ bound signature)\n",
" # def foo_const(input: List[int]) -> None: (python)\n",
" # fn_params_replace_c_array_const_by_std_array__regex contains a list of regexes on functions names\n",
" # for which this transformation will be applied.\n",
" # Set it to r".*" to apply this to all functions, set it to "" to disable it\n",
" fn_params_replace_c_array_const_by_std_array__regex: str = r".*"\n",
"\n",
" # Signatures like\n",
" # void foo_non_const(int output[2])\n",
" # may be transformed to:\n",
" # void foo_non_const(BoxedInt & output_0, BoxedInt & output_1) (c++ bound signature)\n",
" # def foo_non_const(output_0: BoxedInt, output_0: BoxedInt) -> None (python)\n",
" # fn_params_replace_c_array_modifiable_by_boxed__regex contains a list of regexes on functions names\n",
" # for which this transformation will be applied.\n",
" # Set it to r".*" to apply this to all functions, set it to "" to disable it\n",
" fn_params_replace_c_array_modifiable_by_boxed__regex: str = r".*"\n",
" # (c_array_modifiable_max_size is the maximum number of params that can be boxed like this)\n",
" fn_params_replace_modifiable_c_array__max_size = 10\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # C style string list functions and methods parameters\n",
" # ------------------------------------------------------------------------------\n",
" # Signatures like\n",
" # void foo(const char * const items[], int items_count)\n",
" # may be transformed to:\n",
" # void foo(const std::vector<std::string>& const items[]) (c++ bound signature)\n",
" # def foo(items: List[str]) -> None (python)\n",
" # fn_params_replace_c_string_list_regexes contains a list of regexes on functions names\n",
" # for which this transformation will be applied.\n",
" # Set it to [r".*"] to apply this to all functions, set it to [] to disable it\n",
" fn_params_replace_c_string_list__regex: str = r".*"\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Make "immutable python types" modifiable, when passed by pointer or reference\n",
" # ------------------------------------------------------------------------------\n",
" #\n",
" # adapt functions params that use non const pointers or reference to a type that is immutable in python.\n",
"\n",
" # Signatures like\n",
" # int foo(int* value)\n",
" # May be transformed to:\n",
" # def foo(BoxedInt value) -> int (python)\n",
" # So that any modification done on the C++ side can be seen from python.\n",
" #\n",
" # fn_params_adapt_modifiable_immutable_regexes contains a list of regexes on functions names\n",
" # Set it to r".*" to apply this to all functions. Set it to "" to disable it\n",
" fn_params_replace_modifiable_immutable_by_boxed__regex: str = ""\n",
"\n",
" # As an alternative, we can also add the modified value to the returned type\n",
" # of the function (which will now be a tuple)\n",
" #\n",
" # For example\n",
" # int foo(int* value)\n",
" # May be transformed to:\n",
" # def foo(int value) -> Tuple[int, bool]\n",
" # So that any modification done on the C++ side can be seen from python.\n",
" #\n",
" # fn_params_output_modifiable_immutable_to_return__regex contains a list of regexes on functions names\n",
" # Set it to r".*" to apply this to all functions. Set it to "" to disable it\n",
" fn_params_output_modifiable_immutable_to_return__regex: str = ""\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Custom adapters (advanced, very advanced and not documented here)\n",
" # fn_custom_adapters may contain callables of signature\n",
" # f(adapted_function: AdaptedFunction) -> Optional[LambdaAdapter]\n",
" # ------------------------------------------------------------------------------\n",
" fn_custom_adapters: list[Any]\n",
"\n",
" ################################################################################\n",
" # <class, struct, and member adaptations>\n",
" ################################################################################\n",
"\n",
" # Exclude certain classes and structs by a regex on their name\n",
" class_exclude_by_name__regex: str = ""\n",
" # Exclude certain members by a regex on their name\n",
" member_exclude_by_name__regex: str = ""\n",
" # Exclude members based on their type\n",
" member_exclude_by_type__regex: str = ""\n",
" # Make certain members read-only by a regex on their name\n",
" member_readonly_by_name__regex: str = ""\n",
" # Make certain members read-only based on their type\n",
" member_readonly_by_type__regex: str = ""\n",
"\n",
" # class_create_default_named_ctor__regex / struct_create_default_named_ctor__regex:\n",
" # regex giving the list of class & struct names for which we want to generate a named\n",
" # constructor for Python, when no default constructor is provided by C++\n",
" # (by default, this is active for all structs and not for the classes,\n",
" # in order for it to work, all struct members need to be default constructible if\n",
" # they are not declared with a default value)\n",
" struct_create_default_named_ctor__regex: str = r".*"\n",
" class_create_default_named_ctor__regex: str = r""\n",
"\n",
" # class_expose_protected_methods__regex:\n",
" # regex giving the list of class names for which we want to expose protected methods.\n",
" # (by default, only public methods are exposed)\n",
" # If active, this will use the technique described at\n",
" # https://pybind11.readthedocs.io/en/stable/advanced/classes.html#binding-protected-member-functions)\n",
" class_expose_protected_methods__regex: str = ""\n",
"\n",
" # class_expose_protected_methods__regex:\n",
" # regex giving the list of class names for which we want to be able to override virtual methods\n",
" # from python.\n",
" # (by default, this is not possible)\n",
" # If active, this will use the technique described at\n",
" # https://pybind11.readthedocs.io/en/stable/advanced/classes.html#overriding-virtual-functions-in-python\n",
" #\n",
" # Note: if you want to override protected functions, also fill `class_expose_protected_methods__regex`\n",
" class_override_virtual_methods_in_python__regex: str = ""\n",
"\n",
" # class_dynamic_attributes__regex\n",
" # By default, classes exported from C++ do not support dynamic attributes and the only writable attributes are\n",
" # the ones explicitly defined using class_::def_readwrite() or class_::def_property().\n",
" # If active, this will use the technique described at\n",
" # https://pybind11.readthedocs.io/en/stable/classes.html#dynamic-attributes\n",
" class_dynamic_attributes__regex: str = ""\n",
"\n",
" # class_deep_copy__regex & class_copy__regex:\n",
" # By default, structs and classes exported from C++ do not support (deep)copy.\n",
" # However, if they do have a copy constructor (implicit or user defined),\n",
" # (deep)copy can be enabled by invoking this constructor.\n",
" # https://pybind11.readthedocs.io/en/stable/advanced/classes.html#deepcopy-support\n",
" class_deep_copy__regex: str = ""\n",
" class_copy__regex: str = ""\n",
" # If class_copy_add_info_in_stub=True, the existence of __copy__ and __deepcopy__\n",
" # will be mentioned in the stub file.\n",
" class_copy_add_info_in_stub: bool = False\n",
"\n",
" # iterable classes: if some cpp classes expose begin()/end()/size(), they can be made iterable in python\n",
" # Make classes iterables by setting:\n",
" # options.class_iterables_infos.add_iterable_class(python_class_name__regex, iterable_python_type_name)\n",
" class_iterables_infos: ClassIterablesInfos\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Templated class options\n",
" # ------------------------------------------------------------------------------\n",
" # Template class must be instantiated for the desired types, and a new name must be given for each instantiation\n",
" # See https://pybind11.readthedocs.io/en/stable/advanced/classes.html#binding-classes-with-template-parameters\n",
" #\n",
" # class_template_options enables to set this\n",
" #\n",
" # For example\n",
" # 1. this call would instantiate some classes for types "int" and "const char *", with a naming scheme:\n",
" # MyClass<int> (cpp) -> MyClassInt (python)\n",
" # ------------------------------------------\n",
" # options.class_template_options.add_specialization(\n",
" # class_name_regex=r"^MyPrefix", # r"^MyPrefix" => select class names with this prefix\n",
" # cpp_types_list=["int", "const char *"], # instantiated types\n",
" # naming_scheme=TemplateNamingScheme.camel_case_suffix\n",
" # )\n",
" # 2. this call would ignore all template classes:\n",
" # options.class_template_options.add_ignore(r".*")\n",
" # would ignore all template functions (they will not be exported)\n",
" class_template_options: TemplateClassOptions\n",
" # if class_template_decorate_in_stub is True, then there will be some\n",
" # decorative comments in the stub file, in order to visually group\n",
" # the generated classes together\n",
" class_template_decorate_in_stub: bool = True\n",
"\n",
" # ------------------------------------------------------------------------------\n",
" # Adapt class members\n",
" # ------------------------------------------------------------------------------\n",
" # adapt class members which are a fixed size array of a numeric type:\n",
" #\n",
" # For example\n",
" # struct Foo { int values[10]; };\n",
" # May be transformed to:\n",
" # class Foo:\n",
" # values: numpy.ndarray\n",
" #\n",
" # i.e. the member will be transformed to a property that points to a numpy array\n",
" # which can be read/written from python (this requires numpy)\n",
" # This is active by default.\n",
" member_numeric_c_array_replace__regex: str = r".*"\n",
"\n",
" # member_numeric_c_array_types: list of numeric types that can be stored in a numpy array\n",
" # for a class member which is a fixed size array of a numeric type\n",
" # - Synonyms (defined via. `typedef` or `using`) are allowed here\n",
" # - *don't* include char, *don't* include byte, those are not numeric!\n",
" # See https://numpy.org/doc/stable/reference/generated/numpy.chararray.html\n",
" member_numeric_c_array_types: str = code_utils.join_string_by_pipe_char(\n",
" [\n",
" "int",\n",
" "unsigned int",\n",
" "long",\n",
" "unsigned long",\n",
" "long long",\n",
" "unsigned long long",\n",
" "float",\n",
" "double",\n",
" "long double",\n",
" "uint8_t",\n",
" "int8_t",\n",
" "uint16_t",\n",
" "int16_t",\n",
" "uint32_t",\n",
" "int32_t",\n",
" "uint64_t",\n",
" "int64_t",\n",
" "bool",\n",
" ]\n",
" )\n",
"\n",
" ################################################################################\n",
" # <namespace adaptations>\n",
" ################################################################################\n",
"\n",
" # All C++ namespaces in this list will not be emitted as a submodule\n",
" # (i.e. their inner code will be placed in the root python module, or in the parent\n",
" # module)\n",
" namespaces_root: List[str]\n",
"\n",
" # All C++ namespaces that match this regex will be excluded\n",
" # By default, any namespace whose name contains "internal" or "detail" will be excluded.\n",
" namespace_exclude__regex = r"[Ii]nternal|[Dd]etail"\n",
"\n",
" ################################################################################\n",
" # <enum adaptations>\n",
" ################################################################################\n",
" # Exclude certain enums by a regex on their name\n",
" enum_exclude_by_name__regex: str = ""\n",
" # Remove the typical "EnumName_" prefix from "C enum" values.\n",
" # For example, with the C enum:\n",
" # enum MyEnum { MyEnum_A = 0, MyEnum_B };\n",
" # Values would be named "a" and "b" in python\n",
" enum_flag_remove_values_prefix: bool = True\n",
" # Skip count value from enums, for example like in:\n",
" # enum MyEnum { MyEnum_A = 1, MyEnum_B = 1, MyEnum_COUNT };\n",
" enum_flag_skip_count: bool = True\n",
" # By default, all enums export rudimentary arithmetic and bit-level operations ( r".*" matches any enum name)\n",
" enum_make_arithmetic__regex: str = r".*"\n",
"\n",
" ################################################################################\n",
" # <define adaptations>\n",
" ################################################################################\n",
" # Simple preprocessor defines can be exported as global variables, e.g.:\n",
" # #define MY_VALUE 1\n",
" # #define MY_FLOAT 1.5\n",
" # #define MY_STRING "abc"\n",
" # #define MY_HEX_VALUE 0x00010009\n",
" # This is limited to *simple* defines (no param, string, int, float or hex only)\n",
" # By default nothing is exported\n",
" macro_define_include_by_name__regex: str = ""\n",
"\n",
" ################################################################################\n",
" # <post processing>\n",
" ################################################################################\n",
" # If you need to process the code after generation, fill these functions\n",
" postprocess_stub_function: Callable[[str], str] | None = None # run at the very end\n",
" postprocess_pydef_function: Callable[[str], str] | None = None\n",
"\n",
" ################################################################################\n",
" # <Sanity checks and utilities below>\n",
" ################################################################################\n",
" def check_options_consistency(self) -> None:\n",
" # the only authorized type are those for which the size is known with certainty\n",
" # * int and long are not acceptable candidates: use int8_t, uint_8t, int32_t, etc.\n",
" # * concerning float and doubles, there is no standard for fixed size floats, so we have to cope with\n",
" # float, double and long double and their various platforms implementations...\n",
" authorized_types = [\n",
" "byte",\n",
" "uint8_t",\n",
" "int8_t",\n",
" "uint16_t",\n",
" "int16_t",\n",
" "uint32_t",\n",
" "int32_t",\n",
" "np_uint_l", # Platform dependent: "uint64_t" on *nixes, "uint32_t" on windows\n",
" "np_int_l", # Platform dependent: "int64_t" on *nixes, "int32_t" on windows\n",
" "float",\n",
" "double",\n",
" "long double",\n",
" "long long",\n",
" ]\n",
" for buffer_type in self._fn_params_buffer_types_list():\n",
" if buffer_type not in authorized_types:\n",
" raise ValueError(\n",
" f"""\n",
" options.build_types contains an unauthorized type: {buffer_type}\n",
" Authorized types are: { ", ".join(authorized_types) }\n",
" """\n",
" )\n",
"\n",
" def _indent_cpp_spaces(self) -> str:\n",
" space = "\\t" if self.cpp_indent_with_tabs else " "\n",
" return space * self.cpp_indent_size\n",
"\n",
" def _indent_python_spaces(self) -> str:\n",
" space = "\\t" if self.python_ident_with_tabs else " "\n",
" return space * self.python_indent_size\n",
"\n",
" def _fn_params_buffer_types_list(self) -> list[str]:\n",
" return code_utils.split_string_by_pipe_char(self.fn_params_buffer_types)\n",
"\n",
" def _fn_params_buffer_template_types_list(self) -> list[str]:\n",
" return code_utils.split_string_by_pipe_char(self.fn_params_buffer_template_types)\n",
"\n",
" def _member_numeric_c_array_types_list(self) -> list[str]:\n",
" return code_utils.split_string_by_pipe_char(self.member_numeric_c_array_types)\n",
"\n",
" def __init__(self) -> None:\n",
" # See doc for all the params at their declaration site (scroll up to the top of this file!)\n",
" from litgen.internal import cpp_to_python\n",
"\n",
" self.srcmlcpp_options = SrcmlcppOptions()\n",
" self.srcmlcpp_options.header_filter_preprocessor_regions = True\n",
"\n",
" self.type_replacements = cpp_to_python.standard_type_replacements()\n",
" self.value_replacements = cpp_to_python.standard_value_replacements()\n",
" self.comments_replacements = cpp_to_python.standard_comment_replacements()\n",
"\n",
" self.function_names_replacements = RegexReplacementList()\n",
" self.var_names_replacements = RegexReplacementList()\n",
" self.macro_name_replacements = RegexReplacementList()\n",
" self.namespace_names_replacements = RegexReplacementList()\n",
"\n",
" self.fn_template_options = TemplateFunctionsOptions()\n",
" self.class_template_options = TemplateClassOptions()\n",
"\n",
" self.class_iterables_infos = ClassIterablesInfos()\n",
"\n",
" self.fn_custom_adapters = []\n",
" self.namespaces_root = []\n",
"
"""\n",
"Options for srcmlcpp. Read the doc near all options elements.\n",
""""\n",
"from __future__ import annotations\n",
"from typing import Callable, Optional\n",
"\n",
"from codemanip.code_utils import split_string_by_pipe_char\n",
"from srcmlcpp.scrml_warning_settings import WarningType\n",
"\n",
"\n",
"class SrcmlcppOptions:\n",
" ################################################################################\n",
" # <API prefixes for functions / API comment suffixes for classes>\n",
" ################################################################################\n",
"\n",
" # Prefixes that denote exported dll functions.\n",
" # For example, you could use "MY_API" which would be defined as `__declspec(dllexport|dllimport)` on windows\n",
" # You can have several prefixes: separate them with a "|", for example: "MY_API|OTHER_API"\n",
" #\n",
" # If you filled SrcmlcppOptions.functions_api_prefixes, then those prefixes will be mentioned\n",
" # as specifiers for the return type of the functions.\n",
" functions_api_prefixes: str = ""\n",
"\n",
" ################################################################################\n",
" # <Numbers parsing: resolve macros values>\n",
" ################################################################################\n",
"\n",
" # List of named possible numbers or sizes (fill it if some number/sizes are defined by macros or constexpr values)\n",
" # For example it could store `{ "SPACE_DIMENSIONS" : 3 }` if the C++ code uses a macro `SPACE_DIMENSIONS`\n",
" named_number_macros: dict[str, int]\n",
"\n",
" ################################################################################\n",
" # <Exclude certain regions based on preprocessor macros>\n",
" ################################################################################\n",
"\n",
" # Set header_filter_preprocessor_regions to True if the header has regions\n",
" # that you want to exclude from the parsing, like this:\n",
" # #ifdef SOME_RARE_OPTION\n",
" # // code we want to exclude\n",
" # #endif\n",
" #\n",
" # See srcmlcpp/filter_preprocessor_regions.py for more complete examples\n",
" header_filter_preprocessor_regions: bool = False\n",
" # If header_filter_preprocessor_regions is True,\n",
" # you need to also fill header_filter_acceptable__regex in order to accept code contained\n",
" # inside header_guards (and other acceptable preprocessor defines you may set via this regex)\n",
" # Your regex can have several options: separate them with a "|".\n",
" # By default, all macros names ending with "_H", "HPP", "HXX" are considered as acceptable.\n",
" header_filter_acceptable__regex: str = "__cplusplus|_h_$|_h$|_H$|_H_$|hpp$|HPP$|hxx$|HXX$"\n",
"\n",
" ################################################################################\n",
" # <Custom preprocess of the code>\n",
" ################################################################################\n",
"\n",
" #\n",
" # If you need to preprocess the code before parsing, fill this function\n",
" #\n",
" code_preprocess_function: Optional[Callable[[str], str]] = None\n",
"\n",
" ################################################################################\n",
" # <Misc options>\n",
" ################################################################################\n",
"\n",
" # Encoding of python and C++ files\n",
" encoding: str = "utf-8"\n",
"\n",
" # Preserve empty lines, i.e. any empty line in the C++ code will be mentioned as a CppEmptyLine element\n",
" # this is done by adding a dummy comment on the line.\n",
" preserve_empty_lines: bool = True\n",
"\n",
" # flag_srcml_dump_positions: if True, code positions will be outputted in the xml tree (recommended)\n",
" flag_srcml_dump_positions: bool = True\n",
"\n",
" # indentation used by CppElements str_code() methods (4 spaces by default)\n",
" indent_cpp_str: str = " "\n",
"\n",
" ################################################################################\n",
" # <Verbose / Quiet mode>\n",
" ################################################################################\n",
"\n",
" # if quiet, all warning messages are discarded (warning messages go to stderr)\n",
" flag_quiet: bool = False\n",
"\n",
" # List of ignored warnings\n",
" ignored_warnings: list[WarningType]\n",
" # List of ignored warnings, identified by a part of the warning message\n",
" ignored_warning_parts: list[str]\n",
"\n",
" # Show python callstack when warnings are raised\n",
" flag_show_python_callstack: bool = False\n",
"\n",
" # if true, display parsing progress during execution (on stdout)\n",
" flag_show_progress: bool = False\n",
"\n",
" ################################################################################\n",
" # Workaround for https://github.com/srcML/srcML/issues/1833\n",
" ################################################################################\n",
" fix_brace_init_default_value = True\n",
"\n",
" ################################################################################\n",
" # <End>\n",
" ################################################################################\n",
"\n",
" def __init__(self) -> None:\n",
" # See doc for all the params at their declaration site (scroll up!)\n",
" self.named_number_macros = {}\n",
" self.ignored_warnings = []\n",
" self.ignored_warning_parts = []\n",
"\n",
" def functions_api_prefixes_list(self) -> list[str]:\n",
" assert isinstance(self.functions_api_prefixes, str)\n",
" return split_string_by_pipe_char(self.functions_api_prefixes)\n",
"\n",
"\n",
"def _int_from_str_or_named_number_macros(options: SrcmlcppOptions, int_str: Optional[str]) -> Optional[int]:\n",
" if int_str is None:\n",
" return None\n",
"\n",
" try:\n",
" v = int(int_str)\n",
" return v\n",
" except ValueError:\n",
" if int_str in options.named_number_macros:\n",
" return options.named_number_macros[int_str]\n",
" else:\n",
" return None\n",
"