提交 6213cb92 authored 作者: abalkin's avatar abalkin

Merged python 3 port changes. Resolved white space conflicts.

...@@ -10,9 +10,10 @@ python: ...@@ -10,9 +10,10 @@ python:
before_install: before_install:
- sudo apt-get install -qq libatlas3gf-base libatlas-dev - sudo apt-get install -qq libatlas3gf-base libatlas-dev
install: install:
#If we don't install numpy before SciPy 0.10.1, the SciPy installations fails. # If we don't install numpy before SciPy 0.10.1, the SciPy installations fails.
- "pip install -q six==1.2.0 --use-mirrors"
- "pip install -q numpy==1.5 --use-mirrors" - "pip install -q numpy==1.5 --use-mirrors"
#We can't install SciPy as there is no BLAS installed. # We can't install SciPy as there is no BLAS installed.
- "pip install . --no-deps --use-mirrors" - "pip install . --no-deps --use-mirrors"
# command to run tests # command to run tests
env: env:
......
...@@ -14,13 +14,17 @@ try: ...@@ -14,13 +14,17 @@ try:
except ImportError: except ImportError:
from distutils.core import setup from distutils.core import setup
try: try:
from distutils.command.build_py import build_py_2to3 \ from distutils.command.build_py import build_py_2to3 as build_py
as build_py
from distutils.command.build_scripts import build_scripts_2to3 \
as build_scripts
except ImportError: except ImportError:
from distutils.command.build_py import build_py from distutils.command.build_py import build_py
from distutils.command.build_scripts import build_scripts from distutils.command.build_scripts import build_scripts
else:
exclude_fixers = ['fix_next', 'fix_filter']
from distutils.util import Mixin2to3
from lib2to3.refactor import get_fixers_from_package
Mixin2to3.fixer_names = [f for f in get_fixers_from_package('lib2to3.fixes')
if f.rsplit('.', 1)[-1] not in exclude_fixers]
from distutils.command.build_scripts import build_scripts_2to3 as build_scripts
CLASSIFIERS = """\ CLASSIFIERS = """\
...@@ -177,7 +181,7 @@ def do_setup(): ...@@ -177,7 +181,7 @@ def do_setup():
license=LICENSE, license=LICENSE,
platforms=PLATFORMS, platforms=PLATFORMS,
packages=find_packages(), packages=find_packages(),
install_requires=['numpy>=1.5.0', 'scipy>=0.7.2'], install_requires=['numpy>=1.5.0', 'scipy>=0.7.2', 'six>=1.2.0'],
package_data={ package_data={
'': ['*.txt', '*.rst', '*.cu', '*.cuh', '*.c', '*.sh', '': ['*.txt', '*.rst', '*.cu', '*.cuh', '*.c', '*.sh',
'ChangeLog'], 'ChangeLog'],
......
...@@ -184,4 +184,4 @@ from theano.tensor.randomstreams import RandomStreams ...@@ -184,4 +184,4 @@ from theano.tensor.randomstreams import RandomStreams
# Imitate the numpy.random symbol with a tensor.random one # Imitate the numpy.random symbol with a tensor.random one
tensor.random = RandomStreams(seed=0xBAD5EED, no_warn=True) tensor.random = RandomStreams(seed=0xBAD5EED, no_warn=True)
del RandomStreams del RandomStreams
__import__('theano.tensor.shared_randomstreams') __import__('theano.tensor.shared_randomstreams')
\ No newline at end of file
...@@ -10,6 +10,7 @@ from itertools import izip ...@@ -10,6 +10,7 @@ from itertools import izip
from StringIO import StringIO from StringIO import StringIO
import numpy import numpy
import six
import theano import theano
from theano import gof from theano import gof
...@@ -530,7 +531,7 @@ def char_from_number(number): ...@@ -530,7 +531,7 @@ def char_from_number(number):
remainder = number % base remainder = number % base
new_char = chr(ord('A') + remainder) new_char = chr(ord('A') + remainder)
rval = new_char + rval rval = new_char + rval
number /= base number //= base
return rval return rval
...@@ -1563,8 +1564,8 @@ class _VariableEquivalenceTracker(object): ...@@ -1563,8 +1564,8 @@ class _VariableEquivalenceTracker(object):
#List of default version of make thunk. #List of default version of make thunk.
#This is needed to know if the user overrided it. #This is needed to know if the user overrided it.
#The GpuOp will be added here when theano.sandbox.cuda is imported. #The GpuOp will be added here when theano.sandbox.cuda is imported.
default_make_thunk = [theano.gof.Op.make_thunk.im_func, default_make_thunk = [six.get_unbound_function(theano.gof.Op.make_thunk),
theano.gof.OpenMPOp.make_thunk.im_func] six.get_unbound_function(theano.gof.OpenMPOp.make_thunk)]
class _Linker(gof.link.LocalLinker): class _Linker(gof.link.LocalLinker):
......
...@@ -5,15 +5,13 @@ For design notes, see doc/advanced/module.txt ...@@ -5,15 +5,13 @@ For design notes, see doc/advanced/module.txt
""" """
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
import sys, warnings
from itertools import chain
from theano import gof from theano import gof
from theano.printing import pprint from theano.printing import pprint
import io, sys from theano.compile import io
from theano.gof.python25 import all from theano.gof.python25 import all
import warnings
from itertools import chain
import theano.compile.function_module import theano.compile.function_module
import theano.compile.mode import theano.compile.mode
...@@ -1150,12 +1148,12 @@ class Module(ComponentDict): ...@@ -1150,12 +1148,12 @@ class Module(ComponentDict):
# to look for submodules on which make_module_instance needs to be called # to look for submodules on which make_module_instance needs to be called
def recurse(v): def recurse(v):
if isinstance(v,list): if isinstance(v,list):
iter = enumerate(v) iterv = enumerate(v)
else: else:
iter = v.iteritems() iterv = v.iteritems()
#backport #backport
#iter = enumerate(v) if isinstance(v,list) else v.iteritems() #iter = enumerate(v) if isinstance(v,list) else v.iteritems()
for sk,sv in iter: for sk,sv in iterv:
if isinstance(sv,(list,dict)): if isinstance(sv,(list,dict)):
sv = recurse(sv) sv = recurse(sv)
elif isinstance(sv,Module): elif isinstance(sv,Module):
......
...@@ -63,7 +63,7 @@ class ViewOp(gof.Op): ...@@ -63,7 +63,7 @@ class ViewOp(gof.Op):
version = [] version = []
# If any of the c code is unversionned, we have to return () # If any of the c code is unversionned, we have to return ()
# Else, we will return a list of (type name, version) pairs. # Else, we will return a list of (type name, version) pairs.
for t, (c, v) in sorted(self.c_code_and_version.items()): for t, (c, v) in sorted(self.c_code_and_version.items(), key=lambda pair: str(pair[0])):
if not v: if not v:
warnings.warn("Type %s has C code for ViewOp, but it has " warnings.warn("Type %s has C code for ViewOp, but it has "
"no version. You should add a 'version' keyword arg " "no version. You should add a 'version' keyword arg "
...@@ -153,7 +153,7 @@ class DeepCopyOp(gof.Op): ...@@ -153,7 +153,7 @@ class DeepCopyOp(gof.Op):
version = [] version = []
# If any of the c code is unversionned, we have to return () # If any of the c code is unversionned, we have to return ()
# Else, we will return a list of (type name, version) pairs. # Else, we will return a list of (type name, version) pairs.
for t, (c, v) in sorted(self.c_code_and_version.items()): for t, (c, v) in sorted(self.c_code_and_version.items(), key=lambda pair: str(pair[0])):
if not v: if not v:
warnings.warn("Type %s has C code for OutputGuard, but it has " warnings.warn("Type %s has C code for OutputGuard, but it has "
"no version. You should add a 'version' keyword arg " "no version. You should add a 'version' keyword arg "
......
...@@ -179,10 +179,11 @@ def rebuild_collect_shared(outputs, ...@@ -179,10 +179,11 @@ def rebuild_collect_shared(outputs,
# it is also not clear when/how to use the value of that shared # it is also not clear when/how to use the value of that shared
# variable (is it a default? ignored?, if the shared variable changes, # variable (is it a default? ignored?, if the shared variable changes,
# does that function default also change?). # does that function default also change?).
if any([isinstance(v, SharedVariable) for v in input_variables]): for v in input_variables:
raise TypeError(('Cannot use a shared variable (%s) as explicit ' if isinstance(v, SharedVariable):
'input. Consider substituting a non-shared' raise TypeError(('Cannot use a shared variable (%s) as explicit '
' variable via the `givens` parameter') % v) 'input. Consider substituting a non-shared'
' variable via the `givens` parameter') % v)
# Fill update_d and update_expr with provided updates # Fill update_d and update_expr with provided updates
if updates is None: if updates is None:
......
...@@ -632,10 +632,11 @@ class T_picklefunction(unittest.TestCase): ...@@ -632,10 +632,11 @@ class T_picklefunction(unittest.TestCase):
f = theano.function([x], theano.tensor.dot(x, y)) f = theano.function([x], theano.tensor.dot(x, y))
import StringIO from six import BytesIO
fp = StringIO.StringIO() fp = BytesIO()
p = cPickle.Pickler(fp, 2) p = cPickle.Pickler(fp, 2)
p.persistent_id = pers_save p.persistent_id = pers_save
p.dump(f)
try: try:
p.dump(f) p.dump(f)
except NotImplementedError, e: except NotImplementedError, e:
...@@ -643,7 +644,7 @@ class T_picklefunction(unittest.TestCase): ...@@ -643,7 +644,7 @@ class T_picklefunction(unittest.TestCase):
return return
else: else:
raise raise
fp2 = StringIO.StringIO(fp.getvalue()) fp2 = BytesIO(fp.getvalue())
fp.close() fp.close()
p = cPickle.Unpickler(fp2) p = cPickle.Unpickler(fp2)
p.persistent_load = pers_load p.persistent_load = pers_load
......
...@@ -10,6 +10,21 @@ from theano.compile.function_module import AliasedMemoryError ...@@ -10,6 +10,21 @@ from theano.compile.function_module import AliasedMemoryError
import theano.tensor as T import theano.tensor as T
import sys, copy import sys, copy
import theano import theano
from six import PY3
# Copied from theano/tensor/tests/test_basic.py
if PY3:
# In python 3.x, when an exception is reraised it saves original
# exception in its args, therefore in order to find the actual
# message, we need to unpack arguments recurcively.
def exc_message(e):
msg = e.args[0]
if isinstance(msg, Exception):
return exc_message(msg)
return msg
else:
def exc_message(e):
return e[0]
#TODO: add test for module.make(member=init_value) #TODO: add test for module.make(member=init_value)
class T_module(unittest.TestCase): class T_module(unittest.TestCase):
...@@ -489,7 +504,7 @@ class T_module(unittest.TestCase): ...@@ -489,7 +504,7 @@ class T_module(unittest.TestCase):
m.a = [4, 5, 6] m.a = [4, 5, 6]
assert False assert False
except Exception, e: except Exception, e:
if e[0].startswith("Cannot set readonly"): if exc_message(e).startswith("Cannot set readonly"):
pass pass
else: else:
raise raise
...@@ -498,7 +513,7 @@ class T_module(unittest.TestCase): ...@@ -498,7 +513,7 @@ class T_module(unittest.TestCase):
m.a[0] = 4 m.a[0] = 4
assert False assert False
except Exception, e: except Exception, e:
if e[0].startswith("Cannot set readonly"): if exc_message(e).startswith("Cannot set readonly"):
pass pass
else: else:
raise raise
...@@ -514,7 +529,7 @@ class T_module(unittest.TestCase): ...@@ -514,7 +529,7 @@ class T_module(unittest.TestCase):
m.a[0] = 4 m.a[0] = 4
assert False assert False
except Exception, e: except Exception, e:
if e[0].startswith("Cannot set readonly"): if exc_message(e).startswith("Cannot set readonly"):
pass pass
else: else:
raise raise
...@@ -634,7 +649,7 @@ def test_method_updates(): ...@@ -634,7 +649,7 @@ def test_method_updates():
m = M.make() m = M.make()
assert False assert False
except ValueError, e: except ValueError, e:
if str(e[0]).startswith('Variable listed in both inputs and up'): if str(exc_message(e)).startswith('Variable listed in both inputs and up'):
pass pass
else: else:
raise raise
......
...@@ -6,7 +6,9 @@ import logging ...@@ -6,7 +6,9 @@ import logging
import os import os
import sys import sys
import warnings import warnings
import ConfigParser
from six.moves import configparser as ConfigParser
import StringIO import StringIO
import theano import theano
......
...@@ -9,12 +9,23 @@ import os ...@@ -9,12 +9,23 @@ import os
import StringIO import StringIO
import sys import sys
from itertools import izip from itertools import izip
from six import PY3
import numpy import numpy
if sys.version_info[:2] >= (3, 0):
import hashlib
if sys.version_info[:2] >= (2, 5): def hash_from_code(msg):
# hashlib.md5() requires an object that supports buffer interface,
# but Python 3 (unicode) strings don't.
if isinstance(msg, str):
msg = msg.encode()
# Python 3 does not like module names that start with
# a digit.
return 'm' + hashlib.md5(msg).hexdigest()
elif sys.version_info[:2] >= (2, 5):
import hashlib import hashlib
def hash_from_code(msg): def hash_from_code(msg):
...@@ -1227,19 +1238,25 @@ class CLinker(link.Linker): ...@@ -1227,19 +1238,25 @@ class CLinker(link.Linker):
# Static methods that can run and destroy the struct built by # Static methods that can run and destroy the struct built by
# instantiate. # instantiate.
static = """ if PY3:
static = """
int {struct_name}_executor({struct_name} *self) {{
return self->run();
}}
void {struct_name}_destructor(PyObject *capsule) {{
{struct_name} *self = ({struct_name} *)PyCapsule_GetContext(capsule);
delete self;
}}
""".format(struct_name=self.struct_name)
else:
static = """
int %(struct_name)s_executor(%(struct_name)s* self) { int %(struct_name)s_executor(%(struct_name)s* self) {
return self->run(); return self->run();
} }
void %(struct_name)s_destructor(void* executor, void* self) { void %(struct_name)s_destructor(void* executor, void* self) {
//printf("doing cleanup\\n");
//fflush(stdout);
// ((%(struct_name)s*)self)->cleanup();
// free(self);
delete ((%(struct_name)s*)self); delete ((%(struct_name)s*)self);
//printf("done cleanup\\n");
//fflush(stdout);
} }
""" % dict(struct_name=self.struct_name) """ % dict(struct_name=self.struct_name)
...@@ -1305,7 +1322,17 @@ class CLinker(link.Linker): ...@@ -1305,7 +1322,17 @@ class CLinker(link.Linker):
print >> code, ' }' print >> code, ' }'
print >> code, ' %(struct_name)s* struct_ptr = new %(struct_name)s();' % locals() print >> code, ' %(struct_name)s* struct_ptr = new %(struct_name)s();' % locals()
print >> code, ' struct_ptr->init(', ','.join('PyTuple_GET_ITEM(argtuple, %i)' % n for n in xrange(n_args)), ');' print >> code, ' struct_ptr->init(', ','.join('PyTuple_GET_ITEM(argtuple, %i)' % n for n in xrange(n_args)), ');'
print >> code, ' PyObject* thunk = PyCObject_FromVoidPtrAndDesc((void*)(&%(struct_name)s_executor), struct_ptr, %(struct_name)s_destructor);' % locals() if PY3:
print >> code, """\
PyObject* thunk = PyCapsule_New((void*)(&{struct_name}_executor), NULL, {struct_name}_destructor);
if (thunk != NULL && PyCapsule_SetContext(thunk, struct_ptr) != 0) {{
PyErr_Clear();
Py_DECREF(thunk);
thunk = NULL;
}}
""".format(**locals())
else:
print >> code, ' PyObject* thunk = PyCObject_FromVoidPtrAndDesc((void*)(&%(struct_name)s_executor), struct_ptr, %(struct_name)s_destructor);' % locals()
print >> code, " return thunk; }" print >> code, " return thunk; }"
return code.getvalue() return code.getvalue()
......
...@@ -13,6 +13,7 @@ import subprocess ...@@ -13,6 +13,7 @@ import subprocess
import sys import sys
import tempfile import tempfile
import time import time
from six import PY3, b, next
import distutils.sysconfig import distutils.sysconfig
...@@ -164,11 +165,27 @@ class DynamicModule(object): ...@@ -164,11 +165,27 @@ class DynamicModule(object):
print >> stream, "};" print >> stream, "};"
def print_init(self, stream): def print_init(self, stream):
print >> stream, "PyMODINIT_FUNC init%s(void){" % self.name if PY3:
for b in self.init_blocks: print >> stream, """\
print >> stream, ' ', b static struct PyModuleDef moduledef = {{
print >> stream, ' ', ('(void) Py_InitModule("%s", MyMethods);' PyModuleDef_HEAD_INIT,
% self.name) "{name}",
NULL,
-1,
MyMethods,
}};
""".format(name=self.name)
print >> stream, "PyMODINIT_FUNC PyInit_%s(void) {" % self.name
for b in self.init_blocks:
print >> stream, ' ', b
print >> stream, " PyObject *m = PyModule_Create(&moduledef);"
print >> stream, " return m;"
else:
print >> stream, "PyMODINIT_FUNC init%s(void){" % self.name
for b in self.init_blocks:
print >> stream, ' ', b
print >> stream, ' ', ('(void) Py_InitModule("%s", MyMethods);'
% self.name)
print >> stream, "}" print >> stream, "}"
def add_include(self, str): def add_include(self, str):
...@@ -917,7 +934,7 @@ class ModuleCache(object): ...@@ -917,7 +934,7 @@ class ModuleCache(object):
# If we do, then there is no need to even compile it. # If we do, then there is no need to even compile it.
duplicated_module = False duplicated_module = False
# The first compilation step is to yield the source code. # The first compilation step is to yield the source code.
src_code = compile_steps.next() src_code = next(compile_steps)
module_hash = get_module_hash(src_code, key) module_hash = get_module_hash(src_code, key)
# The op has c_code, so take the lock. # The op has c_code, so take the lock.
...@@ -972,7 +989,7 @@ class ModuleCache(object): ...@@ -972,7 +989,7 @@ class ModuleCache(object):
try: try:
# The module should be returned by the last # The module should be returned by the last
# step of the compilation. # step of the compilation.
module = compile_steps.next() module = next(compile_steps)
except StopIteration: except StopIteration:
break break
...@@ -1572,7 +1589,7 @@ class GCC_compiler(object): ...@@ -1572,7 +1589,7 @@ class GCC_compiler(object):
lib_dirs.append(python_lib) lib_dirs.append(python_lib)
cppfilename = os.path.join(location, 'mod.cpp') cppfilename = os.path.join(location, 'mod.cpp')
cppfile = file(cppfilename, 'w') cppfile = open(cppfilename, 'w')
_logger.debug('Writing module C++ code to %s', cppfilename) _logger.debug('Writing module C++ code to %s', cppfilename)
...@@ -1630,14 +1647,15 @@ class GCC_compiler(object): ...@@ -1630,14 +1647,15 @@ class GCC_compiler(object):
# prints the exception, having '\n' in the text makes it more # prints the exception, having '\n' in the text makes it more
# difficult to read. # difficult to read.
raise Exception('Compilation failed (return status=%s): %s' % raise Exception('Compilation failed (return status=%s): %s' %
(status, compile_stderr.replace('\n', '. '))) (status, compile_stderr.replace(b('\n'), b('. '))))
elif config.cmodule.compilation_warning and compile_stderr: elif config.cmodule.compilation_warning and compile_stderr:
# Print errors just below the command line. # Print errors just below the command line.
print compile_stderr print compile_stderr
if py_module: if py_module:
#touch the __init__ file #touch the __init__ file
file(os.path.join(location, "__init__.py"), 'w').close() open(os.path.join(location, "__init__.py"), 'w').close()
assert os.path.isfile(lib_filename)
return dlimport(lib_filename) return dlimport(lib_filename)
......
...@@ -27,7 +27,7 @@ try: ...@@ -27,7 +27,7 @@ try:
stdin=dummy_in.fileno(), stdin=dummy_in.fileno(),
stderr=dummy_err.fileno()) stderr=dummy_err.fileno())
p.wait() p.wait()
gcc_version_str = p.stdout.readline().strip() gcc_version_str = p.stdout.readline().strip().decode()
except OSError: except OSError:
# Typically means gcc cannot be found. # Typically means gcc cannot be found.
gcc_version_str = 'GCC_NOT_FOUND' gcc_version_str = 'GCC_NOT_FOUND'
......
import os import os
import sys import sys
from six import PY3
from theano.gof.compilelock import get_lock, release_lock from theano.gof.compilelock import get_lock, release_lock
from theano import config from theano import config
...@@ -38,8 +39,29 @@ def compile_cutils(): ...@@ -38,8 +39,29 @@ def compile_cutils():
{"run_cthunk", run_cthunk, METH_VARARGS|METH_KEYWORDS, {"run_cthunk", run_cthunk, METH_VARARGS|METH_KEYWORDS,
"Run a theano cthunk."}, "Run a theano cthunk."},
{NULL, NULL, 0, NULL} /* Sentinel */ {NULL, NULL, 0, NULL} /* Sentinel */
};"""
if PY3:
# This is not the most efficient code, but it is written this way to highlight
# the changes needed to make 2.x code compile under python 3.
code = code.replace("<Python.h>", '"numpy/npy_3kcompat.h"', 1)
code = code.replace("PyCObject", "NpyCapsule")
code += """
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"cutils_ext",
NULL,
-1,
CutilsExtMethods,
}; };
PyMODINIT_FUNC
PyInit_cutils_ext(void) {
return PyModule_Create(&moduledef);
}
}
"""
else:
code += """
PyMODINIT_FUNC PyMODINIT_FUNC
initcutils_ext(void) initcutils_ext(void)
{ {
...@@ -68,7 +90,7 @@ try: ...@@ -68,7 +90,7 @@ try:
if not os.path.exists(location): if not os.path.exists(location):
os.mkdir(location) os.mkdir(location)
if not os.path.exists(os.path.join(location, '__init__.py')): if not os.path.exists(os.path.join(location, '__init__.py')):
file(os.path.join(location, '__init__.py'), 'w').close() open(os.path.join(location, '__init__.py'), 'w').close()
try: try:
from cutils_ext.cutils_ext import * from cutils_ext.cutils_ext import *
......
...@@ -13,6 +13,17 @@ typedef int Py_ssize_t; ...@@ -13,6 +13,17 @@ typedef int Py_ssize_t;
#define PyNumber_AsSsize_t(ob, exc) PyInt_AsLong(ob) #define PyNumber_AsSsize_t(ob, exc) PyInt_AsLong(ob)
#endif #endif
#if PY_VERSION_HEX >= 0x03000000
#include "numpy/npy_3kcompat.h"
#define PyCObject_AsVoidPtr NpyCapsule_AsVoidPtr
#define PyCObject_GetDesc NpyCapsule_GetDesc
#define PyCObject_Check NpyCapsule_Check
#endif
#ifndef Py_TYPE
#define Py_TYPE(obj) obj->ob_type
#endif
/** /**
TODO: TODO:
...@@ -172,7 +183,7 @@ CLazyLinker_dealloc(PyObject* _self) ...@@ -172,7 +183,7 @@ CLazyLinker_dealloc(PyObject* _self)
Py_XDECREF(self->call_times); Py_XDECREF(self->call_times);
Py_XDECREF(self->call_counts); Py_XDECREF(self->call_counts);
Py_XDECREF(self->pre_call_clear); Py_XDECREF(self->pre_call_clear);
self->ob_type->tp_free((PyObject*)self); Py_TYPE(self)->tp_free((PyObject*)self);
} }
static PyObject * static PyObject *
CLazyLinker_new(PyTypeObject *type, PyObject *args, PyObject *kwds) CLazyLinker_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
...@@ -937,8 +948,12 @@ static PyMemberDef CLazyLinker_members[] = { ...@@ -937,8 +948,12 @@ static PyMemberDef CLazyLinker_members[] = {
}; };
static PyTypeObject lazylinker_ext_CLazyLinkerType = { static PyTypeObject lazylinker_ext_CLazyLinkerType = {
#if defined(NPY_PY3K)
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /*ob_size*/ 0, /*ob_size*/
#endif
"lazylinker_ext.CLazyLinker", /*tp_name*/ "lazylinker_ext.CLazyLinker", /*tp_name*/
sizeof(CLazyLinker), /*tp_basicsize*/ sizeof(CLazyLinker), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
...@@ -992,19 +1007,44 @@ static PyMethodDef lazylinker_ext_methods[] = { ...@@ -992,19 +1007,44 @@ static PyMethodDef lazylinker_ext_methods[] = {
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void #define PyMODINIT_FUNC void
#endif #endif
#if defined(NPY_PY3K)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"lazylinker_ext",
NULL,
-1,
lazylinker_ext_methods,
NULL,
NULL,
NULL,
NULL
};
#endif
#if defined(NPY_PY3K)
#define RETVAL m
PyMODINIT_FUNC
PyInit_lazylinker_ext(void) {
#else
#define RETVAL
PyMODINIT_FUNC PyMODINIT_FUNC
initlazylinker_ext(void) initlazylinker_ext(void)
{ {
#endif
PyObject* m; PyObject* m;
lazylinker_ext_CLazyLinkerType.tp_new = PyType_GenericNew; lazylinker_ext_CLazyLinkerType.tp_new = PyType_GenericNew;
if (PyType_Ready(&lazylinker_ext_CLazyLinkerType) < 0) if (PyType_Ready(&lazylinker_ext_CLazyLinkerType) < 0)
return; return RETVAL;
#if defined(NPY_PY3K)
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule3("lazylinker_ext", lazylinker_ext_methods, m = Py_InitModule3("lazylinker_ext", lazylinker_ext_methods,
"Example module that creates an extension type."); "Example module that creates an extension type.");
#endif
Py_INCREF(&lazylinker_ext_CLazyLinkerType); Py_INCREF(&lazylinker_ext_CLazyLinkerType);
PyModule_AddObject(m, "CLazyLinker", (PyObject *)&lazylinker_ext_CLazyLinkerType); PyModule_AddObject(m, "CLazyLinker", (PyObject *)&lazylinker_ext_CLazyLinkerType);
return RETVAL;
} }
import errno import errno
import os, logging, sys import os, logging, sys
from six.moves import reload_module as reload
import theano import theano
from theano import config from theano import config
...@@ -45,7 +46,7 @@ try: ...@@ -45,7 +46,7 @@ try:
assert os.path.isdir(location) assert os.path.isdir(location)
if not os.path.exists(os.path.join(location, '__init__.py')): if not os.path.exists(os.path.join(location, '__init__.py')):
file(os.path.join(location, '__init__.py'), 'w').close() open(os.path.join(location, '__init__.py'), 'w').close()
_need_reload = False _need_reload = False
if force_compile: if force_compile:
......
...@@ -49,6 +49,16 @@ class Optimizer(object): ...@@ -49,6 +49,16 @@ class Optimizer(object):
_optimizer_idx[0] += 1 _optimizer_idx[0] += 1
return self._optimizer_idx return self._optimizer_idx
def __eq__(self, other):
# added to override the __eq__ implementation that may be inherited
# in subclasses from other bases.
return id(self) == id(other)
def __neq__(self, other):
# added to override the __neq__ implementation that may be inherited
# in subclasses from other bases.
return id(self) != id(other)
def apply(self, fgraph): def apply(self, fgraph):
"""WRITEME """WRITEME
Applies the optimization to the provided L{FunctionGraph}. It may Applies the optimization to the provided L{FunctionGraph}. It may
...@@ -177,14 +187,6 @@ class SeqOptimizer(Optimizer, list): ...@@ -177,14 +187,6 @@ class SeqOptimizer(Optimizer, list):
return (self, l, validate_time, nb_node_before, return (self, l, validate_time, nb_node_before,
len(fgraph.apply_nodes), sub_profs) len(fgraph.apply_nodes), sub_profs)
def __eq__(self, other):
#added to override the list's __eq__ implementation
return id(self) == id(other)
def __neq__(self, other):
#added to override the list's __neq__ implementation
return id(self) != id(other)
def __str__(self): def __str__(self):
return "SeqOpt(%s)" % list.__str__(self) return "SeqOpt(%s)" % list.__str__(self)
......
...@@ -8,7 +8,11 @@ from theano.gof import fg ...@@ -8,7 +8,11 @@ from theano.gof import fg
from theano.gof import toolbox from theano.gof import toolbox
from theano.gof.link import * from theano.gof.link import *
try:
cmp
except NameError:
def cmp(a, b):
return (a > b) - (a < b)
def as_variable(x): def as_variable(x):
assert isinstance(x, Variable) assert isinstance(x, Variable)
......
...@@ -6,7 +6,7 @@ import shutil ...@@ -6,7 +6,7 @@ import shutil
import stat import stat
import sys import sys
import numpy import six
import theano import theano
from theano.compile import optdb from theano.compile import optdb
...@@ -243,7 +243,7 @@ class GpuOp(theano.gof.Op): ...@@ -243,7 +243,7 @@ class GpuOp(theano.gof.Op):
return super(GpuOp, self).make_thunk(node, storage_map, return super(GpuOp, self).make_thunk(node, storage_map,
compute_map, no_recycling) compute_map, no_recycling)
theano.compile.debugmode.default_make_thunk.append(GpuOp.make_thunk.im_func) theano.compile.debugmode.default_make_thunk.append(six.get_unbound_function(GpuOp.make_thunk))
# We must do those import to be able to create the full doc when # We must do those import to be able to create the full doc when
# nvcc is not available # nvcc is not available
......
...@@ -18,6 +18,7 @@ from copy import copy ...@@ -18,6 +18,7 @@ from copy import copy
from itertools import imap from itertools import imap
from textwrap import dedent from textwrap import dedent
from six import PY3
import numpy import numpy
import theano import theano
...@@ -515,8 +516,12 @@ class _scalar_py_operators: ...@@ -515,8 +516,12 @@ class _scalar_py_operators:
def __mul__(self, other): def __mul__(self, other):
return mul(self, other) return mul(self, other)
def __div__(self, other): if PY3:
return div_proxy(self, other) def __truediv__(self, other):
return div_proxy(self, other)
else:
def __div__(self, other):
return div_proxy(self, other)
def __floordiv__(self, other): def __floordiv__(self, other):
return int_div(self, other) return int_div(self, other)
......
...@@ -13,7 +13,9 @@ imported_scipy_special = False ...@@ -13,7 +13,9 @@ imported_scipy_special = False
try: try:
import scipy.special import scipy.special
imported_scipy_special = True imported_scipy_special = True
except ImportError: # Importing scipy.special may raise ValueError.
# See http://projects.scipy.org/scipy/ticket/1739
except (ImportError, ValueError):
pass pass
......
import logging import os, logging, sys
import os from six.moves import reload_module as reload
import sys
import theano import theano
from theano import config from theano import config
......
...@@ -6,6 +6,7 @@ import sys ...@@ -6,6 +6,7 @@ import sys
import warnings import warnings
from itertools import izip from itertools import izip
from six import PY3
import numpy import numpy
#from copy import copy as python_copy #from copy import copy as python_copy
...@@ -495,7 +496,7 @@ def get_scalar_constant_value(v): ...@@ -495,7 +496,7 @@ def get_scalar_constant_value(v):
# on passing it None) # on passing it None)
raise NotScalarConstantError() raise NotScalarConstantError()
if isinstance(v, (int, float)): if isinstance(v, (numpy.integer, int, float)):
return numpy.asarray(v) return numpy.asarray(v)
def numpy_scalar(n): def numpy_scalar(n):
...@@ -1542,6 +1543,8 @@ class _tensor_py_operators: ...@@ -1542,6 +1543,8 @@ class _tensor_py_operators:
raise raise
except (NotImplementedError, TypeError): except (NotImplementedError, TypeError):
return NotImplemented return NotImplemented
if PY3:
__truediv__ = __div__
def __pow__(self, other): def __pow__(self, other):
# See explanation in __add__ for the error catched # See explanation in __add__ for the error catched
...@@ -4411,8 +4414,9 @@ class Subtensor(Op): ...@@ -4411,8 +4414,9 @@ class Subtensor(Op):
slice_c = None slice_c = None
return slice(slice_a, slice_b, slice_c) return slice(slice_a, slice_b, slice_c)
# There is a bug in numpy that results in isinstance(x, int) returning False for numpy integers.
elif isinstance(entry, int): # See <http://projects.scipy.org/numpy/ticket/2235>.
elif isinstance(entry, (numpy.integer, int)):
return entry return entry
else: else:
raise AdvancedIndexingError(Subtensor.e_indextype, entry) raise AdvancedIndexingError(Subtensor.e_indextype, entry)
......
...@@ -123,7 +123,9 @@ class DimShuffle(Op): ...@@ -123,7 +123,9 @@ class DimShuffle(Op):
for i, j in enumerate(new_order): for i, j in enumerate(new_order):
if j != 'x': if j != 'x':
if not isinstance(j, int): # There is a bug in numpy that results in isinstance(x, int) returning False for numpy integers.
# See <http://projects.scipy.org/numpy/ticket/2235>.
if not isinstance(j, (int, numpy.integer)):
raise TypeError( raise TypeError(
"DimShuffle indices must be python ints.") "DimShuffle indices must be python ints.")
if j >= len(input_broadcastable): if j >= len(input_broadcastable):
...@@ -1178,7 +1180,9 @@ class CAReduce(Op): ...@@ -1178,7 +1180,9 @@ class CAReduce(Op):
if axis is None: if axis is None:
self.axis = axis self.axis = axis
elif isinstance(axis, int): # There is a bug in numpy that results in isinstance(x, int) returning False for numpy integers.
# See <http://projects.scipy.org/numpy/ticket/2235>.
elif isinstance(axis, (int, numpy.integer)):
self.axis = (axis,) self.axis = (axis,)
else: else:
self.axis = list(set(axis)) self.axis = list(set(axis))
......
...@@ -224,8 +224,8 @@ def inplace_elemwise_optimizer_op(OP): ...@@ -224,8 +224,8 @@ def inplace_elemwise_optimizer_op(OP):
candidate_output].type: candidate_output].type:
continue continue
inplace_pattern = dict(baseline, **{candidate_output: inplace_pattern = dict(baseline)
candidate_input}) inplace_pattern[candidate_output] = candidate_input
try: try:
if hasattr(op.scalar_op, "make_new_inplace"): if hasattr(op.scalar_op, "make_new_inplace"):
new_scal = op.scalar_op.make_new_inplace( new_scal = op.scalar_op.make_new_inplace(
...@@ -510,7 +510,7 @@ class MakeVector(T.Op): ...@@ -510,7 +510,7 @@ class MakeVector(T.Op):
"The upcast of the inputs to MakeVector should match the " "The upcast of the inputs to MakeVector should match the "
"dtype given in __init__.") "dtype given in __init__.")
if not all(self.dtype == T.cast(i, dtype=dtype).dtype if not all(self.dtype == T.cast(i, dtype=dtype).dtype
for a in inputs): for i in inputs):
raise TypeError("MakeVector.make_node expected inputs" raise TypeError("MakeVector.make_node expected inputs"
" upcastable to %s. got %s" % ( " upcastable to %s. got %s" % (
self.dtype, self.dtype,
......
...@@ -8,10 +8,28 @@ from tempfile import mkstemp ...@@ -8,10 +8,28 @@ from tempfile import mkstemp
import unittest import unittest
import warnings import warnings
from copy import copy, deepcopy from copy import copy, deepcopy
from itertools import izip
# Import builtin min to be able to use it after importing the tensor version. # Import builtin min to be able to use it after importing the tensor version.
import __builtin__ import __builtin__
builtin_min = __builtin__.min builtin_min = __builtin__.min
from six import PY3
if PY3:
operator_div = operator.truediv
# In python 3.x, when an exception is reraised it saves original
# exception in its args, therefore in order to find the actual
# message, we need to unpack arguments recurcively.
def exc_message(e):
msg = e.args[0]
if isinstance(msg, Exception):
return exc_message(msg)
return msg
else:
operator_div = operator.div
def exc_message(e):
return e[0]
from nose.plugins.skip import SkipTest from nose.plugins.skip import SkipTest
import numpy import numpy
from numpy.testing import dec, assert_array_equal, assert_allclose from numpy.testing import dec, assert_array_equal, assert_allclose
...@@ -25,7 +43,7 @@ from theano.gof.python25 import any, all, combinations ...@@ -25,7 +43,7 @@ from theano.gof.python25 import any, all, combinations
from theano.tensor import (_shared, wvector, bvector, autocast_float_as, from theano.tensor import (_shared, wvector, bvector, autocast_float_as,
argmin, max_and_argmax, cscalar, Subtensor, ctensor3, join, argmin, max_and_argmax, cscalar, Subtensor, ctensor3, join,
horizontal_stack, vertical_stack, argmax, get_vector_length, horizontal_stack, vertical_stack, argmax, get_vector_length,
fscalar, zeros_like, sum, tensor3, vector, izip, add, addbroadcast, fscalar, zeros_like, sum, tensor3, vector, add, addbroadcast,
alloc, as_tensor_variable, tensor_from_scalar, ARange, autocast_float, alloc, as_tensor_variable, tensor_from_scalar, ARange, autocast_float,
clip, constant, default, dot, inc_subtensor, set_subtensor, clip, constant, default, dot, inc_subtensor, set_subtensor,
dmatrix, dscalar, dvector, eq, eye, fill, flatten, inverse_permutation, dmatrix, dscalar, dvector, eq, eye, fill, flatten, inverse_permutation,
...@@ -727,14 +745,21 @@ _good_broadcast_div_mod_normal_float_no_complex = dict( ...@@ -727,14 +745,21 @@ _good_broadcast_div_mod_normal_float_no_complex = dict(
#empty2=(numpy.asarray([0]), numpy.asarray([])), #empty2=(numpy.asarray([0]), numpy.asarray([])),
) )
_good_broadcast_div_mod_normal_float_inplace = copymod( if PY3:
_good_broadcast_div_mod_normal_float_no_complex, _good_broadcast_div_mod_normal_float_inplace = copymod(
empty1=(numpy.asarray([]), numpy.asarray([1])), _good_broadcast_div_mod_normal_float_no_complex,
complex1=(randcomplex(2, 3), randcomplex_nonzero((2, 3))), empty1=(numpy.asarray([]), numpy.asarray([1])),
complex2=(randcomplex(2, 3), rand_nonzero((2, 3))), # No complex floor division in python 3.x
# Inplace on the first element. Must have the same type. )
#complex3=(rand(2, 3) ,randcomplex(2, 3)), else:
) _good_broadcast_div_mod_normal_float_inplace = copymod(
_good_broadcast_div_mod_normal_float_no_complex,
empty1=(numpy.asarray([]), numpy.asarray([1])),
complex1=(randcomplex(2, 3), randcomplex_nonzero((2, 3))),
complex2=(randcomplex(2, 3), rand_nonzero((2, 3))),
# Inplace on the first element. Must have the same type.
#complex3=(rand(2, 3) ,randcomplex(2, 3)),
)
_good_broadcast_div_mod_normal_float = copymod( _good_broadcast_div_mod_normal_float = copymod(
_good_broadcast_div_mod_normal_float_inplace, _good_broadcast_div_mod_normal_float_inplace,
...@@ -2804,7 +2829,7 @@ class T_subtensor(unittest.TestCase, utt.TestOptimizationMixin): ...@@ -2804,7 +2829,7 @@ class T_subtensor(unittest.TestCase, utt.TestOptimizationMixin):
self.eval_output_and_check(t) self.eval_output_and_check(t)
assert 0 assert 0
except Exception, e: except Exception, e:
if e[0] != 'index out of bounds': if exc_message(e) != 'index out of bounds':
raise raise
finally: finally:
_logger.setLevel(oldlevel) _logger.setLevel(oldlevel)
...@@ -4328,8 +4353,8 @@ class T_divimpl(unittest.TestCase): ...@@ -4328,8 +4353,8 @@ class T_divimpl(unittest.TestCase):
assert numpy.allclose(function([i, d], d / i)(5, 7.0), (7.0 / 5.0)) assert numpy.allclose(function([i, d], d / i)(5, 7.0), (7.0 / 5.0))
assert numpy.allclose(function([i, f], i / f)(5, 11.0), (5.0 / 11.0)) assert numpy.allclose(function([i, f], i / f)(5, 11.0), (5.0 / 11.0))
assert numpy.allclose(function([i, f], f / i)(5, 11.0), (11.0 / 5.0)) assert numpy.allclose(function([i, f], f / i)(5, 11.0), (11.0 / 5.0))
assert numpy.allclose(function([i, ii], i // ii)(5, 3), (5 / 3)) assert numpy.allclose(function([i, ii], i // ii)(5, 3), (5 // 3))
assert numpy.allclose(function([i, ii], ii // i)(5, 3), (3 / 5)) assert numpy.allclose(function([i, ii], ii // i)(5, 3), (3 // 5))
assert numpy.allclose(function([i, ii], true_div(i, ii))(5, 3), assert numpy.allclose(function([i, ii], true_div(i, ii))(5, 3),
(5. / 3.)) (5. / 3.))
assert numpy.allclose(function([i, ii], true_div(ii, i))(5, 3), assert numpy.allclose(function([i, ii], true_div(ii, i))(5, 3),
...@@ -4570,17 +4595,18 @@ class t_dot(unittest.TestCase): ...@@ -4570,17 +4595,18 @@ class t_dot(unittest.TestCase):
tz = eval_outputs([z]) tz = eval_outputs([z])
assert False # should have raised exception assert False # should have raised exception
except ValueError, e: except ValueError, e:
e0 = exc_message(e)
self.assertTrue( self.assertTrue(
# Reported by numpy. # Reported by numpy.
e[0].split()[1:4] == ['are', 'not', 'aligned'] or e0.split()[1:4] == ['are', 'not', 'aligned'] or
# Reported by blas or Theano. # Reported by blas or Theano.
e[0].split()[0:2] == ['Shape', 'mismatch:'] or e0.split()[0:2] == ['Shape', 'mismatch:'] or
# Reported by Theano perform # Reported by Theano perform
e[0].split()[0:4] e0.split()[0:4]
== ['Incompatible', 'shapes', 'for', 'gemv'] or == ['Incompatible', 'shapes', 'for', 'gemv'] or
# Reported by Theano when 'exception_verbosity' is set # Reported by Theano when 'exception_verbosity' is set
# to 'high'. # to 'high'.
e[0].split()[0:3] == ['dot', 'product', 'failed.'], e0.split()[0:3] == ['dot', 'product', 'failed.'],
e) e)
finally: finally:
_logger.setLevel(oldlevel) _logger.setLevel(oldlevel)
...@@ -6051,7 +6077,7 @@ class test_arithmetic_cast(unittest.TestCase): ...@@ -6051,7 +6077,7 @@ class test_arithmetic_cast(unittest.TestCase):
for cfg in ('numpy+floatX', ): # Used to test 'numpy' as well. for cfg in ('numpy+floatX', ): # Used to test 'numpy' as well.
config.cast_policy = cfg config.cast_policy = cfg
for op in (operator.add, operator.sub, operator.mul, for op in (operator.add, operator.sub, operator.mul,
operator.div, operator.floordiv): operator_div, operator.floordiv):
for a_type in dtypes: for a_type in dtypes:
for b_type in dtypes: for b_type in dtypes:
# Note that we do not test division between # Note that we do not test division between
...@@ -6059,7 +6085,7 @@ class test_arithmetic_cast(unittest.TestCase): ...@@ -6059,7 +6085,7 @@ class test_arithmetic_cast(unittest.TestCase):
# Theano deals with integer division in its own # Theano deals with integer division in its own
# special way (depending on `config.int_division`). # special way (depending on `config.int_division`).
is_int_division = ( is_int_division = (
op is operator.div and op is operator_div and
a_type in tensor.discrete_dtypes and a_type in tensor.discrete_dtypes and
b_type in tensor.discrete_dtypes) b_type in tensor.discrete_dtypes)
# We will test all meaningful combinations of # We will test all meaningful combinations of
...@@ -6142,12 +6168,12 @@ class test_arithmetic_cast(unittest.TestCase): ...@@ -6142,12 +6168,12 @@ class test_arithmetic_cast(unittest.TestCase):
config.int_division == 'floatX'): config.int_division == 'floatX'):
assert theano_dtype == config.floatX assert theano_dtype == config.floatX
continue continue
numpy_version =numpy.__version__.split('.')[:2] numpy_version = numpy.__version__.split('.')[:2]
if (cfg == 'numpy+floatX' and if (cfg == 'numpy+floatX' and
a_type == 'complex128' and a_type == 'complex128' and
b_type == 'float32' and b_type == 'float32' and
combo == ('scalar', 'array') and combo == ('scalar', 'array') and
bool(numpy_version >= [1, 6]) and bool(numpy_version >= ['1', '6']) and
theano_dtype == 'complex128' and theano_dtype == 'complex128' and
numpy_dtypes == ['complex64', numpy_dtypes == ['complex64',
'complex64']): 'complex64']):
......
try: try:
from main import main, TheanoNoseTester from theano.tests.main import main, TheanoNoseTester
except ImportError: except ImportError:
pass pass
import unittest_tools from theano.tests import unittest_tools
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论