提交 bd7bfba9 authored 作者: Frédéric Bastien's avatar Frédéric Bastien 提交者: GitHub

Merge pull request #4924 from nouiz/drop_old_version

Drop old version
...@@ -8,7 +8,7 @@ cache: ...@@ -8,7 +8,7 @@ cache:
language: python language: python
python: python:
- "2.6" - "2.7"
- "3.3" - "3.3"
# command to install dependencies # command to install dependencies
...@@ -16,7 +16,7 @@ before_install: ...@@ -16,7 +16,7 @@ before_install:
# Install miniconda to avoid compiling scipy # Install miniconda to avoid compiling scipy
- mkdir -p download - mkdir -p download
- cd download - cd download
- wget -c https://repo.continuum.io/miniconda/Miniconda2-3.19.0-Linux-x86_64.sh -O miniconda.sh - wget -c https://repo.continuum.io/miniconda/Miniconda2-4.1.11-Linux-x86_64.sh -O miniconda.sh
- chmod +x miniconda.sh - chmod +x miniconda.sh
- ./miniconda.sh -b - ./miniconda.sh -b
- cd .. - cd ..
...@@ -30,11 +30,10 @@ addons: ...@@ -30,11 +30,10 @@ addons:
- dvipng - dvipng
install: install:
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then conda create --yes -q -n pyenv mkl python=2.6 numpy=1.7.1 scipy=0.11 nose=1.3.0 pip flake8=2.3 six=1.9.0 pep8=1.6.2 pyflakes=0.8.1 sphinx; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then conda create --yes -q -n pyenv mkl python=2.7 numpy=1.9.1 scipy=0.14 nose=1.3.0 pip flake8=2.3 six=1.9.0 pep8=1.6.2 pyflakes=0.8.1 sphinx libgfortran=1 mkl-service; fi
- if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then conda create --yes -q -n pyenv mkl python=3.3 numpy=1.9.1 scipy=0.14.0 nose=1.3.4 pip flake8=2.3 six=1.9.0 pep8=1.6.2 pyflakes=0.8.1 sphinx; fi - if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then conda create --yes -q -n pyenv mkl python=3.3 numpy=1.9.1 scipy=0.14.0 nose=1.3.4 pip flake8=2.3 six=1.9.0 pep8=1.6.2 pyflakes=0.8.1 sphinx mkl-service; fi
- source activate pyenv - source activate pyenv
# pydot 1.2 broke support of python 2.6. They won't try to maintain it. - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install pydot; else pip install pydot-ng; fi
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install pydot==1.1.0; else pip install pydot-ng; fi
- pip install . --no-deps - pip install . --no-deps
- pip install flake8-future-import nose-parameterized==0.5.0 - pip install flake8-future-import nose-parameterized==0.5.0
...@@ -49,7 +48,7 @@ matrix: ...@@ -49,7 +48,7 @@ matrix:
include: include:
- python: "3.3" - python: "3.3"
env: PART="-e test_flake8.py ." THEANO_FLAGS="mode=FAST_COMPILE" env: PART="-e test_flake8.py ." THEANO_FLAGS="mode=FAST_COMPILE"
- python: "2.6" - python: "2.7"
env: PART="-e test_flake8.py ." THEANO_FLAGS="mode=FAST_COMPILE,floatX=float32" env: PART="-e test_flake8.py ." THEANO_FLAGS="mode=FAST_COMPILE,floatX=float32"
script: script:
......
...@@ -42,10 +42,16 @@ todo_include_todos = True ...@@ -42,10 +42,16 @@ todo_include_todos = True
napoleon_google_docstring = False napoleon_google_docstring = False
napoleon_include_special_with_doc = False napoleon_include_special_with_doc = False
# We do it like this to support multiple sphinx version without having warning.
# Our buildbot consider warning as error.
try: try:
from sphinx.ext import imgmath
extensions.append('sphinx.ext.imgmath')
except ImportError:
try:
from sphinx.ext import pngmath from sphinx.ext import pngmath
extensions.append('sphinx.ext.pngmath') extensions.append('sphinx.ext.pngmath')
except ImportError: except ImportError:
pass pass
......
...@@ -8,13 +8,16 @@ Requirements ...@@ -8,13 +8,16 @@ Requirements
.. _BLAS: http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms .. _BLAS: http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms
.. _Python: http://www.python.org/ .. _Python: http://www.python.org/
Python_ >= 2.6 or >= 3.3 Python_ >= 2.7 or >= 3.3 The development package (python-dev or
The development package (python-dev or python-devel on most Linux distributions) is recommended (see just below). Python 2.4 was supported up to and including the release 0.6. Python 3 is supported past the 3.3 release. python-devel on most Linux distributions) is recommended (see
just below). Python 2.4 was supported up to and including the
release 0.6. Python 2.6 was supported up to and including the
release 0.8.2. Python 3 is supported past the 3.3 release.
`NumPy <http://numpy.scipy.org/>`_ >= 1.7.1 < 1.11.1 `NumPy <http://numpy.scipy.org/>`_ >= 1.9.1 < 1.11.1
Earlier versions could work, but we don’t test it. Earlier versions could work, but we don’t test it.
`SciPy <http://scipy.org>`_ >= 0.11 < 0.17.1 `SciPy <http://scipy.org>`_ >= 0.14 < 0.17.1
Only currently required for sparse matrix and special functions support, but highly recommended. SciPy >=0.8 could work, but earlier versions have known bugs with sparse matrices. Only currently required for sparse matrix and special functions support, but highly recommended. SciPy >=0.8 could work, but earlier versions have known bugs with sparse matrices.
`BLAS`_ installation (with Level 3 functionality) `BLAS`_ installation (with Level 3 functionality)
......
...@@ -31,7 +31,6 @@ Operating System :: POSIX ...@@ -31,7 +31,6 @@ Operating System :: POSIX
Operating System :: Unix Operating System :: Unix
Operating System :: MacOS Operating System :: MacOS
Programming Language :: Python :: 2 Programming Language :: Python :: 2
Programming Language :: Python :: 2.6
Programming Language :: Python :: 2.7 Programming Language :: Python :: 2.7
Programming Language :: Python :: 3 Programming Language :: Python :: 3
Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.3
...@@ -163,7 +162,7 @@ def do_setup(): ...@@ -163,7 +162,7 @@ def do_setup():
platforms=PLATFORMS, platforms=PLATFORMS,
packages=find_packages(), packages=find_packages(),
# 1.7.0 give too much warning related to numpy.diagonal. # 1.7.0 give too much warning related to numpy.diagonal.
install_requires=['numpy>=1.7.1', 'scipy>=0.11', 'six>=1.9.0'], install_requires=['numpy>=1.9.1', 'scipy>=0.14', 'six>=1.9.0'],
# pygments is a dependency for Sphinx code highlight # pygments is a dependency for Sphinx code highlight
extras_require={ extras_require={
'test': ['nose>=1.3.0', 'nose-parameterized>=0.5.0', 'flake8<3'], 'test': ['nose>=1.3.0', 'nose-parameterized>=0.5.0', 'flake8<3'],
......
""" """
Helper functions to make theano backwards compatible with python 2.6 - 2.7 Helper functions to make theano backwards compatible with python 2.6 - 2.7
Now mostly there for compatibility as we don't support Python 2.6 anymore.
""" """
from __future__ import absolute_import, print_function, division from __future__ import absolute_import, print_function, division
import sys try:
if sys.version_info[:2] < (2, 7):
# The following implementation of OrderedDict compatible with python 2.4
# was taken from http://pypi.python.org/pypi/ordereddict/1.1
# It is under the MIT license.
# Copyright (c) 2009 Raymond Hettinger
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
from UserDict import DictMixin
class OrderedDict(dict, DictMixin):
def __init__(self, *args, **kwds):
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' %
len(args))
try:
self.__end
except AttributeError:
self.clear()
self.update(*args, **kwds)
def clear(self):
self.__end = end = []
end += [None, end, end] # sentinel node for doubly linked list
self.__map = {} # key --> [key, prev, next]
dict.clear(self)
def __setitem__(self, key, value):
if key not in self:
end = self.__end
curr = end[1]
curr[2] = end[1] = self.__map[key] = [key, curr, end]
dict.__setitem__(self, key, value)
def __delitem__(self, key):
dict.__delitem__(self, key)
key, prev, next = self.__map.pop(key)
prev[2] = next
next[1] = prev
def __iter__(self):
end = self.__end
curr = end[2]
while curr is not end:
yield curr[0]
curr = curr[2]
def __reversed__(self):
end = self.__end
curr = end[1]
while curr is not end:
yield curr[0]
curr = curr[1]
def popitem(self, last=True):
if not self:
raise KeyError('dictionary is empty')
if last:
key = next(reversed(self))
else:
key = next(iter(self))
value = self.pop(key)
return key, value
def __reduce__(self):
items = [[k, self[k]] for k in self]
tmp = self.__map, self.__end
del self.__map, self.__end
inst_dict = vars(self).copy()
self.__map, self.__end = tmp
if inst_dict:
return (self.__class__, (items,), inst_dict)
return self.__class__, (items,)
def keys(self):
return list(self)
setdefault = DictMixin.setdefault
update = DictMixin.update
pop = DictMixin.pop
values = DictMixin.values
items = DictMixin.items
iterkeys = DictMixin.iterkeys
itervalues = DictMixin.itervalues
iteritems = DictMixin.iteritems
def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, list(self.items()))
def copy(self):
return self.__class__(self)
@classmethod
def fromkeys(cls, iterable, value=None):
d = cls()
for key in iterable:
d[key] = value
return d
def __eq__(self, other):
if isinstance(other, OrderedDict):
if len(self) != len(other):
return False
for p, q in zip(self.items(), other.items()):
if p != q:
return False
return True
return dict.__eq__(self, other)
def __ne__(self, other):
return not self == other
# The following implementation of Counter compatible with python 2.4
# was taken from http://code.activestate.com/recipes/576611/
# It is under the MIT license.
# Copyright (c) 2009 Raymond Hettinger
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
from operator import itemgetter
from heapq import nlargest
from itertools import repeat
from theano.compat import ifilter
class Counter(dict):
'''Dict subclass for counting hashable objects.
Sometimes called a bag or multiset. Elements are stored as
dictionary keys and their counts are stored as dictionary
values.
>>> Counter('zyzygy')
Counter({'y': 3, 'z': 2, 'g': 1})
'''
def __init__(self, iterable=None, **kwds):
'''Create a new, empty Counter object.
And if given, count elements from an input iterable. Or,
initialize the count from another mapping of elements to
their counts.
A new, empty counter:
>>> c = Counter()
A new counter from an iterable
>>> c = Counter('gallahad')
A new counter from a mapping
>>> c = Counter({'a': 4, 'b': 2})
A new counter from keyword args
>>> c = Counter(a=4, b=2)
'''
self.update(iterable, **kwds)
def __missing__(self, key):
return 0
def most_common(self, n=None):
'''List the n most common elements and their counts.
The list goes from the most common to the least. If n is
None, then list all element counts.
>>> Counter('abracadabra').most_common(3)
[('a', 5), ('r', 2), ('b', 2)]
'''
if n is None:
return sorted(self.iteritems(), key=itemgetter(1),
reverse=True)
return nlargest(n, self.iteritems(), key=itemgetter(1))
def elements(self):
'''Iterator over elements.
It repeats each element as many times as its count.
>>> c = Counter('ABCABC')
>>> sorted(c.elements())
['A', 'A', 'B', 'B', 'C', 'C']
If an element's count has been set to zero or is a negative
number, elements() will ignore it.
'''
for elem, count in self.iteritems():
for _ in repeat(None, count):
yield elem
# Override dict methods where the meaning changes for Counter objects.
@classmethod
def fromkeys(cls, iterable, v=None):
raise NotImplementedError(
'Counter.fromkeys() is undefined. '
'Use Counter(iterable) instead.')
def update(self, iterable=None, **kwds):
'''Like dict.update() but add counts instead of replacing them.
Source can be an iterable, a dictionary, or another Counter
instance.
>>> c = Counter('which')
>>> c.update('witch') # add elements from another iterable
>>> d = Counter('watch')
>>> c.update(d) # add elements from another counter
>>> c['h'] # four 'h' in which, witch, and watch
4
'''
if iterable is not None:
if hasattr(iterable, 'iteritems'):
if self:
self_get = self.get
for elem, count in iterable.iteritems():
self[elem] = self_get(elem, 0) + count
else:
# fast path when counter is empty
dict.update(self, iterable)
else:
self_get = self.get
for elem in iterable:
self[elem] = self_get(elem, 0) + 1
if kwds:
self.update(kwds)
def copy(self):
'''Like dict.copy() but returns a Counter instance instead
of a dict.'''
return Counter(self)
def __delitem__(self, elem):
'''Like dict.__delitem__() but does not raise KeyError for
missing values.'''
if elem in self:
dict.__delitem__(self, elem)
def __repr__(self):
if not self:
return '%s()' % self.__class__.__name__
items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
return '%s({%s})' % (self.__class__.__name__, items)
# Multiset-style mathematical operations discussed in:
# Knuth TAOCP Volume II section 4.6.3 exercise 19
# and at http://en.wikipedia.org/wiki/Multiset
#
# Outputs guaranteed to only include positive counts.
#
# To strip negative and zero counts, add-in an empty counter:
# c += Counter()
def __add__(self, other):
'''Add counts from two counters.
>>> Counter('abbb') + Counter('bcc')
Counter({'b': 4, 'c': 2, 'a': 1})
'''
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
for elem in set(self) | set(other):
newcount = self[elem] + other[elem]
if newcount > 0:
result[elem] = newcount
return result
def __sub__(self, other):
''' Subtract count, but keep only results with positive counts.
>>> Counter('abbbc') - Counter('bccd')
Counter({'b': 2, 'a': 1})
'''
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
for elem in set(self) | set(other):
newcount = self[elem] - other[elem]
if newcount > 0:
result[elem] = newcount
return result
def __or__(self, other):
'''Union is the maximum of value in either of the input counters.
>>> Counter('abbb') | Counter('bcc')
Counter({'b': 3, 'c': 2, 'a': 1})
'''
if not isinstance(other, Counter):
return NotImplemented
_max = max
result = Counter()
for elem in set(self) | set(other):
newcount = _max(self[elem], other[elem])
if newcount > 0:
result[elem] = newcount
return result
def __and__(self, other):
''' Intersection is the minimum of corresponding counts.
>>> Counter('abbb') & Counter('bcc')
Counter({'b': 1})
'''
if not isinstance(other, Counter):
return NotImplemented
_min = min
result = Counter()
if len(self) < len(other):
self, other = other, self
for elem in ifilter(self.__contains__, other):
newcount = _min(self[elem], other[elem])
if newcount > 0:
result[elem] = newcount
return result
else:
try:
from UserDict import DictMixin from UserDict import DictMixin
except ImportError: except ImportError:
from collections import MutableMapping as DictMixin from collections import MutableMapping as DictMixin
from collections import OrderedDict, Counter from collections import OrderedDict, Counter
__all__ = ['DictMixin', 'OrderedDict', 'Counter'] __all__ = ['DictMixin', 'OrderedDict', 'Counter']
...@@ -1253,7 +1253,7 @@ def default_blas_ldflags(): ...@@ -1253,7 +1253,7 @@ def default_blas_ldflags():
"mk2_rt"]]) "mk2_rt"]])
# Anaconda # Anaconda
if "Anaconda" in sys.version and sys.platform == "win32": if "Anaconda" in sys.version or "Continuum" in sys.version:
# If the "mkl-service" conda package (available # If the "mkl-service" conda package (available
# through Python package "mkl") is installed and # through Python package "mkl") is installed and
# importable, then the libraries (installed by conda # importable, then the libraries (installed by conda
...@@ -1266,14 +1266,23 @@ def default_blas_ldflags(): ...@@ -1266,14 +1266,23 @@ def default_blas_ldflags():
_logger.info('Conda mkl is not available: %s', e) _logger.info('Conda mkl is not available: %s', e)
else: else:
# This branch is executed if no exception was raised # This branch is executed if no exception was raised
if sys.platform == "win32":
lib_path = os.path.join(sys.prefix, 'DLLs') lib_path = os.path.join(sys.prefix, 'DLLs')
flags = ['-L"%s"' % lib_path] flags = ['-L"%s"' % lib_path]
else:
lib_path = blas_info.get('library_dirs', [])[0]
flags = ['-L%s' % lib_path]
flags += ['-l%s' % l for l in ["mkl_core", flags += ['-l%s' % l for l in ["mkl_core",
"mkl_intel_thread", "mkl_intel_thread",
"mkl_rt"]] "mkl_rt"]]
res = try_blas_flag(flags) res = try_blas_flag(flags)
if res: if res:
return res return res
flags.extend(['-Wl,-rpath,' + l for l in
blas_info.get('library_dirs', [])])
res = try_blas_flag(flags)
if res:
return res
# to support path that includes spaces, we need to wrap it with double quotes on Windows # to support path that includes spaces, we need to wrap it with double quotes on Windows
path_wrapper = "\"" if os.name == 'nt' else "" path_wrapper = "\"" if os.name == 'nt' else ""
...@@ -1344,7 +1353,7 @@ def try_blas_flag(flags): ...@@ -1344,7 +1353,7 @@ def try_blas_flag(flags):
return 0; return 0;
} }
""") """)
cflags = flags cflags = list(flags)
# to support path that includes spaces, we need to wrap it with double quotes on Windows # to support path that includes spaces, we need to wrap it with double quotes on Windows
path_wrapper = "\"" if os.name == 'nt' else "" path_wrapper = "\"" if os.name == 'nt' else ""
cflags.extend(['-L%s%s%s' % (path_wrapper, d, path_wrapper) for d in theano.gof.cmodule.std_lib_dirs()]) cflags.extend(['-L%s%s%s' % (path_wrapper, d, path_wrapper) for d in theano.gof.cmodule.std_lib_dirs()])
......
...@@ -47,6 +47,9 @@ except ImportError: ...@@ -47,6 +47,9 @@ except ImportError:
# tests should not fail on optional dependency # tests should not fail on optional dependency
pydot_imported_msg = ("Install the python package pydot or pydot-ng." pydot_imported_msg = ("Install the python package pydot or pydot-ng."
" Install graphviz.") " Install graphviz.")
except Exception as e:
pydot_imported_msg = "An error happened while importing/trying pydot: "
pydot_imported_msg += str(e.args)
_logger = logging.getLogger("theano.printing") _logger = logging.getLogger("theano.printing")
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论