2
0
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:
Dave Abrahams
2000-11-01 02:30:37 +00:00
parent 7cf495874d
commit 2ba0b22831
7 changed files with 126 additions and 16 deletions

View File

@@ -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());
}

View File

@@ -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 {

View File

@@ -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)
{

View File

@@ -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
View File

@@ -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)

View File

@@ -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)

View File

@@ -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> > >