mirror of
https://github.com/boostorg/python.git
synced 2026-01-27 07:02:15 +00:00
const-ify ClassBase::getattr()
Add repr() function to Class<T> Add to_python/from_python conversions for PyPtr<T> Standardize set_item/get_item interfaces (instead of proxies) for Dict and List Add Reprable<> template to newtypes.h Fix a bug wherein the __module__ attribute would be lost for classes that have a default virtual function implementation. [SVN r8091]
This commit is contained in:
@@ -379,6 +379,14 @@ void ExtensionClassBase::add_default_method(PyPtr<Function> method, const char*
|
||||
// clear our dict now. It will henceforth contain only default method
|
||||
// implementations.
|
||||
dict() = Dict();
|
||||
|
||||
// Copy the "__module__" attribute from the fake base class, if any
|
||||
PyObject *module_name = PyDict_GetItemString(new_base->dict().get(), "__module__");
|
||||
if (module_name != 0 && PyString_Check(module_name))
|
||||
{
|
||||
static String module_key("__module__", String::interned);
|
||||
PyDict_SetItem(dict().get(), module_key.get(), module_name);
|
||||
}
|
||||
}
|
||||
Function::add_to_namespace(method, name, dict().get());
|
||||
}
|
||||
|
||||
33
newtypes.h
33
newtypes.h
@@ -181,6 +181,18 @@ class Setattrable : public Base
|
||||
int instance_setattr(PyObject* instance, const char* name, PyObject* value) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class Reprable : public Base
|
||||
{
|
||||
public:
|
||||
typedef Reprable Properties; // Convenience for derived class construction
|
||||
typedef typename Base::Instance Instance;
|
||||
Reprable(PyTypeObject* type_type, const char* name);
|
||||
Reprable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_repr(PyObject* instance) const;
|
||||
};
|
||||
|
||||
//
|
||||
// Member function definitions
|
||||
//
|
||||
@@ -261,6 +273,27 @@ int Setattrable<Base>::instance_setattr(PyObject* instance, const char* name, Py
|
||||
return Downcast<Instance>(instance)->setattr(name, value);
|
||||
}
|
||||
|
||||
// Reprable
|
||||
template <class Base>
|
||||
Reprable<Base>::Reprable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(repr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
Reprable<Base>::Reprable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(repr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* Reprable<Base>::instance_repr(PyObject* instance) const
|
||||
{
|
||||
return Downcast<Instance>(instance)->repr();
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct AllMethods {
|
||||
|
||||
41
objects.cpp
41
objects.cpp
@@ -210,7 +210,8 @@ bool Dict::accepts(Ptr p)
|
||||
void Dict::clear()
|
||||
{ PyDict_Clear(get()); }
|
||||
|
||||
const Ptr& Dict::Proxy::operator=(const Ptr& rhs) {
|
||||
const Ptr& Dict::Proxy::operator=(const Ptr& rhs)
|
||||
{
|
||||
if (PyDict_SetItem(m_dict.get(), m_key.get(), rhs.get()) == -1)
|
||||
throw ErrorAlreadySet();
|
||||
return rhs;
|
||||
@@ -234,7 +235,7 @@ Ptr Dict::operator[](Ptr key) const {
|
||||
}
|
||||
|
||||
|
||||
Ptr Dict::get_item(const Ptr& key, const Ptr& default_ /* = Ptr() */)
|
||||
Ptr Dict::get_item(const Ptr& key, const Ptr& default_ /* = Ptr() */) const
|
||||
{
|
||||
PyObject* value_or_null = PyDict_GetItem(get(), key.get());
|
||||
if (value_or_null == 0 && !PyErr_Occurred())
|
||||
@@ -243,6 +244,17 @@ Ptr Dict::get_item(const Ptr& key, const Ptr& default_ /* = Ptr() */)
|
||||
return Ptr(value_or_null, Ptr::borrowed); // Will throw if there was another error
|
||||
}
|
||||
|
||||
void Dict::set_item(const Ptr& key, const Ptr& value)
|
||||
{
|
||||
if (PyDict_SetItem(get(), key.get(), value.get()) == -1)
|
||||
throw ErrorAlreadySet();
|
||||
}
|
||||
|
||||
void Dict::set_item(const Object& key, const Ptr& value)
|
||||
{
|
||||
set_item(key.reference(), value);
|
||||
}
|
||||
|
||||
void Dict::erase(Ptr key) {
|
||||
if (PyDict_DelItem(get(), key.get()) == -1)
|
||||
throw ErrorAlreadySet();
|
||||
@@ -264,7 +276,7 @@ Ptr Dict::operator[](const Object& key) const
|
||||
return this->operator[](key.reference());
|
||||
}
|
||||
|
||||
Ptr Dict::get_item(const Object& key, Ptr default_)
|
||||
Ptr Dict::get_item(const Object& key, Ptr default_) const
|
||||
{
|
||||
return this->get_item(key.reference(), default_);
|
||||
}
|
||||
@@ -402,10 +414,7 @@ Tuple List::as_tuple() const
|
||||
|
||||
const Ptr& List::Proxy::operator=(const Ptr& rhs)
|
||||
{
|
||||
int result = PyList_SetItem(m_list.get(), m_index, rhs.get());
|
||||
if (result == -1)
|
||||
throw ErrorAlreadySet();
|
||||
Py_INCREF(rhs.get());
|
||||
m_list.set_item(m_index, rhs);
|
||||
return rhs;
|
||||
}
|
||||
|
||||
@@ -414,6 +423,24 @@ List::Proxy::operator Ptr() const
|
||||
return Ptr(PyList_GetItem(m_list.get(), m_index), Ptr::borrowed);
|
||||
}
|
||||
|
||||
Ptr List::get_item(std::size_t pos) const
|
||||
{
|
||||
return Ptr(PyList_GetItem(this->get(), pos), Ptr::borrowed);
|
||||
}
|
||||
|
||||
void List::set_item(std::size_t pos, Ptr rhs)
|
||||
{
|
||||
int result = PyList_SetItem(this->get(), pos, rhs.get());
|
||||
if (result == -1)
|
||||
throw ErrorAlreadySet();
|
||||
Py_INCREF(rhs.get());
|
||||
}
|
||||
|
||||
void List::set_item(std::size_t pos, Object rhs)
|
||||
{
|
||||
this->set_item(pos, rhs.reference());
|
||||
}
|
||||
|
||||
List::Proxy::Proxy(const Ptr& list, std::size_t index)
|
||||
: m_list(list), m_index(index)
|
||||
{
|
||||
|
||||
11
objects.h
11
objects.h
@@ -87,6 +87,9 @@ class List : public Object
|
||||
std::size_t size();
|
||||
Ptr operator[](std::size_t pos) const;
|
||||
Proxy operator[](std::size_t pos);
|
||||
Ptr get_item(std::size_t pos) const;
|
||||
void set_item(std::size_t pos, Ptr);
|
||||
void set_item(std::size_t pos, Object);
|
||||
void insert(std::size_t index, Ptr item);
|
||||
void push_back(Ptr item);
|
||||
void append(Ptr item);
|
||||
@@ -155,14 +158,16 @@ class Dict : public Object
|
||||
Proxy operator[](Ptr key);
|
||||
Ptr operator[](Ptr key) const;
|
||||
|
||||
Ptr get_item(const Ptr& key, const Ptr& _default = Ptr());
|
||||
Ptr get_item(const Ptr& key, const Ptr& default_ = Ptr()) const;
|
||||
void set_item(const Ptr& key, const Ptr& value);
|
||||
|
||||
void erase(Ptr key);
|
||||
|
||||
Proxy operator[](const Object& key);
|
||||
Ptr operator[](const Object& key) const;
|
||||
|
||||
Ptr get_item(const Object& key, Ptr default_ = Ptr());
|
||||
Ptr get_item(const Object& key, Ptr default_ = Ptr()) const;
|
||||
void set_item(const Object& key, const Ptr& value);
|
||||
|
||||
void erase(const Object& key);
|
||||
|
||||
@@ -194,7 +199,7 @@ struct List::Proxy
|
||||
friend class List;
|
||||
Proxy(const Ptr& list, std::size_t index);
|
||||
private:
|
||||
Ptr m_list;
|
||||
List m_list;
|
||||
std::size_t m_index;
|
||||
};
|
||||
|
||||
|
||||
27
pyptr.h
27
pyptr.h
@@ -19,9 +19,34 @@
|
||||
|
||||
namespace py {
|
||||
|
||||
|
||||
#ifdef PY_NO_INLINE_FRIENDS_IN_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T, class Base>
|
||||
struct PyPtrConversions : Base
|
||||
{
|
||||
inline friend T from_python(PyObject* x, py::Type<const T&>)
|
||||
{ return T(x, T::new_ref); }
|
||||
|
||||
inline friend T from_python(PyObject* x, py::Type<T>)
|
||||
{ return T(x, T::new_ref); }
|
||||
|
||||
inline friend PyObject* to_python(T x)
|
||||
{ return x.release(); }
|
||||
|
||||
};
|
||||
|
||||
#ifdef PY_NO_INLINE_FRIENDS_IN_NAMESPACE
|
||||
namespace py {
|
||||
using ::PyPtrConversions;
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
class PyPtr
|
||||
: public boost::dereferenceable<PyPtr<T>, T*> // supplies op->
|
||||
: public PyPtrConversions<PyPtr<T>,
|
||||
boost::dereferenceable<PyPtr<T>, T*> > // supplies op->
|
||||
{
|
||||
public:
|
||||
PyPtr(const PyPtr& rhs)
|
||||
|
||||
14
subclass.cpp
14
subclass.cpp
@@ -87,7 +87,7 @@ namespace detail {
|
||||
m_bases = new_bases;
|
||||
}
|
||||
|
||||
PyObject* ClassBase::getattr(const char* name)
|
||||
PyObject* ClassBase::getattr(const char* name) const
|
||||
{
|
||||
if (!PY_CSTD_::strcmp(name, "__dict__"))
|
||||
{
|
||||
@@ -153,6 +153,18 @@ namespace detail {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Mostly copied wholesale from Python's classobject.c
|
||||
PyObject* ClassBase::repr() const
|
||||
{
|
||||
PyObject *mod = PyDict_GetItemString(m_name_space.get(), "__module__");
|
||||
unsigned long address = reinterpret_cast<unsigned long>(this);
|
||||
String result = (mod == NULL || !PyString_Check(mod))
|
||||
? String("<extension class %s at %lx>") % Tuple(m_name, address)
|
||||
: String("<extension class %s.%s at %lx>") % Tuple(Ptr(mod, Ptr::borrowed), m_name, address);
|
||||
return result.reference().release();
|
||||
}
|
||||
|
||||
|
||||
int ClassBase::setattr(const char* name, PyObject* value)
|
||||
{
|
||||
if (is_special_name(name)
|
||||
|
||||
@@ -92,9 +92,10 @@ namespace detail {
|
||||
Dict& dict();
|
||||
|
||||
// Standard Python functions.
|
||||
PyObject* getattr(const char* name);
|
||||
PyObject* getattr(const char* name) const;
|
||||
int setattr(const char* name, PyObject* value);
|
||||
|
||||
PyObject* repr() const;
|
||||
|
||||
protected:
|
||||
bool initialize_instance(Instance* instance, PyObject* args, PyObject* keywords);
|
||||
void add_base(Ptr base);
|
||||
@@ -184,7 +185,7 @@ class Class
|
||||
// The type of a Class<T> object.
|
||||
template <class T>
|
||||
class MetaClass
|
||||
: public Callable<Getattrable<Setattrable<TypeObject<Class<T> > > > >,
|
||||
: public Reprable<Callable<Getattrable<Setattrable<TypeObject<Class<T> > > > > >,
|
||||
boost::noncopyable
|
||||
{
|
||||
public:
|
||||
@@ -192,7 +193,6 @@ class MetaClass
|
||||
|
||||
// Standard Python functions.
|
||||
PyObject* call(PyObject* args, PyObject* keywords);
|
||||
private:
|
||||
|
||||
struct TypeObject
|
||||
: Singleton<TypeObject, Callable<py::TypeObject<MetaClass> > >
|
||||
|
||||
Reference in New Issue
Block a user