From 48315568c4530674ddcc0c3c61913d6ec46958f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ullrich=20K=C3=B6the?= Date: Thu, 2 Nov 2000 17:39:01 +0000 Subject: [PATCH] *** empty log message *** [SVN r8099] --- extclass.h | 13 +++- extclass_demo.cpp | 114 +++++++++++++++++++++++++++++ subclass.h | 4 +- test_extclass.py | 182 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 309 insertions(+), 4 deletions(-) diff --git a/extclass.h b/extclass.h index f6b1ab1a..8ea466cc 100644 --- a/extclass.h +++ b/extclass.h @@ -420,7 +420,11 @@ class ExtensionClass detail::BaseClassInfo baseInfo(base, &detail::DefineConversion::downcast_ptr); ClassRegistry::register_base_class(baseInfo); - add_base(Ptr(as_object(base), Ptr::new_ref)); + + Class* target = (bases().size() == 0) + ? this + : Downcast >(bases()[0].get()).get(); + target->add_base(Ptr(as_object(base), Ptr::new_ref)); detail::DerivedClassInfo derivedInfo(this, &detail::DefineConversion::upcast_ptr); @@ -436,7 +440,12 @@ class ExtensionClass // conversion functions detail::BaseClassInfo baseInfo(base, 0); ClassRegistry::register_base_class(baseInfo); - add_base(Ptr(as_object(base), Ptr::new_ref)); + + Class* target = (bases().size() == 0) + ? this + : Downcast >(bases()[0].get()).get(); + target->add_base(Ptr(as_object(base), Ptr::new_ref)); + detail::DerivedClassInfo derivedInfo(this, &detail::DefineConversion::upcast_ptr); diff --git a/extclass_demo.cpp b/extclass_demo.cpp index 0c281452..331d7371 100644 --- a/extclass_demo.cpp +++ b/extclass_demo.cpp @@ -480,6 +480,81 @@ int testCallback(CallbackTestBase * b, int i) return b->testCallback(i); } +/************************************************************/ +/* */ +/* test classes for interaction of method lookup */ +/* in the context of inheritance */ +/* */ +/************************************************************/ + +struct A1 { + virtual ~A1() {} + virtual const char* overrideA1() const { return "A1::overrideA1"; } + virtual const char* inheritA1() const { return "A1::inheritA1"; } +}; + +struct A2 { + virtual ~A2() {} + virtual const char* inheritA2() const { return "A2::inheritA2"; } +}; + +struct B1 : A1, A2 { + const char* overrideA1() const { return "B1::overrideA1"; } + virtual const char* overrideB1() const { return "B1::overrideB1"; } +}; + +struct B2 : A1, A2 { + const char* overrideA1() const { return "B2::overrideA1"; } + virtual const char* inheritB2() const { return "B2::inheritB2"; } +}; + +struct C : B1 { + const char* overrideB1() const { return "C::overrideB1"; } +}; + +const char* call_overrideA1(const A1& a) { return a.overrideA1(); } +const char* call_overrideB1(const B1& b) { return b.overrideB1(); } +const char* call_inheritA1(const A1& a) { return a.inheritA1(); } + +auto_ptr factoryA1asA1() { return auto_ptr(new A1); } +auto_ptr factoryB1asA1() { return auto_ptr(new B1); } +auto_ptr factoryB2asA1() { return auto_ptr(new B2); } +auto_ptr factoryCasA1() { return auto_ptr(new C); } +auto_ptr factoryA2asA2() { return auto_ptr(new A2); } +auto_ptr factoryB1asA2() { return auto_ptr(new B1); } +auto_ptr factoryB1asB1() { return auto_ptr(new B1); } +auto_ptr factoryCasB1() { return auto_ptr(new C); } + +struct B_callback : B1 { + B_callback(PyObject* self) : m_self(self) {} + + const char* overrideA1() const { return py::Callback::call_method(m_self, "overrideA1"); } + const char* overrideB1() const { return py::Callback::call_method(m_self, "overrideB1"); } + + static const char* default_overrideA1(B1& x) { return x.B1::overrideA1(); } + static const char* default_overrideB1(B1& x) { return x.B1::overrideB1(); } + + PyObject* m_self; +}; + +struct A_callback : A1 { + A_callback(PyObject* self) : m_self(self) {} + + const char* overrideA1() const { return py::Callback::call_method(m_self, "overrideA1"); } + const char* inheritA1() const { return py::Callback::call_method(m_self, "inheritA1"); } + + static const char* default_overrideA1(A1& x) { return x.A1::overrideA1(); } + static const char* default_inheritA1(A1& x) { return x.A1::inheritA1(); } + + PyObject* m_self; +}; + +/************************************************************/ +/* */ +/* Ratio */ +/* */ +/************************************************************/ + typedef boost::rational Ratio; py::String ratio_str(const Ratio& r) @@ -653,6 +728,45 @@ void init_module(py::Module& m) &CallbackTestCallback::default_callbackString); callbackTest.declare_base(callbackTestBase); + + py::ClassWrapper a1_class(m, "A1"); + a1_class.def(py::Constructor<>()); + a1_class.def(&A1::overrideA1, "overrideA1", &A_callback::default_overrideA1); + a1_class.def(&A1::inheritA1, "inheritA1", &A_callback::default_inheritA1); + + py::ClassWrapper a2_class(m, "A2"); + a2_class.def(py::Constructor<>()); + a2_class.def(&A2::inheritA2, "inheritA2"); + + py::ClassWrapper b1_class(m, "B1"); + + // Creates extension class "B_base" + b1_class.def(py::Constructor<>()); + b1_class.def(&B1::overrideA1, "overrideA1", &B_callback::default_overrideA1); + b1_class.def(&B1::overrideB1, "overrideB1", &B_callback::default_overrideB1); + b1_class.declare_base(a1_class); + b1_class.declare_base(a2_class); + + py::ClassWrapper b2_class(m, "B2"); + + b2_class.def(py::Constructor<>()); + b2_class.def(&B2::overrideA1, "overrideA1"); + b2_class.def(&B2::inheritB2, "inheritB2"); + b2_class.declare_base(a1_class); + b2_class.declare_base(a2_class); + + m.def(call_overrideA1, "call_overrideA1"); + m.def(call_overrideB1, "call_overrideB1"); + m.def(call_inheritA1, "call_inheritA1"); + + m.def(factoryA1asA1, "factoryA1asA1"); + m.def(factoryB1asA1, "factoryB1asA1"); + m.def(factoryB2asA1, "factoryB2asA1"); + m.def(factoryCasA1, "factoryCasA1"); + m.def(factoryA2asA2, "factoryA2asA2"); + m.def(factoryB1asA2, "factoryB1asA2"); + m.def(factoryB1asB1, "factoryB1asB1"); + m.def(factoryCasB1, "factoryCasB1"); } void init_module() diff --git a/subclass.h b/subclass.h index 88689a61..7ac27ad3 100644 --- a/subclass.h +++ b/subclass.h @@ -95,10 +95,10 @@ namespace detail { PyObject* getattr(const char* name) const; int setattr(const char* name, PyObject* value); PyObject* repr() const; - + void add_base(Ptr base); + protected: bool initialize_instance(Instance* instance, PyObject* args, PyObject* keywords); - void add_base(Ptr base); private: // virtual functions // Subclasses should override this to delete the particular instance type diff --git a/test_extclass.py b/test_extclass.py index f78c5d0a..ae59a055 100644 --- a/test_extclass.py +++ b/test_extclass.py @@ -657,6 +657,188 @@ Regression test for a reference-counting bug thanks to Mark Evans 0.0 >>> sizelist([1, 2, 4]) 3.0 + +Tests for method lookup in the context of inheritance +Set up the tests + + >>> a1 = A1() + >>> a2 = A2() + >>> b1 = B1() + >>> b2 = B2() + >>> pa1_a1 = factoryA1asA1() + >>> pb1_a1 = factoryB1asA1() + >>> pb2_a1 = factoryB2asA1() + >>> pc_a1 = factoryCasA1() + >>> pa2_a2 = factoryA2asA2() + >>> pb1_a2 = factoryB1asA2() + >>> pb1_b1 = factoryB1asB1() + >>> pc_b1 = factoryCasB1() + >>> class DA1(A1): + ... def overrideA1(self): + ... return 'DA1.overrideA1' + ... + >>> da1 = DA1() + >>> class DB1(B1): + ... def overrideA1(self): + ... return 'DB1.overrideA1' + ... def overrideB1(self): + ... return 'DB1.overrideB1' + ... + >>> db1 = DB1() + >>> class DB2(B2): pass + ... + >>> db2 = DB2() + +test overrideA1 + + >>> a1.overrideA1() + 'A1::overrideA1' + >>> b1.overrideA1() + 'B1::overrideA1' + >>> b2.overrideA1() + 'B2::overrideA1' + >>> da1.overrideA1() + 'DA1.overrideA1' + >>> db1.overrideA1() + 'DB1.overrideA1' + >>> pa1_a1.overrideA1() + 'A1::overrideA1' + >>> pb1_a1.overrideA1() + 'B1::overrideA1' + >>> pb2_a1.overrideA1() + 'B2::overrideA1' + >>> pb1_b1.overrideA1() + 'B1::overrideA1' + >>> pc_a1.overrideA1() + 'B1::overrideA1' + >>> pc_b1.overrideA1() + 'B1::overrideA1' + +test call_overrideA1 + + >>> call_overrideA1(a1) + 'A1::overrideA1' + >>> call_overrideA1(b1) + 'B1::overrideA1' + >>> call_overrideA1(b2) + 'B2::overrideA1' + >>> call_overrideA1(da1) + 'DA1.overrideA1' + >>> call_overrideA1(db1) + 'DB1.overrideA1' + >>> call_overrideA1(pa1_a1) + 'A1::overrideA1' + >>> call_overrideA1(pb1_a1) + 'B1::overrideA1' + >>> call_overrideA1(pb2_a1) + 'B2::overrideA1' + >>> call_overrideA1(pb1_b1) + 'B1::overrideA1' + >>> call_overrideA1(pc_a1) + 'B1::overrideA1' + >>> call_overrideA1(pc_b1) + 'B1::overrideA1' + +test inheritA1 + + >>> a1.inheritA1() + 'A1::inheritA1' + >>> b1.inheritA1() + 'A1::inheritA1' + >>> b2.inheritA1() + 'A1::inheritA1' + >>> da1.inheritA1() + 'A1::inheritA1' + >>> db1.inheritA1() + 'A1::inheritA1' + >>> pa1_a1.inheritA1() + 'A1::inheritA1' + >>> pb1_a1.inheritA1() + 'A1::inheritA1' + >>> pb2_a1.inheritA1() + 'A1::inheritA1' + >>> pb1_b1.inheritA1() + 'A1::inheritA1' + >>> pc_a1.inheritA1() + 'A1::inheritA1' + >>> pc_b1.inheritA1() + 'A1::inheritA1' + +test call_inheritA1 + + >>> call_inheritA1(a1) + 'A1::inheritA1' + >>> call_inheritA1(b1) + 'A1::inheritA1' + >>> call_inheritA1(b2) + 'A1::inheritA1' + >>> call_inheritA1(da1) + 'A1::inheritA1' + >>> call_inheritA1(db1) + 'A1::inheritA1' + >>> call_inheritA1(pa1_a1) + 'A1::inheritA1' + >>> call_inheritA1(pb1_a1) + 'A1::inheritA1' + >>> call_inheritA1(pb2_a1) + 'A1::inheritA1' + >>> call_inheritA1(pb1_b1) + 'A1::inheritA1' + >>> call_inheritA1(pc_a1) + 'A1::inheritA1' + >>> call_inheritA1(pc_b1) + 'A1::inheritA1' + +test inheritA2 + + >>> a2.inheritA2() + 'A2::inheritA2' + >>> b1.inheritA2() + 'A2::inheritA2' + >>> b2.inheritA2() + 'A2::inheritA2' + >>> db1.inheritA2() + 'A2::inheritA2' + >>> pa2_a2.inheritA2() + 'A2::inheritA2' + >>> pb1_a2.inheritA2() + 'A2::inheritA2' + >>> pb1_b1.inheritA2() + 'A2::inheritA2' + +test overrideB1 + + >>> b1.overrideB1() + 'B1::overrideB1' + >>> db1.overrideB1() + 'DB1.overrideB1' + >>> pb1_b1.overrideB1() + 'B1::overrideB1' + >>> pc_b1.overrideB1() + 'C::overrideB1' + +test call_overrideB1 + + >>> call_overrideB1(b1) + 'B1::overrideB1' + >>> call_overrideB1(db1) + 'DB1.overrideB1' + >>> call_overrideB1(pb1_a1) + 'B1::overrideB1' + >>> call_overrideB1(pc_a1) + 'C::overrideB1' + >>> call_overrideB1(pb1_b1) + 'B1::overrideB1' + >>> call_overrideB1(pc_b1) + 'C::overrideB1' + +test inheritB2 + + >>> b2.inheritB2() + 'B2::inheritB2' + >>> db2.inheritB2() + 'B2::inheritB2' + ''' from demo import *