mirror of
https://github.com/boostorg/python.git
synced 2026-01-23 17:52:17 +00:00
slicing
[SVN r14219]
This commit is contained in:
@@ -21,8 +21,9 @@ class object;
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class T>
|
||||
class is_object_manager
|
||||
struct is_object_manager
|
||||
{
|
||||
private:
|
||||
BOOST_STATIC_CONSTANT(bool, hdl = is_handle<T>::value);
|
||||
BOOST_STATIC_CONSTANT(bool, borrowed = python::detail::is_borrowed_ptr<T>::value);
|
||||
public:
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
# include <boost/python/object_core.hpp>
|
||||
# include <boost/python/object_attributes.hpp>
|
||||
# include <boost/python/object_items.hpp>
|
||||
# include <boost/python/object_slices.hpp>
|
||||
# include <boost/python/object_operators.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -14,12 +14,14 @@ namespace boost { namespace python { namespace api {
|
||||
|
||||
struct const_attribute_policies
|
||||
{
|
||||
static object get(object const& target, object const& key);
|
||||
typedef char const* key_type;
|
||||
static object get(object const& target, char const* key);
|
||||
};
|
||||
|
||||
struct attribute_policies : const_attribute_policies
|
||||
{
|
||||
static object const& set(object const& target, object const& key, object const& value);
|
||||
static object const& set(object const& target, char const* key, object const& value);
|
||||
static void del(object const&target, char const* key);
|
||||
};
|
||||
|
||||
//
|
||||
@@ -28,55 +30,38 @@ struct attribute_policies : const_attribute_policies
|
||||
template <class U>
|
||||
inline object_attribute object_operators<U>::attr(char const* name)
|
||||
{
|
||||
object const& x = *static_cast<U*>(this);
|
||||
return object_attribute(x, object(name));
|
||||
object_cref x = *static_cast<U*>(this);
|
||||
return object_attribute(x, name);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
inline const_object_attribute object_operators<U>::attr(char const* name) const
|
||||
{
|
||||
object const& x = *static_cast<U const*>(this);
|
||||
return const_object_attribute(x, object(name));
|
||||
object_cref x = *static_cast<U const*>(this);
|
||||
return const_object_attribute(x, name);
|
||||
}
|
||||
|
||||
|
||||
inline object const_attribute_policies::get(object const& target, object const& key)
|
||||
inline object const_attribute_policies::get(object const& target, char const* key)
|
||||
{
|
||||
return python::getattr(target, key);
|
||||
}
|
||||
|
||||
inline object const& attribute_policies::set(
|
||||
object const& target
|
||||
, object const& key
|
||||
, char const* key
|
||||
, object const& value)
|
||||
{
|
||||
python::setattr(target, key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
namespace converter
|
||||
inline void attribute_policies::del(
|
||||
object const& target
|
||||
, char const* key)
|
||||
{
|
||||
// These specializations are a lie; the proxies do not directly
|
||||
// manage an object. What actually happens is that the implicit
|
||||
// conversion to object takes hold and its conversion to_python is
|
||||
// used. That's OK in part because the object temporary *is*
|
||||
// actually managing the object during the duration of the
|
||||
// conversion.
|
||||
template <>
|
||||
struct is_object_manager<api::object_attribute>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_object_manager<api::const_object_attribute>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
python::delattr(target, key);
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
}}} // namespace boost::python::api
|
||||
|
||||
#endif // OBJECT_ATTRIBUTES_DWA2002615_HPP
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/call.hpp>
|
||||
# include <boost/preprocessor/max.hpp>
|
||||
# include <boost/python/slice_nil.hpp>
|
||||
# include <boost/type.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -27,12 +29,74 @@ namespace api
|
||||
struct attribute_policies;
|
||||
struct const_item_policies;
|
||||
struct item_policies;
|
||||
struct const_slice_policies;
|
||||
struct slice_policies;
|
||||
|
||||
typedef proxy<const_attribute_policies> const_object_attribute;
|
||||
typedef proxy<attribute_policies> object_attribute;
|
||||
typedef proxy<const_item_policies> const_object_item;
|
||||
typedef proxy<item_policies> object_item;
|
||||
typedef proxy<const_slice_policies> const_object_slice;
|
||||
typedef proxy<slice_policies> object_slice;
|
||||
|
||||
//
|
||||
// is_proxy -- proxy type detection
|
||||
//
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T>
|
||||
struct is_proxy
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
template <class T>
|
||||
struct is_proxy<proxy<T> >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
# else
|
||||
typedef char yes_proxy;
|
||||
typedef char (&no_proxy)[2];
|
||||
template <class T>
|
||||
yes_proxy is_proxy_helper(boost::type<proxy<T> >*);
|
||||
no_proxy is_proxy_helper(...);
|
||||
template <class T>
|
||||
struct is_proxy
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = (sizeof(is_proxy_helper((boost::type<T>*)0))
|
||||
== sizeof(yes_proxy)));
|
||||
};
|
||||
# endif
|
||||
|
||||
//
|
||||
// object_handle -- get the handle to construct the object with,
|
||||
// based on whether T is a proxy or not
|
||||
//
|
||||
template <bool = false>
|
||||
struct object_handle
|
||||
{
|
||||
template <class T>
|
||||
static handle<> get(T const& x)
|
||||
{
|
||||
return handle<>(
|
||||
python::borrowed(
|
||||
python::allow_null( // null check is already done
|
||||
converter::arg_to_python<T>(x).get())
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct object_handle<true>
|
||||
{
|
||||
template <class Policies>
|
||||
static handle<> get(proxy<Policies> const& x)
|
||||
{
|
||||
return x.operator object().ptr();
|
||||
}
|
||||
};
|
||||
|
||||
// A way to turn a conrete type T into a type dependent on U. This
|
||||
// keeps conforming compilers from complaining about returning an
|
||||
// incomplete T from a template member function (which must be
|
||||
@@ -54,12 +118,19 @@ namespace api
|
||||
# else
|
||||
typedef object self_cref;
|
||||
# endif
|
||||
|
||||
// there appears to be a codegen bug here. We prevent the early
|
||||
// destruction of a temporary in CWPro8 by binding a named
|
||||
// object instead.
|
||||
# if __MWERKS__ != 0x3000
|
||||
typedef object const& object_cref;
|
||||
# else
|
||||
typedef object const object_cref;
|
||||
# endif
|
||||
|
||||
public:
|
||||
// Attribute access via x.attr("attribute_name")
|
||||
const_object_attribute attr(char const*) const;
|
||||
object_attribute attr(char const*);
|
||||
|
||||
// function call
|
||||
//
|
||||
object operator()() const;
|
||||
|
||||
# ifndef BOOST_PYTHON_GENERATE_CODE
|
||||
@@ -81,10 +152,17 @@ namespace api
|
||||
, BOOST_PYTHON_OBJECT_CALL, ignored)
|
||||
|
||||
// truth value testing
|
||||
//
|
||||
operator bool_type() const;
|
||||
bool operator!() const; // needed for vc6
|
||||
|
||||
// Attribute access
|
||||
//
|
||||
const_object_attribute attr(char const*) const;
|
||||
object_attribute attr(char const*);
|
||||
|
||||
// item access
|
||||
//
|
||||
const_object_item operator[](self_cref) const;
|
||||
object_item operator[](self_cref);
|
||||
|
||||
@@ -110,6 +188,47 @@ namespace api
|
||||
}
|
||||
# endif
|
||||
|
||||
// slicing
|
||||
//
|
||||
const_object_slice slice(self_cref, self_cref) const;
|
||||
object_slice slice(self_cref, self_cref);
|
||||
|
||||
const_object_slice slice(slice_nil, self_cref) const;
|
||||
object_slice slice(slice_nil, self_cref);
|
||||
|
||||
const_object_slice slice(self_cref, slice_nil) const;
|
||||
object_slice slice(self_cref, slice_nil);
|
||||
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
template <class T, class V>
|
||||
const_object_slice
|
||||
slice(T const& start, V const& end) const;
|
||||
|
||||
template <class T, class V>
|
||||
object_slice
|
||||
slice(T const& start, V const& end);
|
||||
|
||||
# else
|
||||
template <class T, class V>
|
||||
const_object_slice
|
||||
slice(T const& start, V const& end) const
|
||||
{
|
||||
return this->slice(
|
||||
slice_bound<T>::type(start)
|
||||
, slice_bound<V>::type(end));
|
||||
}
|
||||
|
||||
template <class T, class V>
|
||||
object_slice
|
||||
slice(T const& start, V const& end)
|
||||
{
|
||||
return this->slice(
|
||||
slice_bound<T>::type(start)
|
||||
, slice_bound<V>::type(end));
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
# if BOOST_MSVC == 1200
|
||||
// For whatever reason, VC6 generates incorrect code unless we
|
||||
// define this
|
||||
@@ -128,12 +247,7 @@ namespace api
|
||||
// explicit conversion from any C++ object to Python
|
||||
template <class T>
|
||||
explicit object(T const& x)
|
||||
: m_ptr(
|
||||
python::borrowed(
|
||||
python::allow_null( // null check is already done
|
||||
converter::arg_to_python<T>(x).get())
|
||||
)
|
||||
)
|
||||
: m_ptr(object_handle<is_proxy<T>::value>::get(x))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -141,12 +255,7 @@ namespace api
|
||||
// literals. Otherwise, they get deduced as char[N]const& above
|
||||
// and conversion fails at runtime.
|
||||
explicit object(char const* x)
|
||||
: m_ptr(
|
||||
python::borrowed(
|
||||
python::allow_null( // null check is already done
|
||||
converter::arg_to_python<char const*>(x).get())
|
||||
)
|
||||
)
|
||||
: m_ptr(object_handle<>::get(x))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,14 @@ namespace boost { namespace python { namespace api {
|
||||
|
||||
struct const_item_policies
|
||||
{
|
||||
typedef object key_type;
|
||||
static object get(object const& target, object const& key);
|
||||
};
|
||||
|
||||
struct item_policies : const_item_policies
|
||||
{
|
||||
static object const& set(object const& target, object const& key, object const& value);
|
||||
static void del(object const& target, object const& key);
|
||||
};
|
||||
|
||||
//
|
||||
@@ -29,7 +31,7 @@ template <class U>
|
||||
inline object_item
|
||||
object_operators<U>::operator[](self_cref key)
|
||||
{
|
||||
object const& x = *static_cast<U*>(this);
|
||||
object_cref x = *static_cast<U*>(this);
|
||||
return object_item(x, key);
|
||||
}
|
||||
|
||||
@@ -37,7 +39,7 @@ template <class U>
|
||||
inline const_object_item
|
||||
object_operators<U>::operator[](self_cref key) const
|
||||
{
|
||||
object const& x = *static_cast<U const*>(this);
|
||||
object_cref x = *static_cast<U const*>(this);
|
||||
return const_object_item(x, key);
|
||||
}
|
||||
|
||||
@@ -62,7 +64,7 @@ object_operators<U>::operator[](T const& key)
|
||||
|
||||
inline object const_item_policies::get(object const& target, object const& key)
|
||||
{
|
||||
return python::getitem(target, key);
|
||||
return getitem(target, key);
|
||||
}
|
||||
|
||||
inline object const& item_policies::set(
|
||||
@@ -70,33 +72,17 @@ inline object const& item_policies::set(
|
||||
, object const& key
|
||||
, object const& value)
|
||||
{
|
||||
python::setitem(target, key, value);
|
||||
setitem(target, key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
namespace converter
|
||||
inline void item_policies::del(
|
||||
object const& target
|
||||
, object const& key)
|
||||
{
|
||||
// These specializations are a lie; the proxies do not directly
|
||||
// manage an object. What actually happens is that the implicit
|
||||
// conversion to object takes hold and its conversion to_python is
|
||||
// used. That's OK in part because the object temporary *is*
|
||||
// actually managing the object during the duration of the
|
||||
// conversion.
|
||||
template <>
|
||||
struct is_object_manager<api::object_item>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_object_manager<api::const_object_item>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
delitem(target, key);
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
}}} // namespace boost::python::api
|
||||
|
||||
#endif // OBJECT_ITEMS_DWA2002615_HPP
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# include <boost/python/object_protocol_core.hpp>
|
||||
# include <boost/python/object_core.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
namespace boost { namespace python { namespace api {
|
||||
|
||||
template <class Target, class Key>
|
||||
object getattr(Target const& target, Key const& key)
|
||||
@@ -26,6 +26,12 @@ void setattr(object const& target, Key const& key, Value const& value)
|
||||
return setattr(target, object(key), object(value));
|
||||
}
|
||||
|
||||
template <class Key>
|
||||
void delattr(object const& target, Key const& key)
|
||||
{
|
||||
delattr(target, object(key));
|
||||
}
|
||||
|
||||
template <class Target, class Key>
|
||||
object getitem(Target const& target, Key const& key)
|
||||
{
|
||||
@@ -39,7 +45,30 @@ void setitem(object const& target, Key const& key, Value const& value)
|
||||
return setitem(target, object(key), object(value));
|
||||
}
|
||||
|
||||
template <class Key>
|
||||
void delitem(object const& target, Key const& key)
|
||||
{
|
||||
delitem(target, object(key));
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
template <class Target, class Begin, class End>
|
||||
object getslice(Target const& target, Begin const& begin, End const& end)
|
||||
{
|
||||
return getslice(object(target), object(begin), object(end));
|
||||
}
|
||||
|
||||
template <class Begin, class End, class Value>
|
||||
void setslice(object const& target, Begin const& begin, End const& end, Value const& value)
|
||||
{
|
||||
return setslice(target, object(begin), object(end), object(value));
|
||||
}
|
||||
|
||||
template <class Begin, class End>
|
||||
void delslice(object const& target, Begin const& begin, End const& end)
|
||||
{
|
||||
delslice(target, object(begin), object(end));
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::api
|
||||
|
||||
#endif // OBJECT_PROTOCOL_DWA2002615_HPP
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef OBJECT_PROTOCOL_CORE_DWA2002615_HPP
|
||||
# define OBJECT_PROTOCOL_CORE_DWA2002615_HPP
|
||||
|
||||
# include <boost/python/handle_fwd.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace api
|
||||
@@ -14,14 +16,34 @@ namespace api
|
||||
|
||||
BOOST_PYTHON_DECL object getattr(object const& target, object const& key);
|
||||
BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value);
|
||||
BOOST_PYTHON_DECL void delattr(object const& target, object const& key);
|
||||
|
||||
// These are defined for efficiency, since attributes are commonly
|
||||
// accessed through literal strings.
|
||||
BOOST_PYTHON_DECL object getattr(object const& target, char const* key);
|
||||
BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object const& value);
|
||||
BOOST_PYTHON_DECL void delattr(object const& target, char const* key);
|
||||
|
||||
BOOST_PYTHON_DECL object getitem(object const& target, object const& key);
|
||||
BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object const& value);
|
||||
BOOST_PYTHON_DECL void delitem(object const& target, object const& key);
|
||||
|
||||
BOOST_PYTHON_DECL object getslice(object const& target, handle<> const& begin, handle<> const& end);
|
||||
BOOST_PYTHON_DECL void setslice(object const& target, handle<> const& begin, handle<> const& end, object const& value);
|
||||
BOOST_PYTHON_DECL void delslice(object const& target, handle<> const& begin, handle<> const& end);
|
||||
}
|
||||
|
||||
using api::getattr;
|
||||
using api::setattr;
|
||||
using api::delattr;
|
||||
|
||||
using api::getitem;
|
||||
using api::setitem;
|
||||
using api::delitem;
|
||||
|
||||
using api::getslice;
|
||||
using api::setslice;
|
||||
using api::delslice;
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
|
||||
124
include/boost/python/object_slices.hpp
Normal file
124
include/boost/python/object_slices.hpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef OBJECT_SLICES_DWA2002615_HPP
|
||||
# define OBJECT_SLICES_DWA2002615_HPP
|
||||
|
||||
# include <boost/python/proxy.hpp>
|
||||
# include <boost/python/object_core.hpp>
|
||||
# include <boost/python/object_protocol.hpp>
|
||||
# include <utility>
|
||||
|
||||
namespace boost { namespace python { namespace api {
|
||||
|
||||
struct const_slice_policies
|
||||
{
|
||||
typedef std::pair<handle<>, handle<> > key_type;
|
||||
static object get(object const& target, key_type const& key);
|
||||
};
|
||||
|
||||
struct slice_policies : const_slice_policies
|
||||
{
|
||||
static object const& set(object const& target, key_type const& key, object const& value);
|
||||
static void del(object const& target, key_type const& key);
|
||||
};
|
||||
|
||||
//
|
||||
// implementation
|
||||
//
|
||||
template <class U>
|
||||
object_slice
|
||||
object_operators<U>::slice(self_cref start, self_cref finish)
|
||||
{
|
||||
object_cref x = *static_cast<U*>(this);
|
||||
return object_slice(x, std::make_pair(start.ptr(), finish.ptr()));
|
||||
}
|
||||
|
||||
template <class U>
|
||||
const_object_slice
|
||||
object_operators<U>::slice(self_cref start, self_cref finish) const
|
||||
{
|
||||
object_cref x = *static_cast<U const*>(this);
|
||||
return const_object_slice(x, std::make_pair(start.ptr(), finish.ptr()));
|
||||
}
|
||||
|
||||
template <class U>
|
||||
object_slice
|
||||
object_operators<U>::slice(slice_nil, self_cref finish)
|
||||
{
|
||||
object_cref x = *static_cast<U*>(this);
|
||||
return object_slice(x, std::make_pair(handle<>(), finish.ptr()));
|
||||
}
|
||||
|
||||
template <class U>
|
||||
const_object_slice
|
||||
object_operators<U>::slice(slice_nil, self_cref finish) const
|
||||
{
|
||||
object_cref x = *static_cast<U const*>(this);
|
||||
return const_object_slice(x, std::make_pair(handle<>(), finish.ptr()));
|
||||
}
|
||||
|
||||
template <class U>
|
||||
object_slice
|
||||
object_operators<U>::slice(self_cref start, slice_nil)
|
||||
{
|
||||
object_cref x = *static_cast<U*>(this);
|
||||
return object_slice(x, std::make_pair(start.ptr(), handle<>()));
|
||||
}
|
||||
|
||||
template <class U>
|
||||
const_object_slice
|
||||
object_operators<U>::slice(self_cref start, slice_nil) const
|
||||
{
|
||||
object_cref x = *static_cast<U const*>(this);
|
||||
return const_object_slice(x, std::make_pair(start.ptr(), handle<>()));
|
||||
}
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
template <class U>
|
||||
template <class T, class V>
|
||||
inline const_object_slice
|
||||
object_operators<U>::slice(T const& start, V const& end) const
|
||||
{
|
||||
return this->slice(
|
||||
typename slice_bound<T>::type(start)
|
||||
, typename slice_bound<V>::type(end));
|
||||
}
|
||||
|
||||
template <class U>
|
||||
template <class T, class V>
|
||||
inline object_slice
|
||||
object_operators<U>::slice(T const& start, V const& end)
|
||||
{
|
||||
return this->slice(
|
||||
typename slice_bound<T>::type(start)
|
||||
, typename slice_bound<V>::type(end));
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
inline object const_slice_policies::get(object const& target, key_type const& key)
|
||||
{
|
||||
return getslice(target, key.first, key.second);
|
||||
}
|
||||
|
||||
inline object const& slice_policies::set(
|
||||
object const& target
|
||||
, key_type const& key
|
||||
, object const& value)
|
||||
{
|
||||
setslice(target, key.first, key.second, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline void slice_policies::del(
|
||||
object const& target
|
||||
, key_type const& key)
|
||||
{
|
||||
delslice(target, key.first, key.second);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::api
|
||||
|
||||
#endif // OBJECT_SLICES_DWA2002615_HPP
|
||||
@@ -13,13 +13,15 @@ namespace boost { namespace python { namespace api {
|
||||
template <class Policies>
|
||||
class proxy : public object_operators<proxy<Policies> >
|
||||
{
|
||||
typedef typename Policies::key_type key_type;
|
||||
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
|
||||
typedef proxy const& copy_ctor_self;
|
||||
# else
|
||||
typedef proxy copy_ctor_self;
|
||||
# endif
|
||||
public:
|
||||
proxy(object const& target, object const& key);
|
||||
proxy(object const& target, key_type const& key);
|
||||
operator object() const;
|
||||
|
||||
// to support a[b] = c[d]
|
||||
@@ -31,18 +33,28 @@ class proxy : public object_operators<proxy<Policies> >
|
||||
Policies::set(m_target, m_key, object(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
public: // implementation detail
|
||||
void del() const;
|
||||
|
||||
private:
|
||||
object m_target;
|
||||
object m_key;
|
||||
key_type m_key;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
inline void del(proxy<T> const& x)
|
||||
{
|
||||
x.del();
|
||||
}
|
||||
|
||||
//
|
||||
// implementation
|
||||
//
|
||||
|
||||
template <class Policies>
|
||||
inline proxy<Policies>::proxy(object const& target, object const& key)
|
||||
inline proxy<Policies>::proxy(object const& target, key_type const& key)
|
||||
: m_target(target), m_key(key)
|
||||
{}
|
||||
|
||||
@@ -78,6 +90,12 @@ BOOST_PYTHON_PROXY_INPLACE(^=)
|
||||
BOOST_PYTHON_PROXY_INPLACE(|=)
|
||||
# undef BOOST_PYTHON_PROXY_INPLACE
|
||||
|
||||
template <class Policies>
|
||||
inline void proxy<Policies>::del() const
|
||||
{
|
||||
Policies::del(m_target, m_key);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::api
|
||||
|
||||
#endif // PROXY_DWA2002615_HPP
|
||||
|
||||
41
include/boost/python/slice_nil.hpp
Normal file
41
include/boost/python/slice_nil.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef SLICE_NIL_DWA2002620_HPP
|
||||
# define SLICE_NIL_DWA2002620_HPP
|
||||
|
||||
namespace boost { namespace python { namespace api {
|
||||
|
||||
class object;
|
||||
|
||||
enum slice_nil
|
||||
{
|
||||
# ifndef _ // Watch out for GNU gettext users, who #define _(x)
|
||||
_
|
||||
# endif
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct slice_bound
|
||||
{
|
||||
typedef object type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct slice_bound<slice_nil>
|
||||
{
|
||||
typedef slice_nil type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using api::slice_nil;
|
||||
# ifndef _ // Watch out for GNU gettext users, who #define _(x)
|
||||
using api::_;
|
||||
# endif
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // SLICE_NIL_DWA2002620_HPP
|
||||
@@ -21,6 +21,40 @@ BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object c
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void delattr(object const& target, object const& key)
|
||||
{
|
||||
if (PyObject_DelAttr(target.ptr().get(), key.ptr().get()) == -1)
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL object getattr(object const& target, char const* key)
|
||||
{
|
||||
return object(
|
||||
(object::new_pyobject_reference*)
|
||||
PyObject_GetAttrString(target.ptr().get(), const_cast<char*>(key))
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object const& value)
|
||||
{
|
||||
if (PyObject_SetAttrString(
|
||||
target.ptr().get(), const_cast<char*>(key), value.ptr().get()) == -1
|
||||
)
|
||||
{
|
||||
throw_error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void delattr(object const& target, char const* key)
|
||||
{
|
||||
if (PyObject_DelAttrString(
|
||||
target.ptr().get(), const_cast<char*>(key)) == -1
|
||||
)
|
||||
{
|
||||
throw_error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL object getitem(object const& target, object const& key)
|
||||
{
|
||||
return object((object::new_pyobject_reference*)PyObject_GetItem(target.ptr().get(), key.ptr().get()));
|
||||
@@ -31,5 +65,104 @@ BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object c
|
||||
if (PyObject_SetItem(target.ptr().get(), key.ptr().get(), value.ptr().get()) == -1)
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void delitem(object const& target, object const& key)
|
||||
{
|
||||
if (PyObject_DelItem(target.ptr().get(), key.ptr().get()) == -1)
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
namespace // slicing code copied directly out of the Python implementation
|
||||
{
|
||||
#undef ISINT
|
||||
#define ISINT(x) ((x) == NULL || PyInt_Check(x) || PyLong_Check(x))
|
||||
|
||||
static PyObject *
|
||||
apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
|
||||
{
|
||||
PyTypeObject *tp = u->ob_type;
|
||||
PySequenceMethods *sq = tp->tp_as_sequence;
|
||||
|
||||
if (sq && sq->sq_slice && ISINT(v) && ISINT(w)) {
|
||||
int ilow = 0, ihigh = INT_MAX;
|
||||
if (!_PyEval_SliceIndex(v, &ilow))
|
||||
return NULL;
|
||||
if (!_PyEval_SliceIndex(w, &ihigh))
|
||||
return NULL;
|
||||
return PySequence_GetSlice(u, ilow, ihigh);
|
||||
}
|
||||
else {
|
||||
PyObject *slice = PySlice_New(v, w, NULL);
|
||||
if (slice != NULL) {
|
||||
PyObject *res = PyObject_GetItem(u, slice);
|
||||
Py_DECREF(slice);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
|
||||
/* u[v:w] = x */
|
||||
{
|
||||
PyTypeObject *tp = u->ob_type;
|
||||
PySequenceMethods *sq = tp->tp_as_sequence;
|
||||
|
||||
if (sq && sq->sq_slice && ISINT(v) && ISINT(w)) {
|
||||
int ilow = 0, ihigh = INT_MAX;
|
||||
if (!_PyEval_SliceIndex(v, &ilow))
|
||||
return -1;
|
||||
if (!_PyEval_SliceIndex(w, &ihigh))
|
||||
return -1;
|
||||
if (x == NULL)
|
||||
return PySequence_DelSlice(u, ilow, ihigh);
|
||||
else
|
||||
return PySequence_SetSlice(u, ilow, ihigh, x);
|
||||
}
|
||||
else {
|
||||
PyObject *slice = PySlice_New(v, w, NULL);
|
||||
if (slice != NULL) {
|
||||
int res;
|
||||
if (x != NULL)
|
||||
res = PyObject_SetItem(u, slice, x);
|
||||
else
|
||||
res = PyObject_DelItem(u, slice);
|
||||
Py_DECREF(slice);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL object getslice(object const& target, handle<> const& begin, handle<> const& end)
|
||||
{
|
||||
return object(
|
||||
(object::new_pyobject_reference*)
|
||||
apply_slice(target.ptr().get(), begin.get(), end.get()));
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void setslice(object const& target, handle<> const& begin, handle<> const& end, object const& value)
|
||||
{
|
||||
if (assign_slice(
|
||||
target.ptr().get(), begin.get(), end.get(), value.ptr().get()) == -1
|
||||
)
|
||||
{
|
||||
throw_error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void delslice(object const& target, handle<> const& begin, handle<> const& end)
|
||||
{
|
||||
if (assign_slice(
|
||||
target.ptr().get(), begin.get(), end.get(), 0) == -1
|
||||
)
|
||||
{
|
||||
throw_error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::api
|
||||
|
||||
@@ -113,6 +113,22 @@ bool test_not_item(object y, object key)
|
||||
return !y[key];
|
||||
}
|
||||
|
||||
bool check_string_slice()
|
||||
{
|
||||
object s("hello, world");
|
||||
|
||||
if (s.slice(_,-3) != "hello, wo")
|
||||
return false;
|
||||
|
||||
if (s.slice(-3,_) != "rld")
|
||||
return false;
|
||||
|
||||
if (", " != s.slice(5,7))
|
||||
return false;
|
||||
|
||||
return s.slice(2,-1).slice(1,-1) == "lo, wor";
|
||||
}
|
||||
|
||||
bool check_binary_operators()
|
||||
{
|
||||
int y;
|
||||
@@ -295,6 +311,7 @@ BOOST_PYTHON_MODULE_INIT(object_ext)
|
||||
|
||||
.def("check_binary_operators", check_binary_operators)
|
||||
.def("check_inplace", check_inplace)
|
||||
.def("check_string_slice", check_string_slice)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,10 +80,15 @@
|
||||
>>> test_not_item(d, 'foo')
|
||||
1
|
||||
|
||||
Slices
|
||||
|
||||
>>> assert check_string_slice()
|
||||
|
||||
Operators
|
||||
|
||||
|
||||
>>> assert check_binary_operators()
|
||||
|
||||
>>> class X: pass
|
||||
...
|
||||
>>> assert check_inplace(range(3), X())
|
||||
|
||||
Reference in New Issue
Block a user