Skip to content

Commit a5d53d1

Browse files
committed
new class_<> objects are always added to the current scope
[SVN r14964]
1 parent 3c5df28 commit a5d53d1

10 files changed

Lines changed: 76 additions & 71 deletions

File tree

include/boost/python/detail/api_placeholder.hpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,6 @@ namespace boost { namespace python {
99
if (PyErr_Occurred()) throw_error_already_set();
1010
return result;
1111
}
12-
13-
inline object getattr(object const& a0, const char* a1, object const& a2)
14-
{
15-
handle<> result(allow_null(PyObject_GetAttrString(
16-
a0.ptr(), const_cast<char*>(a1))));
17-
if (!PyErr_Occurred()) return object(result);
18-
PyErr_Clear();
19-
return a2;
20-
}
21-
2212
}} // namespace boost::python
2313

2414
#endif // BOOST_PYTHON_API_PLACE_HOLDER_HPP

include/boost/python/detail/module_base.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ class BOOST_PYTHON_DECL module_base
2626

2727
protected:
2828
void setattr_doc(const char* name, python::object const&, char const* doc);
29-
void add_class(type_handle const& class_obj);
3029

3130
private:
3231
handle<> m_module;

include/boost/python/module.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class module : public detail::module_base
3838
template <class T1, class T2 , class T3, class T4>
3939
module& add(class_<T1,T2,T3,T4> const& c)
4040
{
41-
this->add_class(type_handle(borrowed((PyTypeObject*)c.ptr())));
41+
// Soon to disappear...
4242
return *this;
4343
}
4444

include/boost/python/object_protocol.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ object getattr(Target const& target, Key const& key)
1919
return getattr(object(target), object(key));
2020
}
2121

22+
template <class Target, class Key, class Default>
23+
object getattr(Target const& target, Key const& key, Default const& default_)
24+
{
25+
return getattr(object(target), object(key), object(default_));
26+
}
27+
2228

2329
template <class Key, class Value>
2430
void setattr(object const& target, Key const& key, Value const& value)

include/boost/python/object_protocol_core.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ namespace api
1515
class object;
1616

1717
BOOST_PYTHON_DECL object getattr(object const& target, object const& key);
18+
BOOST_PYTHON_DECL object getattr(object const& target, object const& key, object const& default_);
1819
BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value);
1920
BOOST_PYTHON_DECL void delattr(object const& target, object const& key);
2021

2122
// These are defined for efficiency, since attributes are commonly
2223
// accessed through literal strings.
2324
BOOST_PYTHON_DECL object getattr(object const& target, char const* key);
25+
BOOST_PYTHON_DECL object getattr(object const& target, char const* key, object const& default_);
2426
BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object const& value);
2527
BOOST_PYTHON_DECL void delattr(object const& target, char const* key);
2628

src/module.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,6 @@ void module_base::add(type_handle const& x)
4242
this->setattr_doc(x->tp_name, python::object(x), 0);
4343
}
4444

45-
void module_base::add_class(type_handle const& class_obj)
46-
{
47-
this->add(class_obj);
48-
49-
handle<> module_name(
50-
PyObject_GetAttrString(
51-
m_module.get(), const_cast<char*>("__name__"))
52-
);
53-
54-
int status = PyObject_SetAttrString(
55-
python::upcast<PyObject>(class_obj.get())
56-
, const_cast<char*>("__module__"), module_name.get());
57-
58-
if (status == -1)
59-
throw_error_already_set();
60-
}
61-
6245
PyMethodDef module_base::initial_methods[] = { { 0, 0, 0, 0 } };
6346

6447
namespace

src/object/class.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
// copyright notice appears in all copies. This software is provided
44
// "as is" without express or implied warranty, and with no claim as
55
// to its suitability for any purpose.
6+
#include <boost/python/scope.hpp>
67
#include <boost/python/converter/registry.hpp>
78
#include <boost/python/object/class.hpp>
89
#include <boost/python/object/find_instance.hpp>
910
#include <boost/python/object/pickle_support.hpp>
1011
#include <boost/python/detail/map_entry.hpp>
1112
#include <boost/python/object.hpp>
13+
#include <boost/python/object_protocol.hpp>
1214
#include <boost/detail/binary_search.hpp>
1315
#include <boost/python/self.hpp>
1416
#include <boost/bind.hpp>
@@ -264,17 +266,30 @@ namespace objects
264266
PyTuple_SET_ITEM(bases.get(), i - 1, upcast<PyObject>(c.release()));
265267
}
266268

269+
object module_name = PyObject_IsInstance(scope().ptr(), upcast<PyObject>(&PyModule_Type))
270+
? scope().attr("__name__")
271+
: getattr(scope(), "__module__", object(""))
272+
;
273+
274+
if (module_name)
275+
module_name += '.';
276+
267277
// Build the (name, bases, dict) tuple for creating the new class
268278
handle<> args(PyTuple_New(3));
269-
PyTuple_SET_ITEM(args.get(), 0, incref(python::object(name).ptr()));
279+
PyTuple_SET_ITEM(args.get(), 0, incref((module_name + name).ptr()));
270280
PyTuple_SET_ITEM(args.get(), 1, bases.release());
271281
handle<> d(PyDict_New());
272282
PyTuple_SET_ITEM(args.get(), 2, d.release());
273283

