Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #384 from gsomix/python3_interface
Browse files Browse the repository at this point in the history
Partial support for python3 interface
  • Loading branch information
Soeren Sonnenburg committed Mar 26, 2012
2 parents f8c2851 + 71e4475 commit 001c17c
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 56 deletions.
20 changes: 10 additions & 10 deletions src/.generate_link_dependencies.py
Expand Up @@ -3,10 +3,10 @@
f=None
BASEDIR=None
try:
f=file('../.config')
f=open('../.config')
BASEDIR='../'
except:
f=file('../../.config')
f=open('../../.config')
BASEDIR='../../'

have_doxygen=f.read().find('-DHAVE_DOXYGEN') is not -1
Expand Down Expand Up @@ -43,7 +43,7 @@ def get_deps(f):
get_deps(d)
cppfile=d[:-1]+'cpp'

if cppfile not in fdep and deps.has_key(cppfile):
if cppfile not in fdep and cppfile in deps:
fdep+=[cppfile]
get_deps(cppfile)
except KeyError:
Expand All @@ -53,7 +53,7 @@ def get_deps(f):
files=sys.stdin.readlines()
for f in files:
f=f[:-1]
d=re.findall(incexpr, file(f).read())
d=re.findall(incexpr, open(f).read())
dd=[]
for i in d:
if i[1]:
Expand All @@ -72,9 +72,9 @@ def get_deps(f):

#'./../modular'
#generate linker dependencies
for f in deps.iterkeys():
if f[-1] == 'i' and not initial_deps.has_key(f):
if file(f).read().find('%module')>-1:
for f in deps.keys():
if f[-1] == 'i' and not f in initial_deps:
if open(f).read().find('%module')>-1:
str1=os.path.join(os.path.dirname(f), prefix + os.path.basename(f)[:-2]) + suffix + ': ' + f[:-2]+'_wrap.cxx.o' + ' sg_print_functions.cpp.o'
str2=os.path.join(os.path.dirname(f), os.path.basename(f)[:-2]) + '_wrap.cxx: ' + f

Expand All @@ -87,11 +87,11 @@ def get_deps(f):
#else:
get_deps(f)
for d in fdep:
if not initial_deps.has_key(d):
if not d in initial_deps:
if d[-4:]=='.cpp' or d[-2:]=='.c':
str1+=' ' + d + '.o'
if d[-2:]=='.h' or d[-2:]=='.i':
str2+=' ' + d

print str1
print str2
print(str1)
print(str2)
14 changes: 10 additions & 4 deletions src/.scrub_docstrings.py
Expand Up @@ -29,10 +29,16 @@ def run (self):
input=open(self.infile, 'r')
output=open(self.outfile, 'w')

for text in input.xreadlines():
for pairs in REPLACEMENTS:
text=text.replace(pairs[0], pairs[1])
output.write(text)
if sys.version_info >= (3,):
for text in input.readlines():
for pairs in REPLACEMENTS:
text=text.replace(pairs[0], pairs[1])
output.write(text)
else:
for text in input.xreadlines():
for pairs in REPLACEMENTS:
text=text.replace(pairs[0], pairs[1])
output.write(text)

