提交 39c511ea authored 作者: abalkin's avatar abalkin

More python 3.x fixes:

* allow numpy array as an argument to hash_from_code. * use truediv instead of div under 3.x. * **kwds checks that keys are strings in 3.x * fixed a typo bug in tensor/opt.py * fixed an incorrect numpy version check in test_basic
上级 95531c52
...@@ -17,9 +17,13 @@ if sys.version_info[:2] >= (3, 0): ...@@ -17,9 +17,13 @@ if sys.version_info[:2] >= (3, 0):
import hashlib import hashlib
def hash_from_code(msg): 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 # Python 3 does not like module names that start with
# a digit. # a digit.
return 'm' + hashlib.md5(msg.encode()).hexdigest() return 'm' + hashlib.md5(msg).hexdigest()
elif sys.version_info[:2] >= (2, 5): elif sys.version_info[:2] >= (2, 5):
import hashlib import hashlib
......
...@@ -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,6 +516,10 @@ class _scalar_py_operators: ...@@ -515,6 +516,10 @@ class _scalar_py_operators:
def __mul__(self, other): def __mul__(self, other):
return mul(self, other) return mul(self, other)
if PY3:
def __truediv__(self, other):
return div_proxy(self, other)
else:
def __div__(self, other): def __div__(self, other):
return div_proxy(self, other) return div_proxy(self, other)
......
...@@ -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
...@@ -1513,6 +1514,8 @@ class _tensor_py_operators: ...@@ -1513,6 +1514,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
......
...@@ -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):
...@@ -1177,7 +1179,9 @@ class CAReduce(Op): ...@@ -1177,7 +1179,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,
......
...@@ -13,6 +13,12 @@ from itertools import izip ...@@ -13,6 +13,12 @@ from itertools import izip
import __builtin__ import __builtin__
builtin_min = __builtin__.min builtin_min = __builtin__.min
from six import PY3
if PY3:
operator_div = operator.truediv
else:
operator_div = operator.div
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
...@@ -4420,7 +4426,7 @@ class t_dot(unittest.TestCase): ...@@ -4420,7 +4426,7 @@ class t_dot(unittest.TestCase):
== ['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.'], e.args[0].split()[0:3] == ['dot', 'product', 'failed.'],
e) e)
finally: finally:
_logger.setLevel(oldlevel) _logger.setLevel(oldlevel)
...@@ -5891,7 +5897,7 @@ class test_arithmetic_cast(unittest.TestCase): ...@@ -5891,7 +5897,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
...@@ -5899,7 +5905,7 @@ class test_arithmetic_cast(unittest.TestCase): ...@@ -5899,7 +5905,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
...@@ -5982,12 +5988,12 @@ class test_arithmetic_cast(unittest.TestCase): ...@@ -5982,12 +5988,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']):
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论