internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: pytorch/pytorch

Issue:
external nccl breaks gloo compilation
Currently, you can have a libnccl on your system, and pytorch setup favors that instead of compiling one itself from source. The code that takes care of this is:
https://github.com/pytorch/pytorch/blob/master/setup.py#L316-L318

However, this breaks gloo build because gloo gets a path to NCCL via: https://github.com/pytorch/pytorch/blob/master/torch/lib/build_libs.sh#L40




Discussion:
I got the error during the installation:
```
CMake Error: The source directory "/home/username/pytorch/torch/lib/gloo" does not appear to contain CMakeLists.txt.
```
Is it related to this problem?
@soumith, that's a dupe of #2375
@zhanghang1989, no, that's a consequence of #2574, now you have to do ```git submodule update --init``` before compiling. I think you don't want to do recursive submodule update, because that will pull in gtest and another copy of nccl. 
Alternatively we can pass new flags to gloo to prevent it from using its own NCCL
Thanks @ngimel! `git submodule update --init` works for me.
You can prevent it from using its own nccl, but its cmake still has to be able to find some nccl.

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -277,6 +277,13 @@ def run(self):
 cwd = os.path.dirname(os.path.abspath(__file__))
 lib_path = os.path.join(cwd, "torch", "lib")
 
+# Check if you remembered to check out submodules
+gloo_cmake = os.path.join(lib_path, "gloo", "CMakeLists.txt")
+if not os.path.exists(gloo_cmake):
+    print("Could not find {}".format(gloo_cmake))
+    print("Did you run 'git submodule update --init'?")
+    sys.exit(1)
+
 tmp_install_path = lib_path + "/tmp_install"
 include_dirs += [
     cwd,


Test patch:
Repository: pytorch/pytorch

Issue:
ONNX error converting torch.mean
I've been working to convert some models using sentence embeddings via ONNX and have run into the following error while running `torch.onnx._export`: 
`RuntimeError: PythonOp doesn't define symbolic Mean`

I also had this error when trying to implement my own "mean" operation using add and divide. 


Discussion:
ReduceMean is in https://github.com/onnx/onnx/blob/master/docs/Operators.md so this should be doable without Caffe2 adjustments (though maybe onnx-caffe2 will need to be clued in)
I will take a look at this. :-)

Resolving patch:
diff --git a/torch/autograd/_functions/reduce.py b/torch/autograd/_functions/reduce.py
--- a/torch/autograd/_functions/reduce.py
+++ b/torch/autograd/_functions/reduce.py
@@ -111,6 +111,15 @@ def reverse_dim(var, dim):
 
 class Mean(Function):
 
+    @staticmethod
+    def symbolic(g, input, dim=None, keepdim=None):
+        output = g.create("ReduceMean", [input])
+        if dim is not None:
+            output = output.is_("axes", dim)
+        if keepdim is None or keepdim is False:
+            output = output.i_("keepdims", 0)
+        return g.appendNode(output)
+
     @staticmethod
     def forward(ctx, input, dim=None, keepdim=None):
         ctx.dim = dim


Test patch:
Repository: pytorch/pytorch

Issue:
BatchNorm shouldn't use Bessel's correction for a batch size of 1
Right now it makes everything `NaN`.


