autopybind11 issueshttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues2024-01-18T04:35:28-05:00https://gitlab.kitware.com/autopybind11/autopybind11/-/issues/207CastXML asks for compiler2024-01-18T04:35:28-05:00SebastianThiedeCastXML asks for compilerHello everyone.
I really like your project, but had some trouble getting it to work with the g++ compiler I'm using.
I cloned it from GitLab latest commit.
I got the error "RuntimeError: Please pass the compiler_path as argument to your...Hello everyone.
I really like your project, but had some trouble getting it to work with the g++ compiler I'm using.
I cloned it from GitLab latest commit.
I got the error "RuntimeError: Please pass the compiler_path as argument to your xml_generator_configuration_t(), or add it to your pygccxml configuration file." which was raised from pygccxml/parser/source_reader.py.
I suppose this is an error other people might get, or maybe I missed something in the documentation, but for me I fixed it by adding a new option, pass the compiler (CMAKE_CXX_COMPILER) from CMake to autopybind11 via this option, then use this in __main__.py in the function "compile_and_parse_wrapper(...)" in the call to "pygccxml.parser.xml_generator_configuration_t(...)" as argument "compiler_path = self.opts.(my_new_option)".
Dunno if this helps or is not needed, but I bet you will tell me.
Best regards
Sebastianhttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/201Conflict between denoising and namespace renaming2022-02-25T07:19:12-05:00Luc HermitteConflict between denoising and namespace renamingI'll try my best to describe the issue.
## The problem
My C++ code looks like this
```c++
namespace aristarchus::geometry {
class Vector {...};
double angle(Vector const&, Vector const&);
}
```
Wrapper specifications
```yml
files:
...I'll try my best to describe the issue.
## The problem
My C++ code looks like this
```c++
namespace aristarchus::geometry {
class Vector {...};
double angle(Vector const&, Vector const&);
}
```
Wrapper specifications
```yml
files:
src/aristarchus/geometry/euclidian/threed/Vector3D.hpp:
namespaces:
aristarchus:
namespaces:
geometry:
customization:
enable_doc_strings: True
classes:
Vector:
customization:
namespace: geometry
module_local:
angle:
customization:
namespace: geometry
```
And the configuration file contains
```yml
enforce_namespace_structure: False
apply_global_namespace: False
```
Without the `customization.namespace` keys, I ended up with an extra scoping level in my Python module. With a `import modulename`, the symbols were in `modulename.aristarchus.geometry.(Vector|angle)` whilst I'd them to be `modulename.geometry.(Vector|angle)`.
If I add the `customization.namespace` key at the class level, it's perfect, `Vector` goes to the right place. However if I add it to each function, the C++ code generated is being striped of `::geometry::` and then `angle()` signature contains `aristarchusVector` instead of `aristarchus::geometry::Vector`.
## The Solution
The removal (/denoising?) of the intermediary namespace shall not be systematic. I've found out that if I check for `is_custom` beforehand, the issue seems fixed. In other words, the following patch seems to solve the issue.
```patch
diff --git i/autopybind11/__main__.py w/autopybind11/__main__.py
index 7e8aa67..bb314fc 100644
--- i/autopybind11/__main__.py
+++ w/autopybind11/__main__.py
@@ -784,8 +784,10 @@ class BindingsGenerator:
)
keys["defs"] = submodules_str + keys["defs"]
- if module_name != free_fun_mod_name:
- keys["defs"] = keys["defs"].replace("::%s::" % module_name, "")
+ if not is_custom:
+ # Only works when the full namespace is removed
+ # and if there is a "using namespace"
+ keys["defs"] = keys["defs"].replace("::%s::" % module_name, "")
content = cpp_body.format(**keys)
if self.opts.exdec:
```
With this I'm even able to have the same name for the python module and my project root namespace name.
## Postscriptum
On a side note, it would be nice to tell that all the free functions shall go in `modulename.geometry` without having to repeat ourselves. IOW, to put the `customization.namespace` key at the upper `namespaces:` level.https://gitlab.kitware.com/autopybind11/autopybind11/-/issues/200[HOWTO] Add module level constants2021-10-17T21:56:54-04:00Amal Khailtash[HOWTO] Add module level constantsHow can one expose constant (#defines, or const) values from c++ side to python module variables?
```
#define VERSION "1.0"
const int H = 2;
```How can one expose constant (#defines, or const) values from c++ side to python module variables?
```
#define VERSION "1.0"
const int H = 2;
```https://gitlab.kitware.com/autopybind11/autopybind11/-/issues/199'os: std::ostream' in method '<class '???'>.print' into a Python object (type...2021-10-13T15:23:09-04:00Amal Khailtash'os: std::ostream' in method '<class '???'>.print' into a Python object (type not registered yet?)I am trying to generate binding for a C++ class library. The generated for a class method looks like this:
`.def("print", static_cast<void ( sc_bit::* )( ::std::ostream & )const>(&sc_bit::print), py::arg("os") = (::std::ostream &)std::...I am trying to generate binding for a C++ class library. The generated for a class method looks like this:
`.def("print", static_cast<void ( sc_bit::* )( ::std::ostream & )const>(&sc_bit::print), py::arg("os") = (::std::ostream &)std::cout)`
For the method defined as:
`void print( ::std::ostream& os = std::cout ) const;`
And I get this error when I import the resulting module:
`ImportError: arg(): could not convert default argument 'os: std::ostream' in method '<class '?'>.print' into a Python object (type not registered yet?)`https://gitlab.kitware.com/autopybind11/autopybind11/-/issues/198AutoPyBind11 doesn't ensure output directory exists2021-07-13T15:29:18-04:00Joe SnyderAutoPyBind11 doesn't ensure output directory existsIf given an non-existing output, APB fails when trying to write the MDX file for the module it is acting upon. Ensure that the output_dir exists at the start of executionIf given an non-existing output, APB fails when trying to write the MDX file for the module it is acting upon. Ensure that the output_dir exists at the start of executionhttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/197Unnecessary calls to write_non_class_data2021-04-20T19:47:29-04:00John ParentUnnecessary calls to write_non_class_dataGenerate_bindings calls write_non_class_data multiple times for the top level module, which can lead to unexpected behavior. This was caused by the transition from having namespaces be the top level yaml object in the wrapper to files. C...Generate_bindings calls write_non_class_data multiple times for the top level module, which can lead to unexpected behavior. This was caused by the transition from having namespaces be the top level yaml object in the wrapper to files. Currently not causing any problems but can lead to very confusing behavior during development, and is a waste of multiple writes.John ParentJohn Parenthttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/196Add "python_warnings_as_errors" flag2021-04-09T13:33:12-04:00Joe SnyderAdd "python_warnings_as_errors" flagWhen !172 is merged, all warnings are now handled via the "warnings" library. This will allow us to perform a similar operation as "-Werror" by informing the warnings module to turn warnings into errors: https://docs.python.org/3/librar...When !172 is merged, all warnings are now handled via the "warnings" library. This will allow us to perform a similar operation as "-Werror" by informing the warnings module to turn warnings into errors: https://docs.python.org/3/library/warnings.html#the-warnings-filter
Add new flag to do so
Suggested by @john.parenthttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/194Should denoise first-party namespace usage in generated bindings; strip globa...2021-04-06T17:21:26-04:00Eric CousineauShould denoise first-party namespace usage in generated bindings; strip global ns qualifier toowill expandwill expandJohn ParentJohn Parenthttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/193Should attempt denoising stdc++ and Eigen types2021-04-06T17:21:26-04:00Eric CousineauShould attempt denoising stdc++ and Eigen typesIn r14 of https://github.com/RobotLocomotion/drake/pull/14265, there are some noisy expansions (denoted in Reviewable comments).
Most cases seem to be expansions of default template parameters, contrasting to how they are used in source...In r14 of https://github.com/RobotLocomotion/drake/pull/14265, there are some noisy expansions (denoted in Reviewable comments).
Most cases seem to be expansions of default template parameters, contrasting to how they are used in source code (and IMO in their most review-friendly state)
```cc
"mutable_descriptor",
static_cast<::Eigen::Ref<Eigen::Matrix<float, -1, 1, 0, -1, 1>, 0,
Eigen::InnerStride<1>> (PointCloud::*)(int)>(
&PointCloud::mutable_descriptor),
...
static_cast<::Eigen::Quaternion<drake::AutoDiffXd, 0> (
RotationMatrix<drake::AutoDiffXd>::*)() const>(
&RotationMatrix<drake::AutoDiffXd>::ToQuaternion))
...
.def(
"DeclareVectorOutputPort",
static_cast<LeafOutputPort<drake::AutoDiffXd> &(
LeafSystem<drake::AutoDiffXd>::
*)(BasicVector<drake::AutoDiffXd> const &,
LeafOutputPort<drake::AutoDiffXd>::CalcVectorCallback,
::std::set<
drake::TypeSafeIndex<DependencyTag>,
std::less<drake::TypeSafeIndex<DependencyTag>>,
std::allocator<drake::TypeSafeIndex<DependencyTag>>>)>(
&LeafSystem_Eigen_AutoDiffScalar_Eigen_VectorXd_publicist::
DeclareVectorOutputPort),
py::arg("model_vector"), py::arg("vector_calc_function"),
py::arg("prerequisites_of_calc") =
::std::set<drake::TypeSafeIndex<DependencyTag>,
std::less<drake::TypeSafeIndex<DependencyTag>>,
std::allocator<drake::TypeSafeIndex<DependencyTag>>>(
{SystemBase::all_sources_ticket()}))
```https://gitlab.kitware.com/autopybind11/autopybind11/-/issues/192Should enable TRI/Drake workflow for template instantiations2021-03-25T11:18:47-04:00Eric CousineauShould enable TRI/Drake workflow for template instantiationswill fill w/ details contrasting sln in !168 and how add'l work is necessary to use Drake-specific things.will fill w/ details contrasting sln in !168 and how add'l work is necessary to use Drake-specific things.https://gitlab.kitware.com/autopybind11/autopybind11/-/issues/190Code customization is out of sync with real values2021-03-29T10:54:41-04:00Joe SnyderCode customization is out of sync with real valuesThe table in the README which describes the CONFIG options is not only incomplete from a paragraph standpoint (https://gitlab.kitware.com/autopybind11/autopybind11/-/blob/master/README.rst#L391)
The content of the table is not the same ...The table in the README which describes the CONFIG options is not only incomplete from a paragraph standpoint (https://gitlab.kitware.com/autopybind11/autopybind11/-/blob/master/README.rst#L391)
The content of the table is not the same as the flags in the `__main__.py` file.
Resync the variable names.Joe SnyderJoe Snyderhttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/188Should add a public API as entrypoint, not just cmdline?2021-03-18T11:41:38-04:00Eric CousineauShould add a public API as entrypoint, not just cmdline?Relates to #10 (code setup, etc.)
Relates to #164
Motivated by things like #175
If there are more complex customizations not expressible via YAML / dictionaries of strings/ints, it'd be nice to have code / functions.Relates to #10 (code setup, etc.)
Relates to #164
Motivated by things like #175
If there are more complex customizations not expressible via YAML / dictionaries of strings/ints, it'd be nice to have code / functions.https://gitlab.kitware.com/autopybind11/autopybind11/-/issues/187Should allow preference towards bindings functions/methods using lambdas, not...2021-03-18T11:37:20-04:00Eric CousineauShould allow preference towards bindings functions/methods using lambdas, not just static_castSee: https://github.com/RobotLocomotion/drake/pull/14265#issuecomment-802027890See: https://github.com/RobotLocomotion/drake/pull/14265#issuecomment-802027890https://gitlab.kitware.com/autopybind11/autopybind11/-/issues/185drake::systems::LeafSystem<T> isn't being seen as trampoline?2021-03-18T11:32:12-04:00Eric Cousineaudrake::systems::LeafSystem<T> isn't being seen as trampoline?See:
https://github.com/RobotLocomotion/drake/blob/a28defe1b0a35b73a64d759dcd98e1d0fcdd6dd1/tmp/autopybind11/LeafSystem_py.cpp#L197-L198
And related comment in PR: https://github.com/RobotLocomotion/drake/pull/14265See:
https://github.com/RobotLocomotion/drake/blob/a28defe1b0a35b73a64d759dcd98e1d0fcdd6dd1/tmp/autopybind11/LeafSystem_py.cpp#L197-L198
And related comment in PR: https://github.com/RobotLocomotion/drake/pull/14265https://gitlab.kitware.com/autopybind11/autopybind11/-/issues/183drake FormulaCell: castxml / pygccxml marking as incomplete?2021-03-04T11:35:26-05:00Eric Cousineaudrake FormulaCell: castxml / pygccxml marking as incomplete?Encountered in : \
https://github.com/josephsnyder/drake/pull/3
This can be found via Drake's `mkdoc`; see full raw file: \
https://raw.githubusercontent.com/josephsnyder/drake/32bc2657806ef6e16b41eb45322c475d187cc433/tmp/autopybind11/d...Encountered in : \
https://github.com/josephsnyder/drake/pull/3
This can be found via Drake's `mkdoc`; see full raw file: \
https://raw.githubusercontent.com/josephsnyder/drake/32bc2657806ef6e16b41eb45322c475d187cc433/tmp/autopybind11/documentation_pybind.h
Relevant snippet:
```cc
// Symbol: drake::symbolic::FormulaCell
struct /* FormulaCell */ {
// Source: drake/common/symbolic_formula_cell.h:33
const char* doc =
R"""(Represents an abstract class which is the base of concrete
symbolic-formula classes (i.e. symbolic::FormulaAnd,
symbolic::FormulaEq).
Note:
It provides virtual function, FormulaCell::Display, because
operator<< is not allowed to be a virtual function.)""";
// Symbol: drake::symbolic::FormulaCell::Display
struct /* Display */ {
// Source: drake/common/symbolic_formula_cell.h:56
const char* doc =
R"""(Outputs string representation of formula into output stream ``os``.)""";
} Display;
// Symbol: drake::symbolic::FormulaCell::EqualTo
struct /* EqualTo */ {
// Source: drake/common/symbolic_formula_cell.h:45
const char* doc = R"""(Checks structural equality.)""";
} EqualTo;
// Symbol: drake::symbolic::FormulaCell::Evaluate
struct /* Evaluate */ {
// Source: drake/common/symbolic_formula_cell.h:49
const char* doc = R"""(Evaluates under a given environment.)""";
} Evaluate;
// Symbol: drake::symbolic::FormulaCell::FormulaCell
struct /* ctor */ {
// Source: drake/common/symbolic_formula_cell.h:59
const char* doc_0args = R"""(Default constructor (deleted).)""";
// Source: drake/common/symbolic_formula_cell.h:69
const char* doc_move =
R"""(Move-construct a formula from an rvalue.)""";
// Source: drake/common/symbolic_formula_cell.h:71
const char* doc_copy =
R"""(Copy-construct a formula from an lvalue.)""";
// Source: drake/common/symbolic_formula_cell.h:73
const char* doc_1args = R"""(Construct FormulaCell of kind ``k``.)""";
} ctor;
// Symbol: drake::symbolic::FormulaCell::GetFreeVariables
struct /* GetFreeVariables */ {
// Source: drake/common/symbolic_formula_cell.h:43
const char* doc =
R"""(Returns set of free variables in formula.)""";
} GetFreeVariables;
// Symbol: drake::symbolic::FormulaCell::HashAppendDetail
struct /* HashAppendDetail */ {
// Source: drake/common/symbolic_formula_cell.h:41
const char* doc =
R"""(Sends all hash-relevant bytes for this FormulaCell type into the given
hasher, per the hash_append concept -- except for get_kind(), because
Formula already sends that.)""";
} HashAppendDetail;
// Symbol: drake::symbolic::FormulaCell::Less
struct /* Less */ {
// Source: drake/common/symbolic_formula_cell.h:47
const char* doc = R"""(Checks ordering.)""";
} Less;
// Symbol: drake::symbolic::FormulaCell::Substitute
struct /* Substitute */ {
// Source: drake/common/symbolic_formula_cell.h:54
const char* doc =
R"""(Returns a Formula obtained by replacing all occurrences of the
variables in ``s`` in the current formula cell with the corresponding
expressions in ``s``.)""";
} Substitute;
// Symbol: drake::symbolic::FormulaCell::get_kind
struct /* get_kind */ {
// Source: drake/common/symbolic_formula_cell.h:36
const char* doc = R"""(Returns kind of formula.)""";
} get_kind;
} FormulaCell;
```Joe SnyderJoe Snyderhttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/179Should leverage aliases, `using`, and/or `using namespace` statements in bind...2021-03-19T15:37:50-04:00Eric CousineauShould leverage aliases, `using`, and/or `using namespace` statements in bindings code to make more human-readable> Current pain point:
> These bindings, using fully-expanded type names with static_cast, are extremely hard to read, and thus would be extremely hard to review in a PR bootstrapping with this tool.
>
> See more readable example:
> http...> Current pain point:
> These bindings, using fully-expanded type names with static_cast, are extremely hard to read, and thus would be extremely hard to review in a PR bootstrapping with this tool.
>
> See more readable example:
> https://github.com/RobotLocomotion/drake/blob/v0.27.0/bindings/pydrake/autodiffutils_py.cc#L38
>
> .def(py::init<const double&, const VectorXd&>())
Direct link to comment: https://github.com/josephsnyder/drake/pull/3#pullrequestreview-598811089
EDIT(eric): For reference, here're the current generated bindings (using 89fecfb)
https://github.com/josephsnyder/drake/blob/32bc2657806ef6e16b41eb45322c475d187cc433/tmp/autopybind11/AutoDiffXd_py.cpp#L22
```
.def(py::init<Eigen::Ref<::Eigen::AutoDiffScalar<Eigen::Matrix<double, -1, 1, 0, -1, 1>>::Scalar const &, 0, Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>> &,Eigen::Ref<::Eigen::AutoDiffScalar<Eigen::Matrix<double, -1, 1, 0, -1, 1>>::DerType const &, 0, Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>> &>(),py::arg("value"),py::arg("der"))
```Joe SnyderJoe Snyderhttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/172PyBind11: Add member variable docstring parsing?2021-02-18T10:07:54-05:00Joe SnyderPyBind11: Add member variable docstring parsing?`.def_readwrite("field_obj", &::simple::field_obj,"/*! variable comment with multiple lines */")`
simply returns the docstring of an int field:
```
>>> print(simple.field_obj.__doc__)
int(x=0) -> integer
int(x, base=10) -> integer
Con...`.def_readwrite("field_obj", &::simple::field_obj,"/*! variable comment with multiple lines */")`
simply returns the docstring of an int field:
```
>>> print(simple.field_obj.__doc__)
int(x=0) -> integer
int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments
are given. If x is a number, return x.__int__(). For floating point
numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string,
bytes, or bytearray instance representing an integer literal in the
given base. The literal can be preceded by '+' or '-' and be surrounded
by whitespace. The base defaults to 10. Valid bases are 0 and 2-36.
Base 0 means to interpret the base from the string as an integer literal.
>>> int('0b100', base=0)
4
```
Determine if an update to pybind11 is necessary to properly add docstrings to the member variablesJohn ParentJohn Parenthttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/168Add test for binding sub-routine `static bool called` check; see if it can be...2021-03-18T11:36:12-04:00Joe SnyderAdd test for binding sub-routine `static bool called` check; see if it can be removedExercise the guards for the early returns which prevent a initialization function from trying to execute more than once
This test should basically import the same module twice, if I understand things correctly.
From VC - more specific ...Exercise the guards for the early returns which prevent a initialization function from trying to execute more than once
This test should basically import the same module twice, if I understand things correctly.
From VC - more specific to this part:
https://gitlab.kitware.com/autopybind11/autopybind11/-/blob/89fecfb3a3c763f6ca63106796ff5c9e6de63872/Tests/code_generation_regression/expected/A_py.cpp#L12-14Joe SnyderJoe Snyderhttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/165Minor code cleanup and optimization2021-01-26T15:22:32-05:00John ParentMinor code cleanup and optimizationSome of the filtering and general binding code is redundant/slow and could use a quick cleanup. I'll take care of this, I just wanted to document that this was something that was going on.Some of the filtering and general binding code is redundant/slow and could use a quick cleanup. I'll take care of this, I just wanted to document that this was something that was going on.John ParentJohn Parenthttps://gitlab.kitware.com/autopybind11/autopybind11/-/issues/164Proposal: Replacing YAML with Python2021-03-18T11:41:18-04:00Jon CrallProposal: Replacing YAML with PythonThis is a quick dump of the brainstorming session where I proposed the YAML file could be replaced with a Python file.
This would allow
1. Similar syntactic ease to yaml
2. Improved customization ability by being able to execute runt...This is a quick dump of the brainstorming session where I proposed the YAML file could be replaced with a Python file.
This would allow
1. Similar syntactic ease to yaml
2. Improved customization ability by being able to execute runtime postprocessing on result of C++ calls.
The idea is given a CPP file, perhaps you define some before.py file that specifies any configuration that would have existed in the YAML file
```python
import autopybind
autopybind.wrap_definitions_from_local_cpp_files()
defs = autopybind.wrap(
'''
files:
non_template/derived2.hpp:
namespaces:
nmspc1:
namespaces:
nmspc2:
classes:
Derived2:
protectedClass:
functions:
call_virt_from_derived2:
'''
)
class Customization(defs['nmspc1.nmspc2.Derived2']):
pass
__autopybind__ = {
'namespace': 'nmspc1.nmspc2',
'file': 'non_template/derived2.hpp',
}
class Derived2:
"""
Custom documentation for my python binding
Example:
>>> self = Derived2()
>>> self.custom_behavior()
# TELL the user what to expect on the PYTHON side
"""
__autopybind__ = {
'functions': [
'call_virt_from_derived2',
]
}
def custom_behavior(self):
x = self.call_virt_from_derived2()
x = x + 1
return x
```
And then this either generates an "after.py" file in the build directory:
```
from _derived2 import _APB_Derived2
class Derived2(_Derived2):
"""
Custom documentation for my python binding
"""
def custom_behavior(self):
x = self.call_virt_from_derived2()
x = x + 1
return x
```
That is either a modified version of the before file, or ideally the same exact file (which would allow for symlinking the source to the build tree and make hacking on the python bindings easier).
The above code is psudocode and contains half-baked ideas for what the syntax of the code would be.
At build time autopybind would
1. read the python configuration file (either dynamically, maybe via `ubelt.import_module_from_file`) or statically (via parsing it with Python's builtin AST module).
2. use the information to gather the information needed to generate the real pybind11 CPP code.
3. compile the real pybind11 CPP code into a private / protected `_after.so` python module.
4. The `after.py` file imports the `_after.so` module and does any python-side manipulations that need to occur to cleanly manage the CPP data structure (if there needs to be any of these at all).
This idea is quite raw and there are lots of things that could be enhanced given a basic implementation (e.g. seemless access to templated data types based on either runtime type introspection or explicit `__getattr__` methods).