input.close()
output.close()
Expand Down
24 changes: 15 additions & 9 deletions src/configure
Expand Up @@ -1588,9 +1588,9 @@ set_install_dirs() {
python_minor=`$PYTHON -V 2>&1 | cut -f 2 -d ' ' | cut -f 2 -d '.'`
if test -z "$_pydir" ; then
if test "$python_major" -ge 2 && test "$python_minor" -ge 6 ; then
_pydir="`$PYTHON -c 'import sys; print \"python\"+sys.version[0:3]'`/dist-packages"
_pydir="`$PYTHON -c 'import sys; print(\"python\"+sys.version[0:3])'`/dist-packages"
else
_pydir="`$PYTHON -c 'import sys; print \"python\"+sys.version[0:3]'`/site-packages"
_pydir="`$PYTHON -c 'import sys; print(\"python\"+sys.version[0:3])'`/site-packages"
fi
fi
}
Expand Down Expand Up @@ -4279,11 +4279,11 @@ test_python()
echocheck "Python numpy support"
if $PYTHON -c "import sys; import numpy" >/dev/null 2>&1
then
if [ `$PYTHON -c 'import numpy; print numpy.__version__' | cut -c 1` -gt 0 ]
if [ `$PYTHON -c 'import numpy; print(numpy.__version__)' | cut -c 1` -gt 0 ]
then
echores "`$PYTHON -c 'import numpy; print numpy.__version__'`"
echores "`$PYTHON -c 'import numpy; print(numpy.__version__)'`"
else
echores "`$PYTHON -c 'import numpy; print numpy.__version__'`... too old version 1.0 or later required"
echores "`$PYTHON -c 'import numpy; print(numpy.__version__)'`... too old version 1.0 or later required"
if test "$_python" = yes
then
die "python numpy outdated"
Expand All @@ -4305,10 +4305,10 @@ test_python()
PRE_LIB_SWIG_PYTHON_MODULAR=_
EXT_IF_SWIG_PYTHON_MODULAR='.py'
test -n "$_pyinclude" && _pyinclude="-I$_pyinclude"
test -n "$_pyinclude" || _pyinclude=`$PYTHON -c "from distutils.sysconfig import get_python_inc; import numpy; print '-I%s -I%s' % (get_python_inc(), numpy.get_include())"`
_pylibpath=`$PYTHON -c 'from distutils.sysconfig import get_config_vars; print "-L%(LIBPL)s" % get_config_vars()'`
EXT_LIB_SWIG_PYTHON_MODULAR=`$PYTHON -c 'from distutils.sysconfig import get_config_vars; print "%(SO)s" % get_config_vars()'`
test -n "$_pylibs" || _pylibs=`$PYTHON -c "import sys; print 'python'+sys.version[0:3]"`${EXT_LIB_SWIG_PYTHON_MODULAR%.*}
test -n "$_pyinclude" || _pyinclude=`$PYTHON -c "from distutils.sysconfig import get_python_inc; import numpy; print('-I%s -I%s' % (get_python_inc(), numpy.get_include()))"`
_pylibpath=`$PYTHON -c 'from distutils.sysconfig import get_config_vars; print("-L%(LIBPL)s" % get_config_vars())'`
EXT_LIB_SWIG_PYTHON_MODULAR=`$PYTHON -c "from distutils.sysconfig import get_config_vars, get_config_var; sle=(get_config_var('SO').replace('.'+get_config_var('SOABI'),'',1) if 'SOABI' in get_config_vars() else get_config_var('SO')); print(sle)"`
test -n "$_pylibs" || _pylibs=`$PYTHON -c "import sys; print('python'+sys.version[0:3])"`${EXT_LIB_SWIG_PYTHON_MODULAR%.*}
INCLUDES_PYTHON="$_pyinclude $INCLUDES_PYTHON"
COMPFLAGS_CPP_PYTHON="-fno-strict-aliasing -fPIC $COMPFLAGS_CPP_PYTHON"
COMPFLAGS_C_PYTHON="-fno-strict-aliasing -fPIC $COMPFLAGS_C_PYTHON"
Expand Down Expand Up @@ -4340,6 +4340,7 @@ PyMODINIT_FUNC initsg(void)
PyMODINIT_FUNC initsg(void);
EOF

echocheck "Python/Python Numpy Developer Files"
if cc_check $COMPFLAGS_CPP_PYTHON $INCLUDES_PYTHON $LINKFLAGS_PYTHON
then
Expand Down Expand Up @@ -4368,6 +4369,11 @@ EOF
fi
fi

if [ `echo $PYVER | cut -c 1` -gt 2 ]
then
SWIGFLAGS_PYTHON_MODULAR="${SWIGFLAGS_PYTHON_MODULAR} -py3"
fi