274284
// Call the class metatype to create a new class
275285
PyObject* c = PyObject_CallObject(upcast<PyObject>(class_metatype().get()), args.get());
276286
assert(PyType_IsSubtype(c->ob_type, &PyType_Type));
277-
return object(python::detail::new_reference(c));
287+
object result = object(python::detail::new_reference(c));
288+
289+
if (scope().ptr() != Py_None)
290+
scope().attr(name) = result;
291+
292+
return result;
278293
}
279294
}
280295

src/object_protocol.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ BOOST_PYTHON_DECL object getattr(object const& target, object const& key)
1515
return object(detail::new_reference(PyObject_GetAttr(target.ptr(), key.ptr())));
1616
}
1717

18+
BOOST_PYTHON_DECL object getattr(object const& target, object const& key, object const& default_)
19+
{
20+
PyObject* result = PyObject_GetAttr(target.ptr(), key.ptr());
21+
if (result == NULL && PyErr_ExceptionMatches(PyExc_AttributeError))
22+
{
23+
PyErr_Clear();
24+
return default_;
25+
}
26+
return object(detail::new_reference(result));
27+
}
28+
1829
BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value)
1930
{
2031
if (PyObject_SetAttr(target.ptr(), key.ptr(), value.ptr()) == -1)
@@ -35,6 +46,17 @@ BOOST_PYTHON_DECL object getattr(object const& target, char const* key)
3546
));
3647
}
3748

49+
BOOST_PYTHON_DECL object getattr(object const& target, char const* key, object const& default_)
50+
{
51+
PyObject* result = PyObject_GetAttrString(target.ptr(), const_cast<char*>(key));
52+
if (result == NULL && PyErr_ExceptionMatches(PyExc_AttributeError))
53+
{
54+
PyErr_Clear();
55+
return default_;
56+
}
57+
return object(detail::new_reference(result));
58+
59+
}
3860
BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object const& value)
3961
{
4062
if (PyObject_SetAttrString(

test/m1.cpp

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
211211

212212
lvalue_from_pytype<extract_identity<SimpleObject>,&SimpleType>();
213213

214-
module m1("m1");
215-
216-
m1
214+
module("m1")
217215
// Insert the metaclass for all extension classes
218216
.setattr("xclass", boost::python::objects::class_metatype())
219217

@@ -239,40 +237,30 @@ BOOST_PYTHON_MODULE_INIT(m1)
239237
.def("take_b", take_b)
240238
.def("take_c", take_c)
241239
.def("take_d", take_d)
240+
;
242241

243-
.add(
244-
class_<A, shared_ptr<A> >("A")
245-
.def("name", &A::name)
246-
)
247-
242+
class_<A, shared_ptr<A> >("A")
243+
.def("name", &A::name)
248244
;
249245

250246
// sequence points don't ensure that "A" is constructed before "B"
251247
// or "C" below if we make them part of the same chain
252-
m1
253-
.add(
254-
class_<B,bases<A>, shared_ptr<B> >("B")
255-
.def("name", &B::name)
256-
)
248+
class_<B,bases<A>, shared_ptr<B> >("B")
249+
.def("name", &B::name)
250+
;
257251

258-
.add(
259-
class_<C,bases<A>, shared_ptr<C> >("C")
260-
.def("name", &C::name)
261-
)
252+
class_<C,bases<A>, shared_ptr<C> >("C")
253+
.def("name", &C::name)
254+
;
255+
256+
class_<D,shared_ptr<D>, bases<B,C> >("D")
257+
.def("name", &D::name)
262258
;
263259

264-
m1
265-
.add(
266-
class_<D,shared_ptr<D>, bases<B,C> >("D")
267-
.def("name", &D::name)
268-
)
269-
270-
.add(
271-
class_<complicated>("complicated",
272-
args<simple const&,int>())
273-
.def_init(args<simple const&>())
274-
.def("get_n", &complicated::get_n)
275-
)
260+
class_<complicated>("complicated",
261+
args<simple const&,int>())
262+
.def_init(args<simple const&>())
263+
.def("get_n", &complicated::get_n)
276264
;
277265
}
278266

test/test_pointer_adoption.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,29 +88,29 @@ A* as_A(Base* b)
8888

8989
BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext)
9090
{
91-
boost::python::module m("test_pointer_adoption_ext");
92-
m.def("num_a_instances", num_a_instances)
91+
boost::python::module("test_pointer_adoption_ext")
92+
.def("num_a_instances", num_a_instances)
9393

9494
// Specify the manage_new_object return policy to take
9595
// ownership of create's result
9696
.def("create", create, return_value_policy<manage_new_object>())
9797

9898
.def("as_A", as_A, return_internal_reference<>())
99-
.add(
100-
99+
;
100+
101101
class_<Base>("Base")
102-
);
102+
;
103103

104-
m.add(class_<A, bases<Base> >(no_init)
104+
class_<A, bases<Base> >(no_init)
105105
.def("content", &A::content)
106106
.def("get_inner", &A::get_inner, return_internal_reference<>())
107-
)
107+
;
108108

109-
.add(class_<inner>(no_init)
109+
class_<inner>(no_init)
110110
.def("change", &inner::change)
111-
)
111+
;
112112

113-
.add(class_<B>("B")
113+
class_<B>("B")
114114
.def_init(args<A*>(), with_custodian_and_ward_postcall<1,2>())
115115

116116
.def("adopt", &B::adopt
@@ -120,7 +120,7 @@ BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext)
120120
, with_custodian_and_ward<1,2> >()
121121
)
122122

123-
.def("a_content", &B::a_content))
123+
.def("a_content", &B::a_content)
124124
;
125125
}
126126

0 commit comments

Comments
 (0)