Pycxx Extention Base
//================================================================================
//
//    Implementation of PythonExtensionBase
//
//================================================================================
#define missing_method( method ) \
    throw RuntimeError( "Extension object missing implement of " #method );

PythonExtensionBase::PythonExtensionBase()
{
    ob_refcnt = 0;
}

PythonExtensionBase::~PythonExtensionBase()
{
    assert( ob_refcnt == 0 );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name )
{
    Py::TupleN args;
    return  self().callMemberFunction( fn_name, args );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
                                            const Py::Object &arg1 )
{
    Py::TupleN args( arg1 );
    return  self().callMemberFunction( fn_name, args );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
                                            const Py::Object &arg1, const Py::Object &arg2 )
{
    Py::TupleN args( arg1, arg2 );
    return self().callMemberFunction( fn_name, args );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3 )
{
    Py::TupleN args( arg1, arg2, arg3 );
    return self().callMemberFunction( fn_name, args );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
                                            const Py::Object &arg4 )
{
    Py::TupleN args( arg1, arg2, arg3, arg4 );
    return self().callMemberFunction( fn_name, args );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
                                            const Py::Object &arg4, const Py::Object &arg5 )
{
    Py::TupleN args( arg1, arg2, arg3, arg4, arg5 );
    return self().callMemberFunction( fn_name, args );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6 )
{
    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6 );
    return self().callMemberFunction( fn_name, args );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6,
                                            const Py::Object &arg7 )
{
    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7 );
    return self().callMemberFunction( fn_name, args );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6,
                                            const Py::Object &arg7, const Py::Object &arg8 )
{
    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 );
    return self().callMemberFunction( fn_name, args );
}

Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6,
                                            const Py::Object &arg7, const Py::Object &arg8, const Py::Object &arg9 )
{
    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 );
    return self().callMemberFunction( fn_name, args );
}

void PythonExtensionBase::reinit( Tuple &args, Dict &kwds )
{
    throw RuntimeError( "Must not call __init__ twice on this class" );
}

Py::Object PythonExtensionBase::genericGetAttro( const Py::String &name )
{
    return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) );
}

int PythonExtensionBase::genericSetAttro( const Py::String &name, const Py::Object &value )
{
    return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() );
}

#ifdef PYCXX_PYTHON_2TO3
int PythonExtensionBase::print( FILE *, int )
{
    missing_method( print );
    return -1;
}
#endif

Py::Object PythonExtensionBase::getattr( const char * )
{
    missing_method( getattr );
    return Py::None();
}

int PythonExtensionBase::setattr( const char *, const Py::Object & )
{
    missing_method( setattr );
    return -1;
}

Py::Object PythonExtensionBase::getattro( const Py::String &name )
{
    return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) );
}

int PythonExtensionBase::setattro( const Py::String &name, const Py::Object &value )
{
    return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() );
}

int PythonExtensionBase::compare( const Py::Object & )
{
    missing_method( compare );
    return -1;
}

Py::Object PythonExtensionBase::rich_compare( const Py::Object &, int )
{
    missing_method( rich_compare );
    return Py::None();
}

Py::Object PythonExtensionBase::repr()
{
    missing_method( repr );
    return Py::None();
}

Py::Object PythonExtensionBase::str()
{
    missing_method( str );
    return Py::None();
}

long PythonExtensionBase::hash()
{
    missing_method( hash );
    return -1; }

Py::Object PythonExtensionBase::call( const Py::Object &, const Py::Object & )
{
    missing_method( call );
    return Py::None();
}

Py::Object PythonExtensionBase::iter()
{
    missing_method( iter );
    return Py::None();
}

PyObject *PythonExtensionBase::iternext()
{
    missing_method( iternext );
    return NULL; }

// Sequence methods
int PythonExtensionBase::sequence_length()
{
    missing_method( sequence_length );
    return -1; }

Py::Object PythonExtensionBase::sequence_concat( const Py::Object & )
{
    missing_method( sequence_concat );
    return Py::None();
}

Py::Object PythonExtensionBase::sequence_repeat( Py_ssize_t )
{
    missing_method( sequence_repeat );
    return Py::None();
}

Py::Object PythonExtensionBase::sequence_item( Py_ssize_t )
{
    missing_method( sequence_item );
    return Py::None();
}

int PythonExtensionBase::sequence_ass_item( Py_ssize_t, const Py::Object & )
{
    missing_method( sequence_ass_item );
    return -1;
}

// Mapping
int PythonExtensionBase::mapping_length()
{
    missing_method( mapping_length );
    return -1;
}

Py::Object PythonExtensionBase::mapping_subscript( const Py::Object & )
{
    missing_method( mapping_subscript );
    return Py::None();
}

int PythonExtensionBase::mapping_ass_subscript( const Py::Object &, const Py::Object & )
{
    missing_method( mapping_ass_subscript );
    return -1;
}

Py::Object PythonExtensionBase::number_negative()
{
    missing_method( number_negative );
    return Py::None();
}

Py::Object PythonExtensionBase::number_positive()
{
    missing_method( number_positive );
    return Py::None();
}

Py::Object PythonExtensionBase::number_absolute()
{
    missing_method( number_absolute );
    return Py::None();
}

Py::Object PythonExtensionBase::number_invert()
{
    missing_method( number_invert );
    return Py::None();
}

Py::Object PythonExtensionBase::number_int()
{
    missing_method( number_int );
    return Py::None();
}

Py::Object PythonExtensionBase::number_float()
{
    missing_method( number_float );
    return Py::None();
}

Py::Object PythonExtensionBase::number_long()
{
    missing_method( number_long );
    return Py::None();
}

