diff --git a/src/CXX/IndirectPythonInterface.cxx b/src/CXX/IndirectPythonInterface.cxx index 38fdd1b5ad..3d810cea88 100644 --- a/src/CXX/IndirectPythonInterface.cxx +++ b/src/CXX/IndirectPythonInterface.cxx @@ -39,33 +39,38 @@ namespace Py { -PYCXX_EXPORT bool _CFunction_Check( PyObject *op ) { return op->ob_type == _CFunction_Type(); } -PYCXX_EXPORT bool _Complex_Check( PyObject *op ) { return op->ob_type == _Complex_Type(); } -PYCXX_EXPORT bool _Dict_Check( PyObject *op ) { return op->ob_type == _Dict_Type(); } -PYCXX_EXPORT bool _Float_Check( PyObject *op ) { return op->ob_type == _Float_Type(); } +static int _IsInstance( PyObject *op, PyTypeObject *type ) +{ + return PyObject_IsInstance( op, reinterpret_cast( type ) ); +} + +PYCXX_EXPORT bool _CFunction_Check( PyObject *op ) { return _IsInstance( op, _CFunction_Type() ) > 0; } +PYCXX_EXPORT bool _Complex_Check( PyObject *op ) { return _IsInstance( op, _Complex_Type() ) > 0; } +PYCXX_EXPORT bool _Dict_Check( PyObject *op ) { return _IsInstance( op, _Dict_Type() ) > 0; } +PYCXX_EXPORT bool _Float_Check( PyObject *op ) { return _IsInstance( op, _Float_Type() ) > 0; } #if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) -PYCXX_EXPORT bool _Function_Check( PyObject *op ) { return op->ob_type == _Function_Type(); } +PYCXX_EXPORT bool _Function_Check( PyObject *op ) { return _IsInstance( op, _Function_Type() ) > 0; } #endif -PYCXX_EXPORT bool _Boolean_Check( PyObject *op ) { return op->ob_type == _Bool_Type(); } -PYCXX_EXPORT bool _List_Check( PyObject *op ) { return op->ob_type == _List_Type(); } -PYCXX_EXPORT bool _Long_Check( PyObject *op ) { return op->ob_type == _Long_Type(); } +PYCXX_EXPORT bool _Boolean_Check( PyObject *op ) { return _IsInstance( op, _Bool_Type() ) > 0; } +PYCXX_EXPORT bool _List_Check( PyObject *op ) { return _IsInstance( op, _List_Type() ) > 0; } +PYCXX_EXPORT bool _Long_Check( PyObject *op ) { return _IsInstance( op, _Long_Type() ) > 0; } #if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) -PYCXX_EXPORT bool _Method_Check( PyObject *op ) { return op->ob_type == _Method_Type(); } +PYCXX_EXPORT bool _Method_Check( PyObject *op ) { return _IsInstance( op, _Method_Type() ) > 0; } #endif -PYCXX_EXPORT bool _Module_Check( PyObject *op ) { return op->ob_type == _Module_Type(); } -PYCXX_EXPORT bool _Range_Check( PyObject *op ) { return op->ob_type == _Range_Type(); } -PYCXX_EXPORT bool _Slice_Check( PyObject *op ) { return op->ob_type == _Slice_Type(); } -PYCXX_EXPORT bool _TraceBack_Check( PyObject *op ) { return op->ob_type == _TraceBack_Type(); } -PYCXX_EXPORT bool _Tuple_Check( PyObject *op ) { return op->ob_type == _Tuple_Type(); } -PYCXX_EXPORT bool _Type_Check( PyObject *op ) { return op->ob_type == _Type_Type(); } -PYCXX_EXPORT bool _Unicode_Check( PyObject *op ) { return op->ob_type == _Unicode_Type(); } +PYCXX_EXPORT bool _Module_Check( PyObject *op ) { return _IsInstance( op, _Module_Type() ) > 0; } +PYCXX_EXPORT bool _Range_Check( PyObject *op ) { return _IsInstance( op, _Range_Type() ) > 0; } +PYCXX_EXPORT bool _Slice_Check( PyObject *op ) { return _IsInstance( op, _Slice_Type() ) > 0; } +PYCXX_EXPORT bool _TraceBack_Check( PyObject *op ) { return _IsInstance( op, _TraceBack_Type() ) > 0; } +PYCXX_EXPORT bool _Tuple_Check( PyObject *op ) { return _IsInstance( op, _Tuple_Type() ) > 0; } +PYCXX_EXPORT bool _Type_Check( PyObject *op ) { return _IsInstance( op, _Type_Type() ) > 0; } +PYCXX_EXPORT bool _Unicode_Check( PyObject *op ) { return _IsInstance( op, _Unicode_Type() ) > 0; } #if PY_MAJOR_VERSION == 2 -PYCXX_EXPORT bool _String_Check( PyObject *op ) { return op->ob_type == _String_Type(); } -PYCXX_EXPORT bool _Int_Check( PyObject *op ) { return op->ob_type == _Int_Type(); } -PYCXX_EXPORT bool _CObject_Check( PyObject *op ) { return op->ob_type == _CObject_Type(); } +PYCXX_EXPORT bool _String_Check( PyObject *op ) { return _IsInstance( op, _String_Type() ) > 0; } +PYCXX_EXPORT bool _Int_Check( PyObject *op ) { return _IsInstance( op, _Int_Type() ) > 0; } +PYCXX_EXPORT bool _CObject_Check( PyObject *op ) { return _IsInstance( op, _CObject_Type() ) > 0; } #endif #if PY_MAJOR_VERSION >= 3 -PYCXX_EXPORT bool _Bytes_Check( PyObject *op ) { return op->ob_type == _Bytes_Type(); } +PYCXX_EXPORT bool _Bytes_Check( PyObject *op ) { return _IsInstance( op, _Bytes_Type() ) > 0; } #endif #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) @@ -123,7 +128,11 @@ static int *ptr_Py_OptimizeFlag = NULL; static int *ptr_Py_NoSiteFlag = NULL; static int *ptr_Py_VerboseFlag = NULL; +# if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7 +static const char **ptr__Py_PackageContext = NULL; +# else static char **ptr__Py_PackageContext = NULL; +# endif # endif # ifdef Py_REF_DEBUG @@ -198,6 +207,17 @@ static char **GetCharPointer_as_CharPointerPointer( const char *name ) return (char **)addr; } +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7 +static char **GetConstCharPointer_as_ConstCharPointerPointer( const char *name ) +{ + FARPROC addr = GetProcAddress( python_dll, name ); + if( addr == NULL ) + throw GetAddressException( name ); + + return (const char **)addr; +} +#endif + # ifdef _DEBUG static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d_D.DLL"; @@ -227,7 +247,12 @@ bool InitialisePythonIndirectInterface() ptr_Py_OptimizeFlag = GetInt_as_IntPointer( "Py_OptimizeFlag" ); ptr_Py_NoSiteFlag = GetInt_as_IntPointer( "Py_NoSiteFlag" ); ptr_Py_VerboseFlag = GetInt_as_IntPointer( "Py_VerboseFlag" ); + +# if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7 + ptr__Py_PackageContext = GetConstCharPointer_as_ConstCharPointerPointer( "_Py_PackageContext" ); +# else ptr__Py_PackageContext = GetCharPointer_as_CharPointerPointer( "_Py_PackageContext" ); +# endif # endif # define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) @@ -379,7 +404,11 @@ PYCXX_EXPORT int &_Py_NoSiteFlag() { return *ptr_Py_NoSiteFlag PYCXX_EXPORT int &_Py_VerboseFlag() { return *ptr_Py_VerboseFlag; } # endif +# if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7 +PYCXX_EXPORT const char *__Py_PackageContext() { return *ptr__Py_PackageContext; } +# else PYCXX_EXPORT char *__Py_PackageContext() { return *ptr__Py_PackageContext; } +# endif # if 0 # define Py_INCREF(op) ( \ @@ -494,7 +523,11 @@ PYCXX_EXPORT int &_Py_InteractiveFlag() { return Py_InteractiveFlag PYCXX_EXPORT int &_Py_OptimizeFlag() { return Py_OptimizeFlag; } PYCXX_EXPORT int &_Py_NoSiteFlag() { return Py_NoSiteFlag; } PYCXX_EXPORT int &_Py_VerboseFlag() { return Py_VerboseFlag; } +# if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7 PYCXX_EXPORT const char *__Py_PackageContext() { return _Py_PackageContext; } +# else +PYCXX_EXPORT char *__Py_PackageContext() { return _Py_PackageContext; } +# endif # endif // diff --git a/src/CXX/Python3/Exception.hxx b/src/CXX/Python3/Exception.hxx index eb35aad33e..96d8ef41e2 100644 --- a/src/CXX/Python3/Exception.hxx +++ b/src/CXX/Python3/Exception.hxx @@ -67,6 +67,9 @@ namespace Py // is the exception this specific exception 'exc' bool matches( ExtensionExceptionType &exc ); + + Object errorType(); // get the error type of the active exception + Object errorValue();// get the error value of the active exception }; // for user defined exceptions to be made know to pycxx diff --git a/src/CXX/Python3/ExtensionModule.hxx b/src/CXX/Python3/ExtensionModule.hxx index c2323a47bd..525f65e0b9 100644 --- a/src/CXX/Python3/ExtensionModule.hxx +++ b/src/CXX/Python3/ExtensionModule.hxx @@ -138,10 +138,12 @@ namespace Py args[0] = Object( self, true ); args[1] = Object( PyCapsule_New( method_def, NULL, NULL ), true ); - PyObject *func = PyCFunction_New + assert( m_module != NULL ); + PyObject *func = PyCFunction_NewEx ( &method_def->ext_meth_def, - new_reference_to( args ) + new_reference_to( args ), + m_module ); method_def->py_method = Object( func, true ); diff --git a/src/CXX/Python3/ExtensionType.hxx b/src/CXX/Python3/ExtensionType.hxx index 1f20714a21..74dd2e17fb 100644 --- a/src/CXX/Python3/ExtensionType.hxx +++ b/src/CXX/Python3/ExtensionType.hxx @@ -340,7 +340,7 @@ namespace Py return false; case 1: return true; - } + } } static bool check( const Object &ob ) diff --git a/src/CXX/Python3/ExtensionTypeBase.hxx b/src/CXX/Python3/ExtensionTypeBase.hxx index 891dd92828..bd8d57d6dd 100644 --- a/src/CXX/Python3/ExtensionTypeBase.hxx +++ b/src/CXX/Python3/ExtensionTypeBase.hxx @@ -70,7 +70,7 @@ namespace Py virtual void reinit( Tuple &args, Dict &kwds ); // object basics -#ifdef PYCXX_PYTHON_2TO3 +#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 virtual int print( FILE *, int ); #endif virtual Object getattr( const char * ); @@ -114,7 +114,6 @@ namespace Py virtual Object number_invert(); virtual Object number_int(); virtual Object number_float(); - virtual Object number_long(); virtual Object number_add( const Object & ); virtual Object number_subtract( const Object & ); virtual Object number_multiply( const Object & ); @@ -126,6 +125,28 @@ namespace Py virtual Object number_xor( const Object & ); virtual Object number_or( const Object & ); virtual Object number_power( const Object &, const Object & ); + virtual Object number_floor_divide( const Object & ); + virtual Object number_true_divide( const Object & ); + virtual Object number_index(); +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 + virtual Object number_matrix_multiply( const Object & ); +#endif + + virtual Object number_inplace_add( const Object & ); + virtual Object number_inplace_subtract( const Object & ); + virtual Object number_inplace_multiply( const Object & ); + virtual Object number_inplace_remainder( const Object & ); + virtual Object number_inplace_power( const Object &, const Object & ); + virtual Object number_inplace_lshift( const Object & ); + virtual Object number_inplace_rshift( const Object & ); + virtual Object number_inplace_and( const Object & ); + virtual Object number_inplace_xor( const Object & ); + virtual Object number_inplace_or( const Object & ); + virtual Object number_inplace_floor_divide( const Object & ); + virtual Object number_inplace_true_divide( const Object & ); +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 + virtual Object number_inplace_matrix_multiply( const Object & ); +#endif #if !defined( Py_LIMITED_API ) // Buffer diff --git a/src/CXX/Python3/IndirectPythonInterface.hxx b/src/CXX/Python3/IndirectPythonInterface.hxx index 8c9bd2eea4..bf2c15c53f 100644 --- a/src/CXX/Python3/IndirectPythonInterface.hxx +++ b/src/CXX/Python3/IndirectPythonInterface.hxx @@ -149,7 +149,11 @@ PYCXX_EXPORT int &_Py_NoSiteFlag(); PYCXX_EXPORT int &_Py_TabcheckFlag(); PYCXX_EXPORT int &_Py_VerboseFlag(); +# if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7 PYCXX_EXPORT const char *__Py_PackageContext(); +# else +PYCXX_EXPORT char *__Py_PackageContext(); +# endif # endif PYCXX_EXPORT void _XINCREF( PyObject *op ); diff --git a/src/CXX/Python3/Objects.hxx b/src/CXX/Python3/Objects.hxx index f097230a7d..52f3d255ee 100644 --- a/src/CXX/Python3/Objects.hxx +++ b/src/CXX/Python3/Objects.hxx @@ -51,6 +51,7 @@ #include #include #include +#include namespace Py { @@ -968,7 +969,6 @@ namespace Py bool operator<=( double a, const Float &b ); bool operator<=( const Float &a, double b ); -#if !defined( Py_LIMITED_API ) // =============================================== // class Complex class PYCXX_EXPORT Complex: public Object @@ -1010,6 +1010,8 @@ namespace Py { return pyob && Py::_Complex_Check( pyob ); } + +#if !defined( Py_LIMITED_API ) // convert to Py_complex operator Py_complex() const { @@ -1021,6 +1023,8 @@ namespace Py set( PyComplex_FromCComplex( v ), true ); return *this; } +#endif // Py_LIMITED_API + // assign from a double Complex &operator=( double v ) { @@ -1056,7 +1060,6 @@ namespace Py return PyComplex_ImagAsDouble( ptr() ); } }; -#endif // Py_LIMITED_API // Sequences // Sequences are here represented as sequences of items of type T. @@ -2029,9 +2032,31 @@ namespace Py return *this; } #endif + long ord() { +#if !defined( Py_LIMITED_API ) return static_cast( PyUnicode_ReadChar( ptr(), 0 ) ); +#else + // we know that a Char() is 1 unicode code point + // that fits in 2 wchar_t on windows at worst + wchar_t buf[2]; + Py_ssize_t num_elements = PyUnicode_AsWideChar( ptr(), buf, 2 ); + + // just one wchar_t that easy + if( num_elements == 1 ) + { + return static_cast( buf[0] ); + } + // must be a pair of utf-16 surragates - convert to a code point + if( num_elements == 2 ) + { + // convert from utf-16 to a code-point + return static_cast( ((buf[0]-0xd800)*0x400) + (buf[1]-0xdc00) + 0x10000); + } + return 0; +#endif + } // Conversion @@ -2123,7 +2148,7 @@ namespace Py validate(); } -#if !defined( Py_UNICODE_WIDE ) +#if !defined( Py_LIMITED_API ) && !defined( Py_UNICODE_WIDE ) // Need these c'tors becuase Py_UNICODE is 2 bytes // User may use "int" or "unsigned int" as the unicode type String( const unsigned int *s, int length ) @@ -2181,12 +2206,15 @@ namespace Py return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ), true ); } +#if !defined( Py_LIMITED_API ) // Queries virtual size_type size() const { return PyUnicode_GetLength( ptr() ); } +#endif +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9 #if !defined( Py_LIMITED_API ) const Py_UNICODE *unicode_data() const { @@ -2200,6 +2228,8 @@ namespace Py return unicodestring( unicode_data(), PyUnicode_GetLength( ptr() ) ); } #endif +#endif + ucs4string as_ucs4string() const { Py_UCS4 *buf = new Py_UCS4[ size() ]; @@ -3250,7 +3280,7 @@ namespace Py } return asObject( result ); } -#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 9 +#if (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 9) || (defined( Py_LIMITED_API ) && Py_LIMITED_API+0 >= 0x03090000) Object apply() const { PyObject *result = PyObject_CallNoArgs( ptr() ); diff --git a/src/CXX/Python3/PythonType.hxx b/src/CXX/Python3/PythonType.hxx index 8ec0a39b3e..b2bd2a32d0 100644 --- a/src/CXX/Python3/PythonType.hxx +++ b/src/CXX/Python3/PythonType.hxx @@ -61,7 +61,7 @@ namespace Py PythonType &doc( const char *d ); PythonType &supportClass( void ); -#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) +#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 PythonType &supportPrint( void ); #endif PythonType &supportGetattr( void ); @@ -133,27 +133,54 @@ namespace Py support_number_xor = B(13), support_number_or = B(14), support_number_int = B(15), - support_number_float= B(16) + support_number_float = B(16), + support_number_floor_divide = B(17), + support_number_true_divide = B(18), + support_number_index = B(19), +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 + support_number_matrix_multiply = B(20), +#endif + + // start a new bit mask for inplace that avoid using more then 32 bits in methods_to_support + support_number_inplace_floor_divide = B(0), + support_number_inplace_true_divide = B(1), + support_number_inplace_add = B(2), + support_number_inplace_subtract = B(3), + support_number_inplace_multiply = B(4), + support_number_inplace_remainder = B(5), + support_number_inplace_power = B(6), + support_number_inplace_lshift = B(7), + support_number_inplace_rshift = B(8), + support_number_inplace_and = B(9), + support_number_inplace_xor = B(10), + support_number_inplace_or = B(11) +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 + , + support_number_inplace_matrix_multiply = B(12) +#endif }; - PythonType &supportNumberType( int methods_to_support= - support_number_add | - support_number_subtract | - support_number_multiply | - support_number_remainder | - support_number_divmod | - support_number_power | - support_number_negative | - support_number_positive | - support_number_absolute | - support_number_invert | - support_number_lshift | - support_number_rshift | - support_number_and | - support_number_xor | - support_number_or | - support_number_int | - support_number_float - ); + PythonType &supportNumberType( + int methods_to_support= + support_number_add | + support_number_subtract | + support_number_multiply | + support_number_remainder | + support_number_divmod | + support_number_power | + support_number_negative | + support_number_positive | + support_number_absolute | + support_number_invert | + support_number_lshift | + support_number_rshift | + support_number_and | + support_number_xor | + support_number_or | + support_number_int | + support_number_float, + int inplace_methods_to_support=0 + ); + #if !defined( Py_LIMITED_API ) enum { support_buffer_getbuffer = B(0), diff --git a/src/CXX/Python3/cxx_extensions.cxx b/src/CXX/Python3/cxx_extensions.cxx index 3b2703de93..7371810be4 100644 --- a/src/CXX/Python3/cxx_extensions.cxx +++ b/src/CXX/Python3/cxx_extensions.cxx @@ -232,7 +232,7 @@ extern "C" // All the following functions redirect the call from Python // onto the matching virtual function in PythonExtensionBase // -#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) +#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 static int print_handler( PyObject *, FILE *, int ); #endif static PyObject *getattr_handler( PyObject *, char * ); @@ -282,6 +282,28 @@ extern "C" static PyObject *number_xor_handler( PyObject *, PyObject * ); static PyObject *number_or_handler( PyObject *, PyObject * ); static PyObject *number_power_handler( PyObject *, PyObject *, PyObject * ); + static PyObject *number_floor_divide_handler( PyObject *, PyObject * ); + static PyObject *number_true_divide_handler( PyObject *, PyObject * ); + static PyObject *number_index_handler( PyObject * ); +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 + static PyObject *number_matrix_multiply_handler( PyObject *, PyObject * ); +#endif + + static PyObject *number_inplace_add_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_subtract_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_multiply_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_remainder_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_power_handler( PyObject *, PyObject *, PyObject * ); + static PyObject *number_inplace_lshift_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_rshift_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_and_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_xor_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_or_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_floor_divide_handler( PyObject *, PyObject * ); + static PyObject *number_inplace_true_divide_handler( PyObject *, PyObject * ); +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 + static PyObject *number_inplace_matrix_multiply_handler( PyObject *, PyObject * ); +#endif // Buffer #if !defined( Py_LIMITED_API ) @@ -391,14 +413,22 @@ PythonType &PythonType::supportMappingType( int methods_to_support ) if( methods_to_support&support_number_ ## slot ) { \ slots[ Py_nb_ ## slot ] = reinterpret_cast( number_ ## slot ## _handler ); \ } +#define FILL_NUMBER_INPLACE_SLOT(slot) \ + if( inplace_methods_to_support&support_number_ ## slot ) { \ + slots[ Py_nb_ ## slot ] = reinterpret_cast( number_ ## slot ## _handler ); \ + } #else #define FILL_NUMBER_SLOT(slot) \ if( methods_to_support&support_number_ ## slot ) { \ number_table->nb_ ## slot = number_ ## slot ## _handler; \ } +#define FILL_NUMBER_INPLACE_SLOT(slot) \ + if( inplace_methods_to_support&support_number_ ## slot ) { \ + number_table->nb_ ## slot = number_ ## slot ## _handler; \ + } #endif -PythonType &PythonType::supportNumberType( int methods_to_support ) +PythonType &PythonType::supportNumberType( int methods_to_support, int inplace_methods_to_support ) { #if !defined( Py_LIMITED_API ) if( number_table ) @@ -427,6 +457,29 @@ PythonType &PythonType::supportNumberType( int methods_to_support ) FILL_NUMBER_SLOT(or) FILL_NUMBER_SLOT(int) FILL_NUMBER_SLOT(float) + FILL_NUMBER_SLOT(floor_divide) + FILL_NUMBER_SLOT(true_divide) + FILL_NUMBER_SLOT(index) +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 + FILL_NUMBER_SLOT(matrix_multiply) +#endif + + FILL_NUMBER_INPLACE_SLOT(inplace_add) + FILL_NUMBER_INPLACE_SLOT(inplace_subtract) + FILL_NUMBER_INPLACE_SLOT(inplace_multiply) + FILL_NUMBER_INPLACE_SLOT(inplace_remainder) + FILL_NUMBER_INPLACE_SLOT(inplace_power) + FILL_NUMBER_INPLACE_SLOT(inplace_lshift) + FILL_NUMBER_INPLACE_SLOT(inplace_rshift) + FILL_NUMBER_INPLACE_SLOT(inplace_and) + FILL_NUMBER_INPLACE_SLOT(inplace_xor) + FILL_NUMBER_INPLACE_SLOT(inplace_or) + FILL_NUMBER_INPLACE_SLOT(inplace_floor_divide) + FILL_NUMBER_INPLACE_SLOT(inplace_true_divide) +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 + FILL_NUMBER_INPLACE_SLOT(inplace_matrix_multiply) +#endif + return *this; } @@ -688,7 +741,7 @@ PythonType &PythonType::supportClass() return *this; } -#if defined( PYCXX_PYTHON_2TO3 ) +#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 PythonType &PythonType::supportPrint() { #if PY_VERSION_HEX < 0x03080000 @@ -835,7 +888,7 @@ PythonExtensionBase *getPythonExtensionBase( PyObject *self ) } } -#if defined( PYCXX_PYTHON_2TO3 ) && !defined ( Py_LIMITED_API ) +#if defined( PYCXX_PYTHON_2TO3 ) && !defined ( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 extern "C" int print_handler( PyObject *self, FILE *fp, int flags ) { try @@ -1143,226 +1196,89 @@ extern "C" int mapping_ass_subscript_handler( PyObject *self, PyObject *key, PyO } // Number -extern "C" PyObject *number_negative_handler( PyObject *self ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_negative() ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } +#define NUMBER_UNARY( slot ) \ +extern "C" PyObject *number_ ## slot ## _handler( PyObject *self ) \ +{ \ + try \ + { \ + PythonExtensionBase *p = getPythonExtensionBase( self ); \ + return new_reference_to( p->number_ ## slot() ); \ + } \ + catch( BaseException & ) \ + { \ + return NULL; /* indicates error */ \ + } \ } -extern "C" PyObject *number_positive_handler( PyObject *self ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_positive() ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } +#define NUMBER_BINARY( slot ) \ +extern "C" PyObject *number_ ## slot ## _handler( PyObject *self, PyObject *other ) \ +{ \ + try \ + { \ + PythonExtensionBase *p = getPythonExtensionBase( self ); \ + return new_reference_to( p->number_ ## slot( Object( other ) ) ); \ + } \ + catch( BaseException & ) \ + { \ + return NULL; /* indicates error */ \ + } \ +} +#define NUMBER_TERNARY( slot ) \ +extern "C" PyObject *number_ ## slot ## _handler( PyObject *self, PyObject *other1, PyObject *other2 ) \ +{ \ + try \ + { \ + PythonExtensionBase *p = getPythonExtensionBase( self ); \ + return new_reference_to( p->number_ ## slot( Object( other1 ), Object( other2 ) ) ); \ + } \ + catch( BaseException & ) \ + { \ + return NULL; /* indicates error */ \ + } \ } -extern "C" PyObject *number_absolute_handler( PyObject *self ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_absolute() ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} +NUMBER_UNARY( negative ) +NUMBER_UNARY( positive ) +NUMBER_UNARY( absolute ) +NUMBER_UNARY( invert ) +NUMBER_UNARY( int ) +NUMBER_UNARY( float ) +NUMBER_BINARY( add ) +NUMBER_BINARY( subtract ) +NUMBER_BINARY( multiply ) +NUMBER_BINARY( remainder ) +NUMBER_BINARY( divmod ) +NUMBER_BINARY( lshift ) +NUMBER_BINARY( rshift ) +NUMBER_BINARY( and ) +NUMBER_BINARY( xor ) +NUMBER_BINARY( or ) +NUMBER_TERNARY( power ) +NUMBER_BINARY( floor_divide ) +NUMBER_BINARY( true_divide ) +NUMBER_UNARY( index ) +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 +NUMBER_BINARY( matrix_multiply ) +#endif +NUMBER_BINARY( inplace_add ) +NUMBER_BINARY( inplace_subtract ) +NUMBER_BINARY( inplace_multiply ) +NUMBER_BINARY( inplace_remainder ) +NUMBER_TERNARY( inplace_power ) +NUMBER_BINARY( inplace_lshift ) +NUMBER_BINARY( inplace_rshift ) +NUMBER_BINARY( inplace_and ) +NUMBER_BINARY( inplace_xor ) +NUMBER_BINARY( inplace_or ) +NUMBER_BINARY( inplace_floor_divide ) +NUMBER_BINARY( inplace_true_divide ) +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 +NUMBER_BINARY( inplace_matrix_multiply ) +#endif -extern "C" PyObject *number_invert_handler( PyObject *self ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_invert() ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_int_handler( PyObject *self ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_int() ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_float_handler( PyObject *self ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_float() ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_add_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_add( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_subtract_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_subtract( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_multiply_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_multiply( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_remainder_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_remainder( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_divmod_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_divmod( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_lshift_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_lshift( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_rshift_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_rshift( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_and_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_and( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_xor_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_xor( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_or_handler( PyObject *self, PyObject *other ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_or( Object( other ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} - -extern "C" PyObject *number_power_handler( PyObject *self, PyObject *x1, PyObject *x2 ) -{ - try - { - PythonExtensionBase *p = getPythonExtensionBase( self ); - return new_reference_to( p->number_power( Object( x1 ), Object( x2 ) ) ); - } - catch( BaseException & ) - { - return NULL; // indicate error - } -} +#undef NUMBER_UNARY +#undef NUMBER_BINARY +#undef NUMBER_TERNARY // Buffer #ifndef Py_LIMITED_API @@ -1499,7 +1415,7 @@ int PythonExtensionBase::genericSetAttro( const String &name, const Object &valu return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); } -#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) +#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 int PythonExtensionBase::print( FILE *, int ) { missing_method( print ); @@ -1624,95 +1540,57 @@ int PythonExtensionBase::mapping_ass_subscript( const Object &, const Object & ) missing_method( mapping_ass_subscript ); } -Object PythonExtensionBase::number_negative() -{ - missing_method( number_negative ); -} +// Number +#define NUMBER_UNARY( slot ) Object PythonExtensionBase::number_ ## slot() \ + { missing_method( number_ ## slot ); } +#define NUMBER_BINARY( slot ) Object PythonExtensionBase::number_ ## slot( const Object & ) \ + { missing_method( number_ ## slot ); } +#define NUMBER_TERNARY( slot ) Object PythonExtensionBase::number_ ## slot( const Object &, const Object & ) \ + { missing_method( number_ ## slot ); } -Object PythonExtensionBase::number_positive() -{ - missing_method( number_positive ); -} +NUMBER_UNARY( negative ) +NUMBER_UNARY( positive ) +NUMBER_UNARY( absolute ) +NUMBER_UNARY( invert ) +NUMBER_UNARY( int ) +NUMBER_UNARY( float ) +NUMBER_BINARY( add ) +NUMBER_BINARY( subtract ) +NUMBER_BINARY( multiply ) +NUMBER_BINARY( remainder ) +NUMBER_BINARY( divmod ) +NUMBER_BINARY( lshift ) +NUMBER_BINARY( rshift ) +NUMBER_BINARY( and ) +NUMBER_BINARY( xor ) +NUMBER_BINARY( or ) +NUMBER_TERNARY( power ) +NUMBER_BINARY( floor_divide ) +NUMBER_BINARY( true_divide ) +NUMBER_UNARY( index ) +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 +NUMBER_BINARY( matrix_multiply ) +#endif -Object PythonExtensionBase::number_absolute() -{ - missing_method( number_absolute ); -} +NUMBER_BINARY( inplace_add ) +NUMBER_BINARY( inplace_subtract ) +NUMBER_BINARY( inplace_multiply ) +NUMBER_BINARY( inplace_remainder ) +NUMBER_TERNARY( inplace_power ) +NUMBER_BINARY( inplace_lshift ) +NUMBER_BINARY( inplace_rshift ) +NUMBER_BINARY( inplace_and ) +NUMBER_BINARY( inplace_xor ) +NUMBER_BINARY( inplace_or ) +NUMBER_BINARY( inplace_floor_divide ) +NUMBER_BINARY( inplace_true_divide ) +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 +NUMBER_BINARY( inplace_matrix_multiply ) +#endif -Object PythonExtensionBase::number_invert() -{ - missing_method( number_invert ); -} - -Object PythonExtensionBase::number_int() -{ - missing_method( number_int ); -} - -Object PythonExtensionBase::number_float() -{ - missing_method( number_float ); -} - -Object PythonExtensionBase::number_long() -{ - missing_method( number_long ); -} - -Object PythonExtensionBase::number_add( const Object & ) -{ - missing_method( number_add ); -} - -Object PythonExtensionBase::number_subtract( const Object & ) -{ - missing_method( number_subtract ); -} - -Object PythonExtensionBase::number_multiply( const Object & ) -{ - missing_method( number_multiply ); -} - -Object PythonExtensionBase::number_remainder( const Object & ) -{ - missing_method( number_remainder ); -} - -Object PythonExtensionBase::number_divmod( const Object & ) -{ - missing_method( number_divmod ); -} - -Object PythonExtensionBase::number_lshift( const Object & ) -{ - missing_method( number_lshift ); -} - -Object PythonExtensionBase::number_rshift( const Object & ) -{ - missing_method( number_rshift ); -} - -Object PythonExtensionBase::number_and( const Object & ) -{ - missing_method( number_and ); -} - -Object PythonExtensionBase::number_xor( const Object & ) -{ - missing_method( number_xor ); -} - -Object PythonExtensionBase::number_or( const Object & ) -{ - missing_method( number_or ); -} - -Object PythonExtensionBase::number_power( const Object &, const Object & ) -{ - missing_method( number_power ); -} +#undef NUMBER_UNARY +#undef NUMBER_BINARY +#undef NUMBER_TERNARY // Buffer @@ -1913,6 +1791,29 @@ bool BaseException::matches( ExtensionExceptionType &exc ) return PyErr_ExceptionMatches( exc.ptr() ) != 0; } +Object BaseException::errorType() +{ + PyObject *type, *value, *traceback; + PyErr_Fetch( &type, &value, &traceback ); + + Object result( type ); + + PyErr_Restore( type, value, traceback ); + return result; +} + +Object BaseException::errorValue() +{ + PyObject *type, *value, *traceback; + PyErr_Fetch( &type, &value, &traceback ); + + Object result( value ); + + PyErr_Restore( type, value, traceback ); + return result; +} + + //------------------------------------------------------------ #if 1 diff --git a/src/CXX/Python3/cxx_standard_exceptions.hxx b/src/CXX/Python3/cxx_standard_exceptions.hxx index d16c14cae4..c02bc0bad4 100644 --- a/src/CXX/Python3/cxx_standard_exceptions.hxx +++ b/src/CXX/Python3/cxx_standard_exceptions.hxx @@ -16,7 +16,11 @@ PYCXX_STANDARD_EXCEPTION( GeneratorExit, BaseException ) PYCXX_STANDARD_EXCEPTION( Exception, BaseException ) #endif PYCXX_STANDARD_EXCEPTION( StopIteration, Exception ) -#if (defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) +#if !defined(MS_WINDOWS) && ((defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5)) +PYCXX_STANDARD_EXCEPTION( StopAsyncIteration, Exception ) +#endif +// Windows builds of python 3.5 do not export the symbol PyExc_StopAsyncIteration - need atleast 3.6 +#if defined(MS_WINDOWS) && ((defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 6) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5)) PYCXX_STANDARD_EXCEPTION( StopAsyncIteration, Exception ) #endif PYCXX_STANDARD_EXCEPTION( ArithmeticError, Exception ) @@ -35,6 +39,7 @@ PYCXX_STANDARD_EXCEPTION( MemoryError, Exception ) PYCXX_STANDARD_EXCEPTION( NameError, Exception ) PYCXX_STANDARD_EXCEPTION( UnboundLocalError, NameError ) PYCXX_STANDARD_EXCEPTION( OSError, Exception ) +#if (defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03060000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 6) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 4) PYCXX_STANDARD_EXCEPTION( BlockingIOError, OSError ) PYCXX_STANDARD_EXCEPTION( ChildProcessError,OSError ) PYCXX_STANDARD_EXCEPTION( ConnectionError, OSError ) @@ -50,10 +55,15 @@ PYCXX_STANDARD_EXCEPTION( NotADirectoryError, OSError ) PYCXX_STANDARD_EXCEPTION( PermissionError, OSError ) PYCXX_STANDARD_EXCEPTION( ProcessLookupError, OSError ) PYCXX_STANDARD_EXCEPTION( TimeoutError, OSError ) +#endif PYCXX_STANDARD_EXCEPTION( ReferenceError, Exception ) PYCXX_STANDARD_EXCEPTION( RuntimeError, Exception ) PYCXX_STANDARD_EXCEPTION( NotImplementedError, RuntimeError ) -#if (defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) +#if !defined(MS_WINDOWS) && ((defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5)) +PYCXX_STANDARD_EXCEPTION( RecursionError, RuntimeError ) +#endif +// Windows builds of python 3.5 do not export the symbol PyExc_RecursionError - need atleast 3.6 +#if defined(MS_WINDOWS) && ((defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 6) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5)) PYCXX_STANDARD_EXCEPTION( RecursionError, RuntimeError ) #endif PYCXX_STANDARD_EXCEPTION( SyntaxError, Exception ) diff --git a/src/CXX/Version.hxx b/src/CXX/Version.hxx index fabce5f60c..e6069aad33 100644 --- a/src/CXX/Version.hxx +++ b/src/CXX/Version.hxx @@ -40,7 +40,7 @@ #define PYCXX_VERSION_MAJOR 7 #define PYCXX_VERSION_MINOR 1 -#define PYCXX_VERSION_PATCH 0 +#define PYCXX_VERSION_PATCH 7 #define PYCXX_MAKEVERSION( major, minor, patch ) ((major<<16)|(minor<<8)|(patch)) #define PYCXX_VERSION PYCXX_MAKEVERSION( PYCXX_VERSION_MAJOR, PYCXX_VERSION_MINOR, PYCXX_VERSION_PATCH ) #endif