if test "$_python" = yes
then
DEFINES_PYTHON="$DEFINES_PYTHON -DHAVE_PYTHON"
Expand Down
10 changes: 6 additions & 4 deletions src/interfaces/modular/SGBase.i
Expand Up @@ -114,6 +114,7 @@ public void readExternal(java.io.ObjectInput in) throws java.io.IOException, jav
#endif

#ifdef SWIGPYTHON

#include <shogun/io/SerializableFile.h>
#include <shogun/io/SerializableAsciiFile.h>
#include <shogun/io/SerializableHdf5File.h>
Expand Down Expand Up @@ -364,10 +365,11 @@ namespace shogun
}
}


%pythoncode %{
import copy_reg

try:
import copy_reg
except ImportError:
import copyreg as copy_reg
def _sg_reconstructor(cls, base, state):
try:
if not isinstance(cls(), SGObject):
Expand Down Expand Up @@ -396,7 +398,7 @@ def _sg_reduce_ex(self, proto):
state = None
else:
if base is self.__class__:
raise TypeError, "can't pickle %s objects" % base.__name__
raise TypeError("can't pickle %s objects" % base.__name__)
state = base(self)
args = (self.__class__, base, state)
try:
Expand Down
10 changes: 9 additions & 1 deletion src/interfaces/python_modular/swig_typemaps.i
Expand Up @@ -29,6 +29,11 @@ extern "C" {
#include <numpy/arrayobject.h>
}

#if PY_VERSION_HEX >= 0x03000000
#define PyString_FromStringAndSize PyBytes_FromStringAndSize
#define PyString_AsStringAndSize PyBytes_AsStringAndSize
#endif

/* Functions to extract array attributes.
*/
static bool is_array(PyObject* a) { return (a) && PyArray_Check(a); }
Expand All @@ -48,9 +53,12 @@ static const char* typecode_string(PyObject* py_obj) {
if (PyDict_Check( py_obj)) return "dict" ;
if (PyList_Check( py_obj)) return "list" ;
if (PyTuple_Check( py_obj)) return "tuple" ;
if (PyFile_Check( py_obj)) return "file" ;
if (PyModule_Check( py_obj)) return "module" ;

#if PY_VERSION_HEX < 0x03000000
if (PyFile_Check( py_obj)) return "file" ;
if (PyInstance_Check(py_obj)) return "instance" ;
#endif

return "unknown type";
}
Expand Down
53 changes: 37 additions & 16 deletions src/interfaces/python_static/PythonInterface.cpp
Expand Up @@ -133,11 +133,11 @@ IFType CPythonInterface::get_argument_type()

int32_t CPythonInterface::get_int()
{
const PyObject* i=get_arg_increment();
const PyObject* i = get_arg_increment();
if (!i || !PyInt_Check(i))
SG_ERROR("Expected Scalar Integer as argument %d\n", m_rhs_counter);

return PyInt_AS_LONG(i);
return PyInt_AS_LONG(const_cast<PyObject*>(i));
}

float64_t CPythonInterface::get_real()
Expand All @@ -155,19 +155,29 @@ bool CPythonInterface::get_bool()
if (!b || !PyBool_Check(b))
SG_ERROR("Expected Scalar Boolean as argument %d\n", m_rhs_counter);

return PyInt_AS_LONG(b) != 0;
return PyInt_AS_LONG(const_cast<PyObject*>(b)) != 0;
}


char* CPythonInterface::get_string(int32_t& len)
{
const PyObject* s=get_arg_increment();
if (!s || !PyString_Check(s))
SG_ERROR("Expected String as argument %d\n", m_rhs_counter);

len=PyString_Size((PyObject*) s);
char* str=PyString_AS_STRING(s);
#ifdef IS_PYTHON3
if (!s || !PyUnicode_Check(s))
SG_ERROR("Expected String as argument %d\n", m_rhs_counter);

len = PyUnicode_GetSize((PyObject*) s);
char* str = PyBytes_AsString(PyUnicode_AsASCIIString(const_cast<PyObject*>(s)));
#else
if (!s || !PyString_Check(s))
SG_ERROR("Expected String as argument %d\n", m_rhs_counter);

len = PyString_Size((PyObject*) s);
char* str = PyString_AS_STRING(s);
ASSERT(str && len>0);
#endif

ASSERT(str && len>0);

char* cstr=SG_MALLOC(char, len+1);
memcpy(cstr, str, len+1);
Expand Down Expand Up @@ -637,7 +647,7 @@ void CPythonInterface::run_python_init()
SG_SERROR("couldn't open " LIBPYTHON ".so\n");
#endif
Py_Initialize();
import_array();
init_numpy();
}