Py::Object PythonExtensionBase::number_add( const Py::Object & )
{
    missing_method( number_add );
    return Py::None();
}

Py::Object PythonExtensionBase::number_subtract( const Py::Object & )
{
    missing_method( number_subtract );
    return Py::None();
}

Py::Object PythonExtensionBase::number_multiply( const Py::Object & )
{
    missing_method( number_multiply );
    return Py::None();
}

Py::Object PythonExtensionBase::number_remainder( const Py::Object & )
{
    missing_method( number_remainder );
    return Py::None();
}

Py::Object PythonExtensionBase::number_divmod( const Py::Object & )
{
    missing_method( number_divmod );
    return Py::None();
}

Py::Object PythonExtensionBase::number_lshift( const Py::Object & )
{
    missing_method( number_lshift );
    return Py::None();
}

Py::Object PythonExtensionBase::number_rshift( const Py::Object & )
{
    missing_method( number_rshift );
    return Py::None();
}

Py::Object PythonExtensionBase::number_and( const Py::Object & )
{
    missing_method( number_and );
    return Py::None();
}

Py::Object PythonExtensionBase::number_xor( const Py::Object & )
{
    missing_method( number_xor );
    return Py::None();
}

Py::Object PythonExtensionBase::number_or( const Py::Object & )
{
    missing_method( number_or );
    return Py::None();
}

Py::Object PythonExtensionBase::number_power( const Py::Object &, const Py::Object & )
{
    missing_method( number_power );
    return Py::None();
}

// Buffer
int PythonExtensionBase::buffer_get( Py_buffer *buf, int flags )
{
    missing_method( buffer_get );
    return -1;
}

int PythonExtensionBase::buffer_release( Py_buffer *buf )
{
    /* This method is optional and only required if the buffer's
       memory is dynamic. */
    return 0;
}

PythonExtensionBase::PythonExtensionBase()
{
    ob_refcnt = 0;
}

PythonExtensionBase::~PythonExtensionBase()
{
    assert( ob_refcnt == 0 );
}

void PythonExtensionBase::reinit( Tuple &args, Dict &kwds )
{
    throw RuntimeError( "Must not call __init__ twice on this class" );
}

Py::Object PythonExtensionBase::genericGetAttro( const Py::String &name )
{
    return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) );
}

int PythonExtensionBase::genericSetAttro( const Py::String &name, const Py::Object &value )
{
    return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() );
}

#ifdef PYCXX_PYTHON_2TO3
int PythonExtensionBase::print( FILE *, int )
{
    throw RuntimeError( "Extension object missing implement of: print" );
    return -1;
}
#endif

Py::Object PythonExtensionBase::getattro( const Py::String &name )
{
    return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) );
}

int PythonExtensionBase::setattro( const Py::String &name, const Py::Object &value )
{
    return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() );
}

// http://en.cppreference.com/w/cpp/preprocessor/replace
#define X( _type_ , _ret_, _func_ , ... ) \
    _type_ PythonExtensionBase::_func_( __VA_ARGS__ ) \
        { \
            throw RuntimeError( "Extension object missing implement of " #_func_ ); \
            return _ret_; \
        } \

X( long         , -1        , hash                  )
X( PyObject *   , nullptr   , iternext              )
X( Py::Object   , Py::None(), getattr              , const char * )
X( int          , -1        , setattr              , const char *, const Py::Object & )
X( int          , -1        , compare              , const Py::Object & )
X( Py::Object   , Py::None(), rich_compare         , const Py::Object &, int )
X( Py::Object   , Py::None(), repr                  )
X( Py::Object   , Py::None(), str                   )
X( Py::Object   , Py::None(), call                 , const Py::Object &, const Py::Object & )
X( Py::Object   , Py::None(), iter                  )

// Sequence methods
X( int          , -1        , sequence_length       )
X( Py::Object   , Py::None(), sequence_concat      , const Py::Object & )
X( Py::Object   , Py::None(), sequence_repeat      , Py_ssize_t )
X( Py::Object   , Py::None(), sequence_item        , Py_ssize_t )
X( int          , -1        , sequence_ass_item    , Py_ssize_t, const Py::Object & )

// Mapping
X( int          , -1        , mapping_length        )
X( Py::Object   , Py::None(), mapping_subscript    , const Py::Object & )
X( int          , -1        , mapping_ass_subscript, const Py::Object &, const Py::Object & )
X( Py::Object   , Py::None(), number_negative       )
X( Py::Object   , Py::None(), number_positive       )
X( Py::Object   , Py::None(), number_absolute       )
X( Py::Object   , Py::None(), number_invert         )
X( Py::Object   , Py::None(), number_int            )
X( Py::Object   , Py::None(), number_float          )
X( Py::Object   , Py::None(), number_long           )
X( Py::Object   , Py::None(), number_add           , const Py::Object & )
X( Py::Object   , Py::None(), number_subtract      , const Py::Object & )
X( Py::Object   , Py::None(), number_multiply      , const Py::Object & )
X( Py::Object   , Py::None(), number_remainder     , const Py::Object & )
X( Py::Object   , Py::None(), number_divmod        , const Py::Object & )
X( Py::Object   , Py::None(), number_lshift        , const Py::Object & )
X( Py::Object   , Py::None(), number_rshift        , const Py::Object & )
X( Py::Object   , Py::None(), number_and           , const Py::Object & )
X( Py::Object   , Py::None(), number_xor           , const Py::Object & )
X( Py::Object   , Py::None(), number_or            , const Py::Object & )
X( Py::Object   , Py::None(), number_power         , const Py::Object &, const Py::Object & )

// Buffer
X( int          , -1        , buffer_get            , Py_buffer *buf, int flags )

#undef X
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License