Discussion:
To be clear, for a `N x C x H x W` tensor, the problem is only when all of N, H, and W are 1. (So BatchNorm2d on batch size of 1 is OK as long as you don't have a 1x1 image).

What's the desired behavior? The only reasonable behavior I can think of is:

- Raise an exception when the dimensions of which you are normalizing are one or
- Output zero (+ optional affine transform)

I'm not sure the outputing zero is a good idea. I can't think of a case where that's what you want.

Resolving patch:
diff --git a/torch/nn/functional.py b/torch/nn/functional.py
--- a/torch/nn/functional.py
+++ b/torch/nn/functional.py
@@ -3,6 +3,8 @@
 from numbers import Integral
 import warnings
 import math
+from operator import mul
+from functools import reduce
 
 import torch
 from torch._C import _infer_size
@@ -700,6 +702,9 @@ def embedding(input, embedding_matrix,
 
 def batch_norm(input, running_mean, running_var, weight=None, bias=None,
                training=False, momentum=0.1, eps=1e-5):
+    size = list(input.size())
+    if reduce(mul, size[2:], size[0]) == 1:
+        raise ValueError('Expected more than 1 value per channel, got input size {}'.format(size))
     f = torch._C._functions.BatchNorm(running_mean, running_var, training, momentum, eps, torch.backends.cudnn.enabled)
     return f(input, weight, bias)
 


Test patch:
Repository: pytorch/pytorch

Issue:
ReflectionPad2d breaks if reflection amount is too large
```python
import torch
from torch.autograd import Variable

x = Variable(torch.randn(1, 3, 2, 2), requires_grad=True)
l = torch.nn.ReflectionPad2d(5)(x).sum()
l.backward()
```
The last line segfaults.

Of course this isn't a usual situation, but it came up when trying to construct a Laplacian pyramid.


Discussion:
Working on this.

Resolving patch:
diff --git a/torch/nn/functional.py b/torch/nn/functional.py
--- a/torch/nn/functional.py
+++ b/torch/nn/functional.py
@@ -1133,7 +1133,7 @@ def pad(input, pad, mode='constant', value=0):
 
     Args:
         input (Variable): Nd tensor
-        pad (tuple): m-elem tuple, where m // 2 > input dimensions and m % 2 == 0
+        pad (tuple): m-elem tuple, where m // 2 <= input dimensions and m % 2 == 0
         mode: 'constant', 'reflect' or 'replicate'. Default: 'constant'
         value: fill value for 'constant' padding. Default: 0
 
@@ -1154,8 +1154,8 @@ def pad(input, pad, mode='constant', value=0):
         >>> print(out.data.size())
         torch.Size([3, 9, 7, 3])
     """
-    assert len(pad) % 2 == 0, 'padding length must be divisible by 2'
-    assert len(pad) // 2 <= len(input.size()), 'padding length too large'
+    assert len(pad) % 2 == 0, 'Padding length must be divisible by 2'
+    assert len(pad) // 2 <= input.dim(), 'Padding length too large'
     if mode == 'constant':
         return ConstantPadNd.apply(input, pad, value)
     elif input.dim() == 3:


Test patch:
Repository: pytorch/pytorch

Issue:
Sparse SGD + momentum  = cuda memory issue.
When using classic SGD optimizer with momentum with sparse embeddings the memory keeps garbage collecting / allocating leading to slow down and out of memory error eventually. [Here is a minimal exemple to reproduce the issue](https://gist.github.com/cedias/946a380807b7e1bf92d738268b71415a)

![slowing](https://user-images.githubusercontent.com/1705336/31611730-87b2ccbc-b27d-11e7-8826-12023e848a77.png)

![memoryerror](https://user-images.githubusercontent.com/1705336/31612140-0fea1080-b27f-11e7-99b7-8dae06d931b1.gif)

The issue dissapears when momentum is not used
![nomomentum](https://user-images.githubusercontent.com/1705336/31611728-86c7a9f8-b27d-11e7-85b3-979ce180ec3d.png)

or when embeddings are not sparse
![notsparse](https://user-images.githubusercontent.com/1705336/31611729-872bb416-b27d-11e7-8ca1-65629cfae6bc.png)


I'm using the last pytorch version on conda: `'0.2.0_4'`



Discussion:

Resolving patch:
diff --git a/torch/optim/sgd.py b/torch/optim/sgd.py
--- a/torch/optim/sgd.py
+++ b/torch/optim/sgd.py
@@ -86,7 +86,8 @@ def step(self, closure=None):
                 if momentum != 0:
                     param_state = self.state[p]
                     if 'momentum_buffer' not in param_state:
-                        buf = param_state['momentum_buffer'] = d_p.clone()
+                        buf = param_state['momentum_buffer'] = p.data.new().resize_as_(p.data).zero_()
+                        buf.mul_(momentum).add_(d_p)
                     else:
                         buf = param_state['momentum_buffer']
                         buf.mul_(momentum).add_(1 - dampening, d_p)


Test patch:
Repository: pytorch/pytorch

Issue:
Custom CUDNN_LIB_DIR not added to rpath
Compiling pytorch master version 0.2.0+0989889 with a custom CUDNN_LIB_DIR and CUDNN_INCLUDE_DIR location, with cuda 8.0 and cudnn 7, it seems the compiled binaries do not include the path to CUDNN_LIB_DIR in their rpath, causing an error on import

> ldd _C.so|grep libcudnn
> 	libcudnn.so.7 => not found

> patchelf --print-rpath _C.so 
> [..]/miniconda2/envs/neural4/lib:/usr/local/cuda-8.0/lib64:$ORIGIN/lib

Might be an addition worth adding to the build system?


Discussion:
Yes, please send a PR!

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -499,9 +499,10 @@ def check_file(f):
     ]
 if WITH_CUDNN:
     main_libraries += ['cudnn']
-    # NOTE: this this at the front, in case there's another cuDNN in CUDA path
-    include_dirs.insert(0, CUDNN_INCLUDE_DIR)
     library_dirs.append(CUDNN_LIB_DIR)
+    # NOTE: these are at the front, in case there's another cuDNN in CUDA path
+    include_dirs.insert(0, CUDNN_INCLUDE_DIR)
+    extra_link_args.insert(0, '-Wl,-rpath,' + CUDNN_LIB_DIR)
     main_sources += [
         "torch/csrc/cudnn/BatchNorm.cpp",
         "torch/csrc/cudnn/Conv.cpp",


Test patch:
Repository: pytorch/pytorch

Issue:
PyTorch throws an exception on import when denormals are flushed to zero
This happens, for example, when you import DyNet before importing PyTorch. The code from #3113 tries to take the log(0) which throws an exception.

My guess is that DyNet is setting FTZ or DAZ (or both). See:
https://software.intel.com/en-us/node/523328


Discussion:
cc @SsnL 
I plan to look into this after dealing with the sparse stuff. How urgent is this?
Since it seems easy to work around, it doesn't sound super urgent to me. (But it would be good to fix... as with all of the bugs :)
We need to fix this before the next release, but it can definitely wait until after the sparse stuff

There's an easy fix: just replace the computation in `__MIN_LOG_SCALE` with `-323`. The minimum denormalized number for IEEE float64s is unlikely to change.

Resolving patch:
diff --git a/torch/_tensor_str.py b/torch/_tensor_str.py
--- a/torch/_tensor_str.py
+++ b/torch/_tensor_str.py
@@ -5,9 +5,6 @@
 from sys import float_info
 
 
-__MIN_LOG_SCALE = math.ceil(math.log(float_info.min * float_info.epsilon, 10))
-
-
 class __PrinterOptions(object):
     precision = 4
     threshold = 1000
@@ -69,7 +66,15 @@ def set_printoptions(
         PRINT_OPTS.linewidth = linewidth
 
 
+def _get_min_log_scale():
+    min_positive = float_info.min * float_info.epsilon  # get smallest denormal
+    if min_positive == 0:  # use smallest normal if DAZ/FTZ is set
+        min_positive = float_info.min
+    return math.ceil(math.log(min_positive, 10))
+
+
 def _number_format(tensor, min_sz=-1):
+    _min_log_scale = _get_min_log_scale()
     min_sz = max(min_sz, 2)
     tensor = torch.DoubleTensor(tensor.size()).copy_(tensor).abs_().view(tensor.nelement())
 
@@ -123,7 +128,7 @@ def _number_format(tensor, min_sz=-1):
         else:
             if exp_max > prec + 1 or exp_max < 0:
                 sz = max(min_sz, 7)
-                scale = math.pow(10, max(exp_max - 1, __MIN_LOG_SCALE))
+                scale = math.pow(10, max(exp_max - 1, _min_log_scale))
             else:
                 if exp_max == 0:
                     sz = 7


Test patch:
Repository: pytorch/pytorch

Issue:
reinforce: throw exception (immediately) that points users at what they should use



Discussion:

Resolving patch:
diff --git a/torch/autograd/variable.py b/torch/autograd/variable.py
--- a/torch/autograd/variable.py
+++ b/torch/autograd/variable.py
@@ -206,20 +206,30 @@ def register_hook(self, hook):
         return handle
 
     def reinforce(self, reward):
-        """Registers a reward obtained as a result of a stochastic process.
-
-        Differentiating stochastic nodes requires providing them with reward
-        value. If your graph contains any stochastic operations, you should
-        call this function on their outputs. Otherwise an error will be raised.
-
-        Parameters:
-            reward(Tensor): Tensor with per-element rewards. It has to match
-                the device location and shape of Variable's data.
-        """
-        if not isinstance(self.grad_fn, StochasticFunction):
-            raise RuntimeError("reinforce() can be only called on outputs "
-                               "of stochastic functions")
-        self.grad_fn._reinforce(reward)
+        def trim(str):
+            return '\n'.join([line.strip() for line in str.split('\n')])
+
+        raise RuntimeError(trim(r"""reinforce() was removed.
+            Use torch.distributions instead.
+            See http://pytorch.org/docs/master/distributions.html
+
+            Instead of:
+
+            probs = policy_network(state)
+            action = probs.multinomial()
+            next_state, reward = env.step(action)
+            action.reinforce(reward)
+            action.backward()
+
+            Use:
+
+            probs = policy_network(state)
+            m = torch.distributions.Multinomial(probs)
+            action = m.sample()
+            next_state, reward = env.step(action)
+            loss = -m.log_prob(action) * reward
+            loss.backward()
+        """))
 
     detach = _add_docstr(_C._VariableBase.detach, r"""
     Returns a new Variable, detached from the current graph.


Test patch:
Repository: pytorch/pytorch

Issue:
Fix far-fetched Boolean ambiguity for byte tensor with one value in it.
Testing non-empty tensor in an if statement will unconditionally raise a RuntimeError stating that "bool value of non-empty torch.ByteTensor objects is ambiguous". But when there's only one value, it's bool value is pretty straightforward.
What do you think?


Discussion:
Yes, that makes sense. I thought we support this, but apparently we don't. NumPy does so it's better to do it as well for consistency
Ok, will do a pull request in a few hours.

Resolving patch:
diff --git a/torch/autograd/variable.py b/torch/autograd/variable.py
--- a/torch/autograd/variable.py
+++ b/torch/autograd/variable.py
@@ -120,10 +120,11 @@ def __repr__(self):
         return 'Variable containing:' + self.data.__repr__()
 
     def __bool__(self):
-        if self.data.numel() == 0:
-            return False
-        raise RuntimeError("bool value of Variable objects containing non-empty " +
-                           torch.typename(self.data) + " is ambiguous")
+        if self.data.numel() <= 1:
+            return self.data.__bool__()
+        raise RuntimeError("bool value of Variable containing " +
+                           torch.typename(self.data) +
+                           " with more than one value is ambiguous")
 
     __nonzero__ = __bool__
 
diff --git a/torch/tensor.py b/torch/tensor.py
--- a/torch/tensor.py
+++ b/torch/tensor.py
@@ -148,8 +148,10 @@ def __str__(self):
     def __bool__(self):
         if self.numel() == 0:
             return False
-        raise RuntimeError("bool value of non-empty " + torch.typename(self) +
-                           " objects is ambiguous")
+        elif self.numel() == 1:
+            return torch.squeeze(self)[0] != 0
+        raise RuntimeError("bool value of " + torch.typename(self) +
+                           " containing more than one value is ambiguous")
 
     __nonzero__ = __bool__
 


Test patch:
Repository: pytorch/pytorch

Issue:
cosine_similarity should not call squeeze() twice
`torch.nn.functional.cosine_similarity` calls `squeeze()` twice: once implicitly in `sum()` and once explicitly before the tensor is returned. 

https://github.com/pytorch/pytorch/blob/master/torch/nn/functional.py#L1653

The second (explicit) call in line 1653 leads to problems if other dimensions than the one over which the cosine similarity is calculated have size 1, e.g. with batch size 1.

This is probably a remnant from before the behavior of sum() was changed to squeeze by default (https://github.com/pytorch/pytorch/issues/289 and https://github.com/pytorch/pytorch/pull/1563), although even then it probably should have been `squeeze(dim)` in order to only squeeze the cosine dimension.


Discussion:
That makes sense, thanks for pointing it out. I'll send a pr for it soon.

Resolving patch:
diff --git a/torch/nn/functional.py b/torch/nn/functional.py
--- a/torch/nn/functional.py
+++ b/torch/nn/functional.py
@@ -1650,7 +1650,7 @@ def cosine_similarity(x1, x2, dim=1, eps=1e-8):
     w12 = torch.sum(x1 * x2, dim)
     w1 = torch.norm(x1, 2, dim)
     w2 = torch.norm(x2, 2, dim)
-    return (w12 / (w1 * w2).clamp(min=eps)).squeeze()
+    return w12 / (w1 * w2).clamp(min=eps)
 
 
 def triplet_margin_loss(anchor, positive, negative, margin=1.0, p=2, eps=1e-6, swap=False):


Test patch:
diff --git a/test/test_nn.py b/test/test_nn.py
--- a/test/test_nn.py
+++ b/test/test_nn.py
@@ -2895,6 +2895,13 @@ def test_cosine_similarity(self):
         self.assertTrue(gradcheck(lambda x, y: F.cosine_similarity(x, y, dim=0), (input1, input2)))
         self.assertTrue(gradcheck(lambda x, y: F.cosine_similarity(x, y, dim=-1), (input1, input2)))
 
+        # Check cosine_similarity input/output shapes
+        input_size = (1, 3, 2, 1)
+        expected_size = (1, 2, 1)
+        input1 = Variable(torch.randn(input_size), requires_grad=True)
+        input2 = Variable(torch.randn(input_size), requires_grad=True)
+        self.assertEqual(F.cosine_similarity(input1, input2, dim=1).size(), expected_size)
+
     def test_grid_sample(self):
         def test_cpu_against_cuda(N, C, H, W, padding_mode):
             def test_shape(N, C, IH, IW, H, W, padding_mode):
Repository: pytorch/pytorch

Issue:
MultiLabelMarginLoss document incorrect
In PyTorch, since class labels are zero-indexed, actually only non “-1” target values are considered, instead of "The criterion only considers the first non zero `y[j]` targets."

https://github.com/pytorch/pytorch/blob/4bce69be221a090c7f679caa7f6c6c5ee4d4a054/torch/nn/modules/loss.py#L457


Discussion:

Resolving patch:
diff --git a/torch/nn/modules/loss.py b/torch/nn/modules/loss.py
--- a/torch/nn/modules/loss.py
+++ b/torch/nn/modules/loss.py
@@ -467,7 +467,7 @@ class MultiLabelMarginLoss(_Loss):
 
     `y` and `x` must have the same size.
 
-    The criterion only considers the first non zero `y[j]` targets.
+    The criterion only considers the first non-negative `y[j]` targets.
 
     This allows for different samples to have variable amounts of target classes
     """


Test patch:
Repository: pytorch/pytorch

Issue:
Sequential and ModuleList call add_module() with integer keys
Hello,

In the case where these classes sequentially append the received elements with `add_module(str(idx), value)`, the modules become inaccessible since a variable name starting with a number is forbidden in Python.

I attached a patch that names the modules as `module_%d` instead of just numbers.

```python
In [17]: foo = nn.Sequential(*[nn.Linear(10, 100), nn.Linear(100, 5)])

In [18]: hasattr(foo, '0')
Out[18]: True

In [19]: foo.0
  File "<ipython-input-19-a18cb4ba7f54>", line 1
    foo.0
        ^
SyntaxError: invalid syntax
```


Discussion:
Use `foo[0]` syntax for Sequential and ModueList.
possible but the attributes are there and they are obviously shown in autocompletion suggestions in IPython for example and when you try to access them you got an error because their naming does not conform to Python rules.
Perhaps we should exclude them from `Module.__dir__`

Resolving patch:
diff --git a/torch/nn/modules/module.py b/torch/nn/modules/module.py
--- a/torch/nn/modules/module.py
+++ b/torch/nn/modules/module.py
@@ -677,4 +677,8 @@ def __dir__(self):
         modules = list(self._modules.keys())
         buffers = list(self._buffers.keys())
         keys = module_attrs + attrs + parameters + modules + buffers
+
+        # Eliminate attrs that are not legal Python variable names
+        keys = [key for key in keys if not key[0].isdigit()]
+
         return sorted(keys)


Test patch:
Repository: pytorch/pytorch

Issue:
torch.svd docs: `some` parameter?
The documentation of the `some` parameter to `torch.svd` is one of the strangest I've seen... what does `some=True` (the default) do???

> 
> torch.svd(input, some=True, out=None) -> (Tensor, Tensor, Tensor)
> ...
> some represents the number of singular values to be computed. If some=True, it computes some and some=False computes all.
> 


Discussion:
Ha it is somewhat weird indeed. When `some=False`, the returned U and V matrices are square orthonormal matrices. I will send out a PR to clarify this.

Resolving patch:
diff --git a/torch/_torch_docs.py b/torch/_torch_docs.py
--- a/torch/_torch_docs.py
+++ b/torch/_torch_docs.py
@@ -4295,16 +4295,15 @@
 `U, S, V = torch.svd(A)` returns the singular value decomposition of a
 real matrix `A` of size `(n x m)` such that :math:`A = USV^T`.
 
-`U` is of shape :math:`(n \times \min(n, m))`.
+`U` is of shape :math:`(n \times n)`.
 
-`S` is a diagonal matrix of shape :math:`(\min(n, m) \times \min(n, m))`,
-represented as a vector of size :math:`\min(n, m)` containing the diagonal
-entries.
+`S` is a diagonal matrix of shape :math:`(n \times m)`, represented as a vector
+of size :math:`\min(n, m)` containing the diagonal entries.
 
-`V` is of shape :math:`(m \times \min(n, m))`.
+`V` is of shape :math:`(m \times m)`.
 
-:attr:`some` represents the number of singular values to be computed.
-If `some=True`, it computes some and `some=False` computes all.
+If :attr:`some` is ``True`` (default), the returned `U` and `V` matrices will
+contain only :math:`min(n, m)` orthonormal columns.
 
 .. note:: Irrespective of the original strides, the returned matrix `U`
           will be transposed, i.e. with strides `(1, n)` instead of `(n, 1)`.
@@ -4321,7 +4320,7 @@
 
 Args:
     input (Tensor): the input 2-D tensor
-    some (bool, optional): controls the number of singular values to be computed
+    some (bool, optional): controls the shape of returned `U` and `V`
     out (tuple, optional): the output tuple of tensors
 
 Example::


Test patch:
Repository: pytorch/pytorch

Issue:
Profiler for Python 2.7
Running `prof = torch.autograd.profiler.load_nvprof('trace_name.prof')` on Python 2.7 causes an error:
`NameError: global name 'FileNotFoundError' is not defined` and according to [here](https://github.com/philkr/lpo/issues/5#issuecomment-100596671), FileNotFoundError apparently doesn't exist in python 2.7.
A simple solution that worked for me is to add to the beginning of torch/autograd/profiler.py file the following lines:

```
try:
    FileNotFoundError
except NameError:
    #py2
    FileNotFoundError = IOError
```

Which I got from [here](https://stackoverflow.com/a/21368622/850760).

PS:
I can create a PR if you agree with the solution.

Cheers,


Discussion:
Thanks for the report. Could you post the stacktrace of the error by any chance? It doesn't look like we have any occurrences of FileNotFoundError in our code, so it may be an upstream problem.
Sure. This is my full traceback:

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/**whatever**/anaconda2/lib/python2.7/site-packages/torch/autograd/profiler.py", line 232, in load_nvprof
    return EventList(parse_nvprof_trace(path))
  File "/home/**whatever**/anaconda2/lib/python2.7/site-packages/torch/autograd/profiler.py", line 392, in parse_nvprof_trace
    strings[r["id"]] = demangle(r["value"])
  File "/home/**whatever**/anaconda2/lib/python2.7/site-packages/torch/autograd/profiler.py", line 323, in demangle
    except (subprocess.CalledProcessError, OSError, FileNotFoundError) as e:
NameError: global name 'FileNotFoundError' is not defined

```

and the program is simply:

```
import torch
prof = torch.autograd.profiler.load_nvprof('trace_name.prof')
```
Yeah it seems that `FileNotFoundError` is defined only in Python 3.3+. Can you please send a PR with the snippet you proposed as a fix? Thanks!

Resolving patch:
diff --git a/torch/autograd/profiler.py b/torch/autograd/profiler.py
--- a/torch/autograd/profiler.py
+++ b/torch/autograd/profiler.py
@@ -7,6 +7,12 @@
 import itertools
 from collections import defaultdict, namedtuple
 
+try:
+    FileNotFoundError
+except NameError:
+    # py2.7
+    FileNotFoundError = IOError
+
 
 class range(object):
     def __init__(self, name):


Test patch: