/* This header contains version specific implementations of certain often used tasks, behind a version agnostic API. */ #include "Python.h" /* Attribute names */ #if PY_MAJOR_VERSION < 3 PyObject *Py2to3_NormaliseAttrName(PyObject *name) { if( PyString_Check(name) ){ return name; #ifdef Py_USING_UNICODE } else if ( PyUnicode_Check( name ) ) { return PyUnicode_AsEncodedString( name, NULL, NULL ); #endif // #ifdef Py_USING_UNICODE } return NULL; } void Py2to3_FinishNormaliseAttrName(PyObject *name,PyObject *nname){ if(nname != name){ Py_DECREF(nname); } } PyObject *Py2to3_AttrNameCStr(PyObject *name) { return name; } #define Py2to3_AttrName_AS_STRING(name) PyString_AS_STRING(name) void Py2to3_FinishAttrNameCStr(PyObject *nname){ }; #else PyObject *Py2to3_NormaliseAttrName(PyObject *name) { if( PyUnicode_Check(name) ){ return name; } return NULL; } void Py2to3_FinishNormaliseAttrName(PyObject *name,PyObject *nname){ } PyObject *Py2to3_AttrNameCStr(PyObject *name) { return PyUnicode_AsUTF8String(name); } #define Py2to3_AttrName_AS_STRING(name) PyBytes_AS_STRING(name) void Py2to3_FinishAttrNameCStr(PyObject *nname){ Py_DECREF(nname); }; #endif /* Simple strings for PyErr formatting: * Python 2: - Attributes are ASCII - PyErr_Format uses PyString_FromFormat * Python 3: - Attributes are Unicode - PyErr_Format uses PyUnicode_FromFormat Thus SimpleString == PyString if Python < 3 else PyUnicode */ #if PY_MAJOR_VERSION >= 3 #define Py2to3_SimpleString_Check(name) PyUnicode_Check(name) #define Py2to3_SimpleString_GET_SIZE(name) PyUnicode_GET_SIZE(name) #define Py2to3_SimpleString_Type PyUnicode_Type #define Py2to3_PYERR_SIMPLE_STRING_FMTCHR "U" #define Py2to3_PYERR_PREPARE_SIMPLE_STRING(name) name #define Py2to3_SimpleString_FromString(string) PyUnicode_FromString(string) #else #define Py2to3_SimpleString_Check(name) PyString_Check(name) #define Py2to3_SimpleString_GET_SIZE(name) PyString_GET_SIZE(name) #define Py2to3_SimpleString_Type PyString_Type #define Py2to3_PYERR_SIMPLE_STRING_FMTCHR "s" #define Py2to3_PYERR_PREPARE_SIMPLE_STRING(name) PyString_AS_STRING(name) #define Py2to3_SimpleString_FromString(string) PyString_FromString(string) #endif /* The following macro is defined from Python 2.6 and differently in Python 3 */ #ifndef Py_TYPE #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #endif /* In Python 3, all ints are longs */ #if PY_MAJOR_VERSION >= 3 #define Py2to3_PyNum_Check PyLong_Check #define Py2to3_PyNum_FromLong PyLong_FromLong #define Py2to3_PyNum_AsLong PyLong_AsLong #else #define Py2to3_PyNum_Check PyInt_Check #define Py2to3_PyNum_FromLong PyInt_FromLong #define Py2to3_PyNum_AsLong PyInt_AsLong #endif /* Get hash of an object, using cached value for attribute names */ #ifndef Py_hash_t #define Py_hash_t long #endif #if PY_MAJOR_VERSION < 3 long Py2to3_GetHash_wCache(PyObject *obj){ long hash; if ( PyString_CheckExact( obj ) && ((hash = ((PyStringObject *) obj)->ob_shash) != -1) ) { return hash; } return PyObject_Hash( obj ); } #else Py_hash_t Py2to3_GetHash_wCache(PyObject *obj){ #ifndef Py_LIMITED_API Py_hash_t hash = -1; if ( PyUnicode_CheckExact( obj ) ) { #if PY_MAJOR_VERSION < 3 || PY_MINOR_VERSION < 3 hash = ((PyUnicodeObject *) obj)->hash; #else hash = ((PyUnicodeObject *) obj)->_base._base.hash; #endif // } else if ( PyBytes_CheckExact( key )) { // hash = ((PyBytesObject *) key)->ob_shash; } if (hash == -1) { hash = PyObject_Hash( obj ); } return hash; #else return PyObject_Hash( obj ); #endif // #ifndef Py_LIMITED_API } #endif // #if PY_MAJOR_VERION < 3 /* Get a value from a dict whose keys are attribute names. If *name* is of a type unfitting for an attribute name, *bad_attr* is returned. Does use the hash cache where possible. Precondition: *dict* is a valid PyDictObject */ #if PY_MAJOR_VERSION < 3 #ifdef Py_USING_UNICODE #define Py2to3_AttrNameCheck(name) (PyString_Check(name) || PyUnicode_Check(name)) #else #define Py2to3_AttrNameCheck(name) (PyString_Check(name)) #endif PyObject *Py2to3_GetAttrDictValue(PyDictObject * dict, PyObject *name, PyObject *bad_attr) { long hash; PyObject *nname; PyObject *value; if ( PyString_CheckExact( name ) ) { if ( (hash = ((PyStringObject *) name)->ob_shash) == -1 ) hash = PyObject_Hash( name ); return (dict->ma_lookup)( dict, name, hash )->me_value; } nname = Py2to3_NormaliseAttrName(name); if( nname == NULL ){ PyErr_Clear(); return bad_attr; } hash = PyObject_Hash( nname ); if( hash == -1 ){ Py2to3_FinishNormaliseAttrName(name,nname); PyErr_Clear(); return NULL; } value = (dict->ma_lookup)( dict, nname, hash )->me_value; Py2to3_FinishNormaliseAttrName(name,nname); return value; } #else // #if PY_MAJOR_VERSION < 3 #define Py2to3_AttrNameCheck(name) (PyUnicode_Check(name)) PyObject *Py2to3_GetAttrDictValue(PyDictObject * dict, PyObject *name, PyObject *bad_attr) { #if !defined(Py_LIMITED_API) && (PY_MAJOR_VERSION < 3 || PY_MINOR_VERSION < 3) && 0 // this does not work as intended! don't use it! Py_hash_t hash; if( PyUnicode_CheckExact( name ) ) { #if PY_MINOR_VERSION < 3 hash = ((PyUnicodeObject *) dict)->hash; #else // currently not usable, as dict->ma_lookup does not exist either hash = ((PyUnicodeObject *) dict)->_base._base.hash; #endif if( hash == -1) hash = PyObject_Hash( name ); return (dict->ma_lookup)( dict, name, hash )->me_value; } #endif // #ifndef Py_LIMITED_API if( !PyUnicode_Check(name) ) return bad_attr; return PyDict_GetItem((PyObject *)dict, name); } #endif // #if PY_MAJOR_VERSION < 3 /* */ double Py2to3_PyNum_AsDouble(PyObject *value) { #if PY_MAJOR_VERSION < 3 if ( PyInt_Check( value ) ) { return (double) PyInt_AS_LONG( value ); } else if( !PyLong_Check(value) ){ #else if ( !PyLong_Check( value ) ) { #endif // #if PY_MAJOR_VERSION < 3 PyErr_SetNone( PyExc_TypeError ); return -1.; } return PyLong_AsDouble( value ); } #ifndef PyVarObject_HEAD_INIT #define PyVarObject_HEAD_INIT(type, size) \ PyObject_HEAD_INIT(type) size, #endif #if PY_MAJOR_VERSION >= 3 #define Py2to3_MOD_ERROR_VAL NULL #define Py2to3_MOD_SUCCESS_VAL(val) val #define Py2to3_MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) #define Py2to3_MOD_DEF(ob, name, doc, methods) \ static struct PyModuleDef moduledef = { \ PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \ ob = PyModule_Create(&moduledef); #else #define Py2to3_MOD_ERROR_VAL #define Py2to3_MOD_SUCCESS_VAL(val) #define Py2to3_MOD_INIT(name) void init##name(void) #define Py2to3_MOD_DEF(ob, name, doc, methods) \ ob = Py_InitModule3(name, methods, doc); #endif