void CPythonInterface::run_python_exit()
Expand Down Expand Up @@ -691,7 +701,12 @@ bool CPythonInterface::run_python_helper(CSGInterface* from_if)

SG_FREE(python_code);

PyObject* res = PyEval_EvalCode((PyCodeObject*) python_code_obj, globals, NULL);
#ifdef IS_PYTHON3
PyObject* res = PyEval_EvalCode(python_code_obj, globals, NULL);
#else
PyObject* res = PyEval_EvalCode((PyCodeObject*) python_code_obj, globals, NULL);
#endif

Py_DECREF(python_code_obj);

if (res == NULL)
Expand Down Expand Up @@ -816,11 +831,13 @@ static PyMethodDef sg_pythonmethods[] = {
};

#ifdef HAVE_ELWMS
PyMODINIT_FUNC initelwms(void)
MOD_INIT(elwms)
#else
PyMODINIT_FUNC initsg(void)
MOD_INIT(sg)
#endif
{
PyObject *module;

// initialize python interpreter
Py_Initialize();

Expand All @@ -832,22 +849,26 @@ PyMODINIT_FUNC initsg(void)

// initialize callbacks
#ifdef HAVE_ELWMS
Py_InitModule((char*) "elwms", sg_pythonmethods);
MOD_DEF(module, (char*) "elwms", sg_pythonmethods);
#else
Py_InitModule((char*) "sg", sg_pythonmethods);
MOD_DEF(module, (char*) "sg", sg_pythonmethods);
#endif

if (module == NULL)
return MOD_ERROR_VAL;

#ifdef HAVE_OCTAVE
COctaveInterface::run_octave_init();
#endif
#ifdef HAVE_R
CRInterface::run_r_init();
#endif

import_array();
init_numpy();

// init_shogun has to be called before anything else
// exit_shogun is called upon destruction in exitsg()
init_shogun(&python_print_message, &python_print_warning,
&python_print_error, &python_cancel_computations);

return MOD_SUCCESS_VAL(module);
}
41 changes: 41 additions & 0 deletions src/interfaces/python_static/PythonInterface.h
Expand Up @@ -15,6 +15,47 @@ extern "C" {
#include <numpy/arrayobject.h>
}

#if PY_VERSION_HEX >= 0x03000000
#define IS_PYTHON3

#define PyString_FromStringAndSize PyBytes_FromStringAndSize
#define PyString_Check PyBytes_Check
#define PyString_Size PyBytes_GET_SIZE
#define PyString_AS_STRING PyBytes_AS_STRING
#define PyString_AsString PyBytes_AsString

#define PyInt_Check PyLong_Check
#define PyInt_AS_LONG PyLong_AS_LONG
#endif

// Python2/3 module initialization
#ifdef IS_PYTHON3
#define MOD_ERROR_VAL NULL
#define MOD_SUCCESS_VAL(val) val
#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
#define MOD_DEF(ob, name, methods) \
static struct PyModuleDef moduledef = { \
PyModuleDef_HEAD_INIT, name, NULL, -1, methods, }; \
ob = PyModule_Create(&moduledef);
#else
#define MOD_ERROR_VAL
#define MOD_SUCCESS_VAL(val)
#define MOD_INIT(name) PyMODINIT_FUNC init##name(void)
#define MOD_DEF(ob, name, methods) \
ob = Py_InitModule(name, methods);
#endif

#ifdef IS_PYTHON3
int init_numpy()
{
import_array();
}
#else
void init_numpy()
{
import_array();
}
#endif

namespace shogun
{
Expand Down

0 comments on commit 001c17c

Please sign in to comment.