-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
[BUG] Unbound methods should just be functions instead of instancemethod #2722
Comments
That's very unfortunate. Seems that the I'm not sure how pybind11 is to blame for this bug, and not even how pybind11 could fix this, though. What did you have in mind? |
Hi Yannick, since they stopped using instancemethod in cython, which solved the issue, maybe the same can be done in pybind11? (See cython/cython#2105 which is mentioned in the pprint bug). I don't know the details but I'm under the impression that instancemethod is obsolete for python 3 (e.g. https://stackoverflow.com/q/4364565). |
@beatmax Hmmm, if that would somehow be efficient and not cause any other problems, it's something to consider, yes. I'm not sure if there was an explicit reason to go with It might be nice to rephrase the title of your issue, then? This doesn't exactly make your issue clear. |
And replaced it with what exactly? According to https://docs.python.org/3/c-api/method.html, the alternative is
Sometimes I really hate python... |
Here is what they did: cython/cython@a152462 Change the title to "Unbound methods should just be functions instead of instancemethod"? (based on the title of cython's PR) |
It would have been lovely if pybind11 could have just as easy a fix. Here's my first attempt: diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h
index 65dad5a..09d263d 100644
--- a/include/pybind11/detail/class.h
+++ b/include/pybind11/detail/class.h
@@ -158,7 +158,7 @@ extern "C" inline int pybind11_meta_setattro(PyObject* obj, PyObject* name, PyOb
*/
extern "C" inline PyObject *pybind11_meta_getattro(PyObject *obj, PyObject *name) {
PyObject *descr = _PyType_Lookup((PyTypeObject *) obj, name);
- if (descr && PyInstanceMethod_Check(descr)) {
+ if (descr && PyCFunction_Check(descr)) {
Py_INCREF(descr);
return descr;
}
diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h
index 56385f5..cb2d05f 100644
--- a/include/pybind11/detail/common.h
+++ b/include/pybind11/detail/common.h
@@ -162,9 +162,9 @@
#include <type_traits>
#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions
-#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr)
-#define PYBIND11_INSTANCE_METHOD_CHECK PyInstanceMethod_Check
-#define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyInstanceMethod_GET_FUNCTION
+#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) (Py_XINCREF(ptr), ptr)
+#define PYBIND11_INSTANCE_METHOD_CHECK PyCFunction_Check
+#define PYBIND11_INSTANCE_METHOD_GET_FUNCTION(func) func
#define PYBIND11_BYTES_CHECK PyBytes_Check
#define PYBIND11_BYTES_FROM_STRING PyBytes_FromString
#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize
@@ -192,7 +192,7 @@
#else
#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyMethod_New(ptr, nullptr, class_)
#define PYBIND11_INSTANCE_METHOD_CHECK PyMethod_Check
-#define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyMethod_GET_FUNCTION
+#define PYBIND11_INSTANCE_METHOD_GET_FUNCTION(func) PyMethod_GET_FUNCTION(func)
#define PYBIND11_BYTES_CHECK PyString_Check
#define PYBIND11_BYTES_FROM_STRING PyString_FromString
#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyString_FromStringAndSize
diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h
index 1010ad7..4c28458 100644
--- a/include/pybind11/pytypes.h
+++ b/include/pybind11/pytypes.h
@@ -466,8 +466,8 @@ PYBIND11_NAMESPACE_BEGIN(detail)
inline handle get_function(handle value) {
if (value) {
#if PY_MAJOR_VERSION >= 3
- if (PyInstanceMethod_Check(value.ptr()))
- value = PyInstanceMethod_GET_FUNCTION(value.ptr());
+ if (PyCFunction_Check(value.ptr()))
+ value = value;
else
#endif
if (PyMethod_Check(value.ptr())) Basically, 3 things:
That segfaults.
As you can see, the |
This is not going to work... A pybind11 function is actually a "closure" (or "function object") of a C function capturing a
|
I've already been playing around with subclassing This is full of hack, but works: diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h
index 2f414e5c..778de079 100644
--- a/include/pybind11/detail/class.h
+++ b/include/pybind11/detail/class.h
@@ -41,6 +41,41 @@ inline PyTypeObject *type_incref(PyTypeObject *type) {
return type;
}
+inline PyObject *pybind11_function_descr_get(PyObject *self, PyObject *obj, PyObject *) {
+ if (obj == NULL) {
+ Py_INCREF(self);
+ return self;
+ }
+ else
+ return PyMethod_New(self, obj);
+}
+
+inline PyTypeObject *make_pybind11_function_type() {
+ constexpr auto *name = "pybind11_function";
+
+ auto heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
+ if (!heap_type)
+ pybind11_fail("make_pybind11_function_type(): error allocating type!");
+
+ auto type = &heap_type->ht_type;
+ type->tp_name = name;
+ type->tp_base = type_incref(&PyCFunction_Type);
+ type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
+ type->tp_setattro = PyObject_GenericSetAttr;
+ type->tp_descr_get = pybind11_function_descr_get;
+ type->tp_getset = PyCFunction_Type.tp_getset;
+
+ if (PyType_Ready(type) < 0)
+ pybind11_fail("make_pybind11_function_type(): failure in PyType_Ready()!");
+
+ return type;
+}
+
+inline PyTypeObject *get_pybind11_function_type() {
+ static auto type = make_pybind11_function_type();
+ return type;
+}
+
#if !defined(PYPY_VERSION)
/// `pybind11_static_property.__get__()`: Always pass the class instead of the instance.
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
index 82003a90..404c9c1c 100644
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -370,6 +370,7 @@ protected:
}
m_ptr = PyCFunction_NewEx(rec->def, rec_capsule.ptr(), scope_module.ptr());
+ m_ptr->ob_type = detail::get_pybind11_function_type();
if (!m_ptr)
pybind11_fail("cpp_function::cpp_function(): Could not allocate function object");
} else {
@@ -443,12 +444,12 @@ protected:
// Install docstring if it's non-empty (when at least one option is enabled)
func->m_ml->ml_doc = signatures.empty() ? nullptr : strdup(signatures.c_str());
- if (rec->is_method) {
- m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr());
- if (!m_ptr)
- pybind11_fail("cpp_function::cpp_function(): Could not allocate instance method object");
- Py_DECREF(func);
- }
+ // if (rec->is_method) {
+ // m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr());
+ // if (!m_ptr)
+ // pybind11_fail("cpp_function::cpp_function(): Could not allocate instance method object");
+ // Py_DECREF(func);
+ // }
}
/// When a cpp_function is GCed, release any memory allocated by pybind11
diff --git a/tests/test_constants_and_functions.py b/tests/test_constants_and_functions.py
index b980ccf1..b41ab439 100644
--- a/tests/test_constants_and_functions.py
+++ b/tests/test_constants_and_functions.py
@@ -40,3 +40,11 @@ def test_exception_specifiers():
assert m.f2(53) == 55
assert m.f3(86) == 89
assert m.f4(140) == 144
+
+
+def test_function_hash():
+ c = m.C()
+ assert hash(c.m1) != hash(c.m2)
+ assert hash(m.C.m1) != hash(m.C.m2)
+
+ assert hash(m.f1) != hash(m.f2) But there's a lot of discussion to be have. In the first place whether adding yet another function type is a great idea, and whether subclassing is a good idea. Secondly whether we want to extend Also, the But given that pybind11 has had things this way since ages and complaints about hashing method are very rare, I don't believe this is currently very close to the top of the TODO list. |
I run into this hashing issue everytime an assertion involving a python object backed by pybind11 fails in a pytest unit test, because pytest tries to look the |
There is a related issue: functions created with cpp_function are not picklable. Note that |
There are some failures with `gnpy` on Windows: ================================== FAILURES =================================== ____________ test_lint_yang[ietf-network-topology@2018-02-26.yang] ____________ yang_model = WindowsPath('D:/a/oopt-gnpy/oopt-gnpy/gnpy/yang/ext/ietf-network-topology@2018-02-26.yang') @pytest.mark.parametrize("yang_model", [x for x in external_path().glob('*.yang')] + [x for x in model_path().glob('*.yang')], ids=_get_basename) def test_lint_yang(yang_model): '''Run a linter on each YANG model''' c = ly.Context(str(external_path()) + os.pathsep + str(model_path()), ly.ContextOptions.NoYangLibrary | ly.ContextOptions.DisableSearchCwd) assert c.parse_module(yang_model, ly.SchemaFormat.YANG) is not None > assert c.errors() == [] E assert <[TypeError("unhashable type: 'instancemethod'") raised in repr()] list object at 0x1880e5958c0> == [] E (pytest_assertion plugin: representation of details failed: C:\hostedtoolcache\windows\Python\3.11.4\x64\Lib\pprint.py:178: TypeError: unhashable type: 'instancemethod'. E Probably an object has a faulty __repr__.) tests\test_yang_lint.py:30: AssertionError ---------------------------- Captured stderr call ----------------------------- libyang[1]: File name "D:\a\oopt-gnpy\oopt-gnpy\gnpy\yang\ext\ietf-network-topology@2018-02-26.yang" does not match module name "ietf-network-topology". ________________ test_lint_yang[ietf-network@2018-02-26.yang] _________________ The actual error is pybind/pybind11#2722, and the warnings are due to libyang assuming that the path separator is `/`, which is not the case on Windows, but atthis point I don't know whether the warning about filename vs. module name mismatch is the root cause or just another wanring to fix.
There are some failures with `gnpy` on Windows: ================================== FAILURES =================================== ____________ test_lint_yang[ietf-network-topology@2018-02-26.yang] ____________ yang_model = WindowsPath('D:/a/oopt-gnpy/oopt-gnpy/gnpy/yang/ext/ietf-network-topology@2018-02-26.yang') @pytest.mark.parametrize("yang_model", [x for x in external_path().glob('*.yang')] + [x for x in model_path().glob('*.yang')], ids=_get_basename) def test_lint_yang(yang_model): '''Run a linter on each YANG model''' c = ly.Context(str(external_path()) + os.pathsep + str(model_path()), ly.ContextOptions.NoYangLibrary | ly.ContextOptions.DisableSearchCwd) assert c.parse_module(yang_model, ly.SchemaFormat.YANG) is not None > assert c.errors() == [] E assert <[TypeError("unhashable type: 'instancemethod'") raised in repr()] list object at 0x1880e5958c0> == [] E (pytest_assertion plugin: representation of details failed: C:\hostedtoolcache\windows\Python\3.11.4\x64\Lib\pprint.py:178: TypeError: unhashable type: 'instancemethod'. E Probably an object has a faulty __repr__.) tests\test_yang_lint.py:30: AssertionError ---------------------------- Captured stderr call ----------------------------- libyang[1]: File name "D:\a\oopt-gnpy\oopt-gnpy\gnpy\yang\ext\ietf-network-topology@2018-02-26.yang" does not match module name "ietf-network-topology". ________________ test_lint_yang[ietf-network@2018-02-26.yang] _________________ The actual error is pybind/pybind11#2722, and the warnings are due to libyang assuming that the path separator is `/`, which is not the case on Windows, but atthis point I don't know whether the warning about filename vs. module name mismatch is the root cause or just another wanring to fix.
There are some failures with `gnpy` on Windows: ================================== FAILURES =================================== ____________ test_lint_yang[ietf-network-topology@2018-02-26.yang] ____________ yang_model = WindowsPath('D:/a/oopt-gnpy/oopt-gnpy/gnpy/yang/ext/ietf-network-topology@2018-02-26.yang') @pytest.mark.parametrize("yang_model", [x for x in external_path().glob('*.yang')] + [x for x in model_path().glob('*.yang')], ids=_get_basename) def test_lint_yang(yang_model): '''Run a linter on each YANG model''' c = ly.Context(str(external_path()) + os.pathsep + str(model_path()), ly.ContextOptions.NoYangLibrary | ly.ContextOptions.DisableSearchCwd) assert c.parse_module(yang_model, ly.SchemaFormat.YANG) is not None > assert c.errors() == [] E assert <[TypeError("unhashable type: 'instancemethod'") raised in repr()] list object at 0x1880e5958c0> == [] E (pytest_assertion plugin: representation of details failed: C:\hostedtoolcache\windows\Python\3.11.4\x64\Lib\pprint.py:178: TypeError: unhashable type: 'instancemethod'. E Probably an object has a faulty __repr__.) tests\test_yang_lint.py:30: AssertionError ---------------------------- Captured stderr call ----------------------------- libyang[1]: File name "D:\a\oopt-gnpy\oopt-gnpy\gnpy\yang\ext\ietf-network-topology@2018-02-26.yang" does not match module name "ietf-network-topology". ________________ test_lint_yang[ietf-network@2018-02-26.yang] _________________ The actual error is pybind/pybind11#2722, and the warnings are due to libyang assuming that the path separator is `/`, which is not the case on Windows, but atthis point I don't know whether the warning about filename vs. module name mismatch is the root cause or just another wanring to fix.
There are some failures with `gnpy` on Windows: ================================== FAILURES =================================== ____________ test_lint_yang[ietf-network-topology@2018-02-26.yang] ____________ yang_model = WindowsPath('D:/a/oopt-gnpy/oopt-gnpy/gnpy/yang/ext/ietf-network-topology@2018-02-26.yang') @pytest.mark.parametrize("yang_model", [x for x in external_path().glob('*.yang')] + [x for x in model_path().glob('*.yang')], ids=_get_basename) def test_lint_yang(yang_model): '''Run a linter on each YANG model''' c = ly.Context(str(external_path()) + os.pathsep + str(model_path()), ly.ContextOptions.NoYangLibrary | ly.ContextOptions.DisableSearchCwd) assert c.parse_module(yang_model, ly.SchemaFormat.YANG) is not None > assert c.errors() == [] E assert <[TypeError("unhashable type: 'instancemethod'") raised in repr()] list object at 0x1880e5958c0> == [] E (pytest_assertion plugin: representation of details failed: C:\hostedtoolcache\windows\Python\3.11.4\x64\Lib\pprint.py:178: TypeError: unhashable type: 'instancemethod'. E Probably an object has a faulty __repr__.) tests\test_yang_lint.py:30: AssertionError ---------------------------- Captured stderr call ----------------------------- libyang[1]: File name "D:\a\oopt-gnpy\oopt-gnpy\gnpy\yang\ext\ietf-network-topology@2018-02-26.yang" does not match module name "ietf-network-topology". ________________ test_lint_yang[ietf-network@2018-02-26.yang] _________________ The actual error is pybind/pybind11#2722, and the warnings are due to libyang assuming that the path separator is `/`, which is not the case on Windows, but atthis point I don't know whether the warning about filename vs. module name mismatch is the root cause or just another wanring to fix.
There are some failures with `gnpy` on Windows: ================================== FAILURES =================================== ____________ test_lint_yang[ietf-network-topology@2018-02-26.yang] ____________ yang_model = WindowsPath('D:/a/oopt-gnpy/oopt-gnpy/gnpy/yang/ext/ietf-network-topology@2018-02-26.yang') @pytest.mark.parametrize("yang_model", [x for x in external_path().glob('*.yang')] + [x for x in model_path().glob('*.yang')], ids=_get_basename) def test_lint_yang(yang_model): '''Run a linter on each YANG model''' c = ly.Context(str(external_path()) + os.pathsep + str(model_path()), ly.ContextOptions.NoYangLibrary | ly.ContextOptions.DisableSearchCwd) assert c.parse_module(yang_model, ly.SchemaFormat.YANG) is not None > assert c.errors() == [] E assert <[TypeError("unhashable type: 'instancemethod'") raised in repr()] list object at 0x1880e5958c0> == [] E (pytest_assertion plugin: representation of details failed: C:\hostedtoolcache\windows\Python\3.11.4\x64\Lib\pprint.py:178: TypeError: unhashable type: 'instancemethod'. E Probably an object has a faulty __repr__.) tests\test_yang_lint.py:30: AssertionError ---------------------------- Captured stderr call ----------------------------- libyang[1]: File name "D:\a\oopt-gnpy\oopt-gnpy\gnpy\yang\ext\ietf-network-topology@2018-02-26.yang" does not match module name "ietf-network-topology". ________________ test_lint_yang[ietf-network@2018-02-26.yang] _________________ The actual error is pybind/pybind11#2722, and the warnings are due to libyang assuming that the path separator is `/`, which is not the case on Windows, but atthis point I don't know whether the warning about filename vs. module name mismatch is the root cause or just another wanring to fix.
There are some failures with `gnpy` on Windows: ================================== FAILURES =================================== ____________ test_lint_yang[ietf-network-topology@2018-02-26.yang] ____________ yang_model = WindowsPath('D:/a/oopt-gnpy/oopt-gnpy/gnpy/yang/ext/ietf-network-topology@2018-02-26.yang') @pytest.mark.parametrize("yang_model", [x for x in external_path().glob('*.yang')] + [x for x in model_path().glob('*.yang')], ids=_get_basename) def test_lint_yang(yang_model): '''Run a linter on each YANG model''' c = ly.Context(str(external_path()) + os.pathsep + str(model_path()), ly.ContextOptions.NoYangLibrary | ly.ContextOptions.DisableSearchCwd) assert c.parse_module(yang_model, ly.SchemaFormat.YANG) is not None > assert c.errors() == [] E assert <[TypeError("unhashable type: 'instancemethod'") raised in repr()] list object at 0x1880e5958c0> == [] E (pytest_assertion plugin: representation of details failed: C:\hostedtoolcache\windows\Python\3.11.4\x64\Lib\pprint.py:178: TypeError: unhashable type: 'instancemethod'. E Probably an object has a faulty __repr__.) tests\test_yang_lint.py:30: AssertionError ---------------------------- Captured stderr call ----------------------------- libyang[1]: File name "D:\a\oopt-gnpy\oopt-gnpy\gnpy\yang\ext\ietf-network-topology@2018-02-26.yang" does not match module name "ietf-network-topology". ________________ test_lint_yang[ietf-network@2018-02-26.yang] _________________ That complaint about __repr__ is an impedance mismatch between pybind11 and Python (pybind/pybind11#2722), but in this case that whole thing is triggered through a bug in libyang which assumes that the directory separator is always `/`. Bug: CESNET/libyang#2093
There are some failures with `gnpy` on Windows: ================================== FAILURES =================================== ____________ test_lint_yang[ietf-network-topology@2018-02-26.yang] ____________ yang_model = WindowsPath('D:/a/oopt-gnpy/oopt-gnpy/gnpy/yang/ext/ietf-network-topology@2018-02-26.yang') @pytest.mark.parametrize("yang_model", [x for x in external_path().glob('*.yang')] + [x for x in model_path().glob('*.yang')], ids=_get_basename) def test_lint_yang(yang_model): '''Run a linter on each YANG model''' c = ly.Context(str(external_path()) + os.pathsep + str(model_path()), ly.ContextOptions.NoYangLibrary | ly.ContextOptions.DisableSearchCwd) assert c.parse_module(yang_model, ly.SchemaFormat.YANG) is not None > assert c.errors() == [] E assert <[TypeError("unhashable type: 'instancemethod'") raised in repr()] list object at 0x1880e5958c0> == [] E (pytest_assertion plugin: representation of details failed: C:\hostedtoolcache\windows\Python\3.11.4\x64\Lib\pprint.py:178: TypeError: unhashable type: 'instancemethod'. E Probably an object has a faulty __repr__.) tests\test_yang_lint.py:30: AssertionError ---------------------------- Captured stderr call ----------------------------- libyang[1]: File name "D:\a\oopt-gnpy\oopt-gnpy\gnpy\yang\ext\ietf-network-topology@2018-02-26.yang" does not match module name "ietf-network-topology". ________________ test_lint_yang[ietf-network@2018-02-26.yang] _________________ That complaint about __repr__ is an impedance mismatch between pybind11 and Python (pybind/pybind11#2722), but in this case that whole thing is triggered through a bug in libyang which assumes that the directory separator is always `/`. Bug: CESNET/libyang#2093
There are some failures with `gnpy` on Windows: ================================== FAILURES =================================== ____________ test_lint_yang[ietf-network-topology@2018-02-26.yang] ____________ yang_model = WindowsPath('D:/a/oopt-gnpy/oopt-gnpy/gnpy/yang/ext/ietf-network-topology@2018-02-26.yang') @pytest.mark.parametrize("yang_model", [x for x in external_path().glob('*.yang')] + [x for x in model_path().glob('*.yang')], ids=_get_basename) def test_lint_yang(yang_model): '''Run a linter on each YANG model''' c = ly.Context(str(external_path()) + os.pathsep + str(model_path()), ly.ContextOptions.NoYangLibrary | ly.ContextOptions.DisableSearchCwd) assert c.parse_module(yang_model, ly.SchemaFormat.YANG) is not None > assert c.errors() == [] E assert <[TypeError("unhashable type: 'instancemethod'") raised in repr()] list object at 0x1880e5958c0> == [] E (pytest_assertion plugin: representation of details failed: C:\hostedtoolcache\windows\Python\3.11.4\x64\Lib\pprint.py:178: TypeError: unhashable type: 'instancemethod'. E Probably an object has a faulty __repr__.) tests\test_yang_lint.py:30: AssertionError ---------------------------- Captured stderr call ----------------------------- libyang[1]: File name "D:\a\oopt-gnpy\oopt-gnpy\gnpy\yang\ext\ietf-network-topology@2018-02-26.yang" does not match module name "ietf-network-topology". ________________ test_lint_yang[ietf-network@2018-02-26.yang] _________________ That complaint about __repr__ is an impedance mismatch between pybind11 and Python (pybind/pybind11#2722), but in this case that whole thing is triggered through a bug in libyang which assumes that the directory separator is always `/`. Bug: CESNET/libyang#2093
There are some failures with `gnpy` on Windows: ================================== FAILURES =================================== ____________ test_lint_yang[ietf-network-topology@2018-02-26.yang] ____________ yang_model = WindowsPath('D:/a/oopt-gnpy/oopt-gnpy/gnpy/yang/ext/ietf-network-topology@2018-02-26.yang') @pytest.mark.parametrize("yang_model", [x for x in external_path().glob('*.yang')] + [x for x in model_path().glob('*.yang')], ids=_get_basename) def test_lint_yang(yang_model): '''Run a linter on each YANG model''' c = ly.Context(str(external_path()) + os.pathsep + str(model_path()), ly.ContextOptions.NoYangLibrary | ly.ContextOptions.DisableSearchCwd) assert c.parse_module(yang_model, ly.SchemaFormat.YANG) is not None > assert c.errors() == [] E assert <[TypeError("unhashable type: 'instancemethod'") raised in repr()] list object at 0x1880e5958c0> == [] E (pytest_assertion plugin: representation of details failed: C:\hostedtoolcache\windows\Python\3.11.4\x64\Lib\pprint.py:178: TypeError: unhashable type: 'instancemethod'. E Probably an object has a faulty __repr__.) tests\test_yang_lint.py:30: AssertionError ---------------------------- Captured stderr call ----------------------------- libyang[1]: File name "D:\a\oopt-gnpy\oopt-gnpy\gnpy\yang\ext\ietf-network-topology@2018-02-26.yang" does not match module name "ietf-network-topology". ________________ test_lint_yang[ietf-network@2018-02-26.yang] _________________ That complaint about __repr__ is an impedance mismatch between pybind11 and Python (pybind/pybind11#2722), but in this case that whole thing is triggered through a bug in libyang which assumes that the directory separator is always `/`. Bug: CESNET/libyang#2093
Issue description
Objects of classes created with pybind11 can't be pretty printed with the pprint module if the result is larger than the given width.
This only happens with python3.
It used to happen with cython too, but cython stopped using 'instancemethod', which solved the issue. The pprint bug was discarded because "Functions/methods should be immutable, so yes, I think it is a safe assumption that they should be hashable":
https://bugs.python.org/issue33395
Reproducible example code
example.cpp:
bug.py:
Result:
The text was updated successfully, but these errors were encountered: