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

Issue:
Remove alias of links under chainer.functions namespace
We left these alias only for backward compatibility.


Discussion:

Resolving patch:
diff --git a/chainer/functions/__init__.py b/chainer/functions/__init__.py
--- a/chainer/functions/__init__.py
+++ b/chainer/functions/__init__.py
@@ -362,19 +362,3 @@
 
 from chainer.functions.util.forget import forget  # NOQA
 from chainer.functions.util.forget import Forget  # NOQA
-
-# Import for backward compatibility
-from chainer.links.activation.prelu import PReLU  # NOQA
-
-from chainer.links.connection.bilinear import Bilinear  # NOQA
-from chainer.links.connection.convolution_2d import Convolution2D  # NOQA
-from chainer.links.connection.dilated_convolution_2d import DilatedConvolution2D  # NOQA
-from chainer.links.connection.embed_id import EmbedID  # NOQA
-from chainer.links.connection.inception import Inception  # NOQA
-from chainer.links.connection.inceptionbn import InceptionBN  # NOQA
-from chainer.links.connection.linear import Linear  # NOQA
-
-from chainer.links.loss.hierarchical_softmax import BinaryHierarchicalSoftmax  # NOQA
-from chainer.links.loss.negative_sampling import NegativeSampling  # NOQA
-
-from chainer.links.normalization.batch_normalization import BatchNormalization  # NOQA
diff --git a/chainer/functions/activation/lstm.py b/chainer/functions/activation/lstm.py
--- a/chainer/functions/activation/lstm.py
+++ b/chainer/functions/activation/lstm.py
@@ -215,8 +215,8 @@ def lstm(c_prev, x):
         >>> y = chainer.Variable(np.zeros((1, n_units), 'f'))
         >>> h = chainer.Variable(np.zeros((1, n_units), 'f'))
         >>> c = chainer.Variable(np.zeros((1, n_units), 'f'))
-        >>> model = chainer.Chain(w=F.Linear(n_units, 4 * n_units),
-        ...                       v=F.Linear(n_units, 4 * n_units),)
+        >>> model = chainer.Chain(w=L.Linear(n_units, 4 * n_units),
+        ...                       v=L.Linear(n_units, 4 * n_units),)
         >>> x = model.w(y) + model.v(h)
         >>> c, h = F.lstm(c, x)
 
diff --git a/examples/word2vec/train_word2vec.py b/examples/word2vec/train_word2vec.py
--- a/examples/word2vec/train_word2vec.py
+++ b/examples/word2vec/train_word2vec.py
@@ -66,7 +66,7 @@ class ContinuousBoW(chainer.Chain):
 
     def __init__(self, n_vocab, n_units, loss_func):
         super(ContinuousBoW, self).__init__(
-            embed=F.EmbedID(
+            embed=L.EmbedID(
                 n_vocab, n_units, initialW=I.Uniform(1. / n_units)),
             loss_func=loss_func,
         )


Test patch:
Repository: chainer/chainer

Issue:
cuda.Device should not be created in Variable.backward when cupy is not used
From chainer==1.21.0, `cuda.Device()` is created always in `Variable.backward` whenever `cuda.available`, even when `Variable.data` is `numpy.ndarray`.

https://github.com/pfnet/chainer/blob/d91ba89da9bbef0b316006648b162d9f4bffbce9/chainer/variable.py#L357

Not only being unnecessary, it can result in an error when `Variable.backward` is called by another process.

The code below runs without problem with chainer==1.20.0.1, but raises `cupy.cuda.runtime.CUDARuntimeError: cudaErrorInitializationError: initialization error` at `cuda.Device()` with chainer==1.21.0.
```
import multiprocessing as mp
import chainer
print(chainer.__version__)
import numpy as np
chainer.cuda.get_device(0).use()

def hoge():
    # Note that this function uses numpy, not cupy, but still it results in an error
    x = chainer.Variable(np.asarray([0], dtype=np.float32)) + 1
    x.backward()

p = mp.Process(target=hoge)
p.start()
p.join()
```


Discussion:

Resolving patch:
diff --git a/chainer/variable.py b/chainer/variable.py
--- a/chainer/variable.py
+++ b/chainer/variable.py
@@ -352,7 +352,7 @@ def backward(self, retain_grad=False):
         if self.creator is None:
             return
         initial_device = None
-        if cuda.available:
+        if cuda.available and isinstance(self.data, cuda.cupy.ndarray):
             try:
                 initial_device = cuda.Device()
             except cuda.cupy.cuda.runtime.CUDARuntimeError as e:


Test patch:
Repository: chainer/chainer

Issue:
Abort installation to Python 3.5.0
I noticed that it is advisable to abort installation to Python 3.5.0 instead of to raise an exception https://github.com/pfnet/chainer/pull/1656.

Ref: https://github.com/pfnet/chainer/issues/1111



Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1,10 +1,24 @@
 #!/usr/bin/env python
 
+import os
 from setuptools import setup
+import sys
 
 import chainer_setup_build
 
 
+if sys.version_info[:3] == (3, 5, 0):
+    if not int(os.getenv('CHAINER_PYTHON_350_FORCE', '0')):
+        msg = """
+Chainer does not work with Python 3.5.0.
+
+We strongly recommend to use another version of Python.
+If you want to use Chainer with Python 3.5.0 at your own risk,
+set 1 to CHAINER_PYTHON_350_FORCE environment variable."""
+        print(msg)
+        sys.exit(1)
+
+
 setup_requires = []
 install_requires = [
     'filelock',


Test patch:
Repository: chainer/chainer

Issue:
Check indices_or_sections is sorted in debug mode
`split_axis` requires `indices_or_sections` be sorted when it is 1D-array. But we do not check it left for users. As the check is costly, we should check it in debug mode.



Discussion:

Resolving patch:
diff --git a/chainer/functions/array/split_axis.py b/chainer/functions/array/split_axis.py
--- a/chainer/functions/array/split_axis.py
+++ b/chainer/functions/array/split_axis.py
@@ -17,6 +17,12 @@ def __init__(self, indices_or_sections, axis):
                 indices_or_sections,
                 six.integer_types + (collections.Iterable,)):
             raise TypeError('indices_or_sections must be integer or 1-D array')
+        if (chainer.is_debug() and
+                isinstance(indices_or_sections, collections.Iterable)):
+            for p, n in six.moves.zip(
+                    indices_or_sections, indices_or_sections[1:]):
+                if p > n:
+                    raise ValueError('indices_or_sections must be sorted')
         self.indices_or_sections = indices_or_sections
         self.axis = axis
 


Test patch:
diff --git a/tests/chainer_tests/functions_tests/array_tests/test_split_axis.py b/tests/chainer_tests/functions_tests/array_tests/test_split_axis.py
--- a/tests/chainer_tests/functions_tests/array_tests/test_split_axis.py
+++ b/tests/chainer_tests/functions_tests/array_tests/test_split_axis.py
@@ -142,4 +142,19 @@ def test_forward_single_gpu(self):
         self.check_forward_single(cuda.to_gpu(self.x), axis=self.axis)
 
 
+class TestSplitAxisInvalidSections(unittest.TestCase):
+
+    def setUp(self):
+        self.default_debug = chainer.is_debug()
+        chainer.set_debug(True)
+
+    def tearDown(self):
+        chainer.set_debug(self.default_debug)
+
+    def test_invalid_sections(self):
+        x = numpy.zeros((2, 3, 4), dtype='f')
+        with self.assertRaises(ValueError):
+            functions.split_axis(x, [2, 1], 1)
+
+
 testing.run_module(__name__, __file__)
Repository: chainer/chainer

Issue:
Check maximum supported version of cuDNN
API compatibility of cuDNN is always broken. We need to check maximum supported version of cuDNN.


Discussion:

Resolving patch:
diff --git a/install/build.py b/install/build.py
--- a/install/build.py
+++ b/install/build.py
@@ -9,6 +9,7 @@
 
 minimum_cuda_version = 6050
 minimum_cudnn_version = 2000
+maximum_cudnn_version = 6999
 # Although cuda 7.0 includes cusolver,
 # we tentatively support cusolver in cuda 8.0 only because
 # provided functions are insufficient to implement cupy.linalg
@@ -112,10 +113,12 @@ def check_cudnn_version(compiler, settings):
 
     cudnn_version = int(out)
 
-    if cudnn_version < minimum_cudnn_version:
+    if not minimum_cudnn_version <= cudnn_version <= maximum_cudnn_version:
+        min_major = minimum_cudnn_version // 1000
+        max_major = maximum_cudnn_version // 1000
         utils.print_warning(
-            'cuDNN version is too old: %d' % cudnn_version,
-            'cuDNN v2 or newer is required')
+            'Unsupported cuDNN version: %d' % cudnn_version,
+            'cuDNN v%d<= and <=v%d is required' % (min_major, max_major))
         return False
 
     return True


Test patch:
Repository: chainer/chainer

Issue:
Show special members in the document
`__call__` is not documented now. We need to use `:special-members:`.
http://www.sphinx-doc.org/en/stable/ext/autodoc.html


Discussion:

Resolving patch:
diff --git a/docs/source/conf.py b/docs/source/conf.py
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -124,6 +124,7 @@
 
 # Napoleon settings
 napoleon_use_ivar = True
+napoleon_include_special_with_doc = True
 
 # -- Options for HTML output ----------------------------------------------
 


Test patch:
Repository: chainer/chainer

Issue:
Variable.transpose() without argument causes error
`F.transpose` and `Variable.transpose` work interchangeably when the `axes` argument is given.
However, without `axes` argument, `Variable.transpose` cannot work.
The following code reproduces the error on python 3.6.1 and chainer 1.23.0.

```python
import numpy as np
import chainer
import chainer.functions as F

x = chainer.Variable(np.ones((2, 4), np.float32))
assert F.transpose(x).data.shape == (4, 2)
x.transpose() # ValueError: axes don't match array
```

Though `x.transpose()` should produce the Variable of transposed array, it causes error.


Discussion:
I found the error occurs when the array is `numpy.ndarray`.
If the array is `cupy.ndarray`, it works as expected.

```python
import cupy
import chainer
import chainer.functions as F

x = chainer.Variable(cupy.ones((2, 4), np.float32))
assert F.transpose(x).data.shape == (4, 2)
assert x.transpose().data.shape == (4, 2)  # pass
```

Resolving patch:
diff --git a/chainer/variable.py b/chainer/variable.py
--- a/chainer/variable.py
+++ b/chainer/variable.py
@@ -469,8 +469,10 @@ def transpose(self, *axes):
            :func:`chainer.functions.transpose` for full documentation.
 
         """
-        if len(axes) == 1 and (isinstance(axes[0], (tuple, list)) or
-                               axes[0] is None):
+        if len(axes) == 0:
+            axes = None
+        elif len(axes) == 1 and (isinstance(axes[0], (tuple, list)) or
+                                 axes[0] is None):
             axes = axes[0]
         return chainer.functions.transpose(self, axes)
 


Test patch:
diff --git a/tests/chainer_tests/test_variable.py b/tests/chainer_tests/test_variable.py
--- a/tests/chainer_tests/test_variable.py
+++ b/tests/chainer_tests/test_variable.py
@@ -802,7 +802,7 @@ def test_backward_gpu(self):
 
 @testing.parameterize(*testing.product({
     'in_shape': [(4, 3, 2)],
-    'axes': [(-1, 0, 1), None, [-1, 0, 1]],
+    'axes': [[], [(-1, 0, 1)], [[-1, 0, 1]], [None], [-1, 0, 1]],
     'dtype': [np.float16, np.float32, np.float32],
 }))
 class TestTranspose(unittest.TestCase):
@@ -813,9 +813,9 @@ def setUp(self):
     def check_forward(self, x_data):
         axes = self.axes
         x = chainer.Variable(x_data)
-        y = x.transpose(axes)
+        y = x.transpose(*axes)
         self.assertEqual(y.data.dtype, self.dtype)
-        self.assertTrue((self.x.transpose(axes) == cuda.to_cpu(y.data)).all())
+        self.assertTrue((self.x.transpose(*axes) == cuda.to_cpu(y.data)).all())
 
     def test_forward_cpu(self):
         self.check_forward(self.x)
@@ -826,7 +826,7 @@ def test_forward_gpu(self):
 
     def check_backward(self, x_data):
         x = chainer.Variable(x_data)
-        y = x.transpose(self.axes)
+        y = x.transpose(*self.axes)
         y.grad = y.data
         y.backward()
         testing.assert_allclose(x.data, x.grad, atol=0, rtol=0)
Repository: chainer/chainer

Issue:
Doc test fails at optimizer.py
This issue is caused by, but not directly related to https://github.com/chainer/chainer/pull/2758.

```
:
reading sources... [ 77%] reference/generated/chainer.optimizers.AdaDelta                                                                                                                                          
Exception occurred:
  File "/repos/chainer/chainer/optimizer.py", line 598, in __get__
    return getattr(obj.hyperparam, self._attr_name)
AttributeError: 'NoneType' object has no attribute 'hyperparam'
The full traceback has been saved in /tmp/sphinx-err-kbktwjzz.log, if you want to report the issue to the developers.
```

And the traceback in the log file:
```
Traceback (most recent call last):
  File "/home/niboshi/anaconda/anaconda3/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg/sphinx/cmdline.py", line 296, in main
    app.build(opts.force_all, filenames)
  File "/home/niboshi/anaconda/anaconda3/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg/sphinx/application.py", line 333, in build
    self.builder.build_update()
  File "/home/niboshi/anaconda/anaconda3/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg/sphinx/builders/__init__.py", line 251, in build_update
    'out of date' % len(to_build))
  File "/home/niboshi/anaconda/anaconda3/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg/sphinx/builders/__init__.py", line 265, in build
    self.doctreedir, self.app))
  File "/home/niboshi/anaconda/anaconda3/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg/sphinx/environment/__init__.py", line 556, in update
    self._read_serial(docnames, app)
  File "/home/niboshi/anaconda/anaconda3/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg/sphinx/environment/__init__.py", line 576, in _read_serial
    self.read_doc(docname, app)
  File "/home/niboshi/anaconda/anaconda3/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg/sphinx/environment/__init__.py", line 700, in read_doc
    app.emit('doctree-read', doctree)
  File "/home/niboshi/anaconda/anaconda3/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg/sphinx/application.py", line 589, in emit
    results.append(callback(self, *args))
  File "/home/niboshi/anaconda/anaconda3/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg/sphinx/ext/linkcode.py", line 57, in doctree_read
    uri = resolve_target(domain, info)
  File "conf.py", line 367, in linkcode_resolve
  File "conf.py", line 351, in _import_object_from_name
  File "/repos/chainer/chainer/optimizer.py", line 598, in __get__
    return getattr(obj.hyperparam, self._attr_name)
AttributeError: 'NoneType' object has no attribute 'hyperparam'
```


Discussion:

Resolving patch:
diff --git a/chainer/optimizer.py b/chainer/optimizer.py
--- a/chainer/optimizer.py
+++ b/chainer/optimizer.py
@@ -595,6 +595,8 @@ def __init__(self, attr_name):
         self.__doc__ = 'Alias to ``self.hyperparam.{}``'.format(attr_name)
 
     def __get__(self, obj, type=None):
+        if obj is None:
+            return self
         return getattr(obj.hyperparam, self._attr_name)
 
     def __set__(self, obj, value):


Test patch:
Repository: chainer/chainer

Issue:
Types of BatchNormalization link are described inaccurately
Although `avg_mean` and `avg_var` are `ndarray`, the docstring says that they are `Variable`.

https://github.com/chainer/chainer/blob/6a526e53aee773b65dca7f0383890fa0ad9a9fac/chainer/links/normalization/batch_normalization.py#L56-L57


Discussion:
~~`avg_mean` and `avg_var` are initialized as `numpy.ndarray`[1] but
`running_avg` and `running_var`[2] could be `cupy.ndarray`.
It it safe?~~

~~[1] https://github.com/chainer/chainer/blob/6a526e53aee773b65dca7f0383890fa0ad9a9fac/chainer/links/normalization/batch_normalization.py#L69
[2] https://github.com/chainer/chainer/blob/6a526e53aee773b65dca7f0383890fa0ad9a9fac/chainer/links/normalization/batch_normalization.py#L145~~

I found this is irrelevant.

Resolving patch:
diff --git a/chainer/links/normalization/batch_normalization.py b/chainer/links/normalization/batch_normalization.py
--- a/chainer/links/normalization/batch_normalization.py
+++ b/chainer/links/normalization/batch_normalization.py
@@ -53,8 +53,8 @@ class BatchNormalization(link.Link):
     Attributes:
         gamma (~chainer.Variable): Scaling parameter.
         beta (~chainer.Variable): Shifting parameter.
-        avg_mean (~chainer.Variable): Population mean.
-        avg_var (~chainer.Variable): Population variance.
+        avg_mean (numpy.ndarray or cupy.ndarray): Population mean.
+        avg_var (numpy.ndarray or cupy.ndarray): Population variance.
         N (int): Count of batches given for fine-tuning.
         decay (float): Decay rate of moving average. It is used on training.
         eps (float): Epsilon value for numerical stability. This value is added


Test patch:
Repository: chainer/chainer

Issue:
Variable defines __hash__ but does not define __eq__
`Variable` defines `__hash__` but doesn't define `__eq__`:
```
class Variable(object):
    # ...

    def __eq__(self, other):
        raise NotImplementedError()

    # ...

    def __hash__(self):
        return super(Variable, self).__hash__()
```

But, the python documentation (https://docs.python.org/3.1/reference/datamodel.html#object.__hash__) says:
> If a class does not define an __eq__() method it should not define a __hash__() operation either;

Is there a reason `Variable` is designed like this?


Discussion:
It looks like a mistake. Variable should not be hashable (like ndarrays).

Resolving patch:
diff --git a/chainer/variable.py b/chainer/variable.py
--- a/chainer/variable.py
+++ b/chainer/variable.py
@@ -1058,10 +1058,8 @@ def __nonzero__(self):
     def __bool__(self):
         raise NotImplementedError()
 
-    def __hash__(self):
-        return super(Variable, self).__hash__()
-
     __array_priority__ = 200
+    __hash__ = None
 
 
 class Parameter(Variable):


Test patch:
diff --git a/tests/chainer_tests/test_variable.py b/tests/chainer_tests/test_variable.py
--- a/tests/chainer_tests/test_variable.py
+++ b/tests/chainer_tests/test_variable.py
@@ -665,6 +665,46 @@ def test_pickle_gpu(self):
         cp.testing.assert_array_equal(x.grad, d.grad)
 
 
+class TestVariableBasic(unittest.TestCase):
+    def test_unhashable(self):
+        a = chainer.Variable(np.ones((2,)))
+        with six.assertRaisesRegex(self, TypeError, '^unhashable type: '):
+            hash(a)
+
+    def test_unequatable(self):
+        a = chainer.Variable(np.ones((2,)))
+        b = chainer.Variable(np.ones((2,)))
+        with self.assertRaises(NotImplementedError):
+            a == b
+        with self.assertRaises(NotImplementedError):
+            a == a
+        with self.assertRaises(NotImplementedError):
+            a != b
+        with self.assertRaises(NotImplementedError):
+            a != a
+
+    def test_uncomparable(self):
+        a = chainer.Variable(np.ones((2,)))
+        b = chainer.Variable(np.ones((2,)))
+        with self.assertRaises(NotImplementedError):
+            a < b
+        with self.assertRaises(NotImplementedError):
+            a <= b
+        with self.assertRaises(NotImplementedError):
+            a > b
+        with self.assertRaises(NotImplementedError):
+            a >= b
+
+    def test_bool_inconvertible(self):
+        a = chainer.Variable(np.ones((2,)))
+        with self.assertRaises(NotImplementedError):
+            if a:
+                pass
+        with self.assertRaises(NotImplementedError):
+            if not a:
+                pass
+
+
 class TestParameter(unittest.TestCase):
 
     def setUp(self):
Repository: chainer/chainer

Issue:
Install bug: Mock required for gradient_check
#2972 Install bug

Chainer installed with `pip install chainer`
`from chainer import gradient_check` fails due to unable to find mock to import
Fixed by `conda install mock`

`gradient_check` is included in the block declarations in the tutorial, so it should either be removed from there or mock should be added to default install so that people doing the tutorial do not get an error during the import commands.

```
from chainer import gradient_check

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-0ba4708b632d> in <module>()
      1 import numpy as np
      2 import chainer
----> 3 from chainer import gradient_check
      4 from chainer import datasets, iterators, optimizers, serializers
      5 from chainer import Link, Chain, ChainList

/home/crissman/.pyenv/versions/anaconda3-4.2.0/lib/python3.5/site-packages/chainer/gradient_check.py in <module>()
      7 from chainer import cuda
      8 from chainer.functions.math import identity
----> 9 from chainer import testing
     10 from chainer import variable
     11 

/home/crissman/.pyenv/versions/anaconda3-4.2.0/lib/python3.5/site-packages/chainer/testing/__init__.py in <module>()
      5 from chainer.testing import parameterized  # NOQA
      6 from chainer.testing import serializer  # NOQA
----> 7 from chainer.testing import training  # NOQA
      8 from chainer.testing import unary_math_function_test  # NOQA
      9 

/home/crissman/.pyenv/versions/anaconda3-4.2.0/lib/python3.5/site-packages/chainer/testing/training.py in <module>()
      1 from __future__ import division
      2 
----> 3 import mock
      4 
      5 from chainer import training

ImportError: No module named 'mock'
```


Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -22,6 +22,7 @@
 setup_requires = []
 install_requires = [
     'filelock',
+    'mock',
     'nose',
     'numpy>=1.9.0',
     'protobuf>=2.6.0',


Test patch:
Repository: chainer/chainer

Issue:
Links to GitHub pages are broken
(Rel. #2758)

Links to GitHub pages do not appear in the  Read-the-Docs build (e.g. https://docs.chainer.org/en/stable/reference/generated/chainer.functions.sigmoid.html#chainer.functions.sigmoid).

It works in locally built documentation.

(Thanks @soskek for reporting)


Discussion:
Should be fixed bye #2995. Please test, confirm fixed, and close.

Resolving patch:
diff --git a/docs/source/conf.py b/docs/source/conf.py
old mode 100644
new mode 100755
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -352,6 +352,42 @@ def _import_object_from_name(module_name, fullname):
     return obj
 
 
+def _is_egg_directory(path):
+    return (path.endswith('.egg') and
+            os.path.isdir(os.path.join(path, 'EGG-INFO')))
+
+
+def _is_git_root(path):
+    return os.path.isdir(os.path.join(path, '.git'))
+
+
+_source_root = None
+
+
+def _find_source_root(source_abs_path):
+    # Note that READTHEDOCS* environment variable cannot be used, because they
+    # are not set under docker environment.
+    global _source_root
+    if _source_root is None:
+        dir = os.path.dirname(source_abs_path)
+        while True:
+            if _is_egg_directory(dir) or _is_git_root(dir):
+                # Reached the root directory
+                _source_root = dir
+                break
+
+            dir_ = os.path.dirname(dir)
+            if len(dir_) == len(dir):
+                raise RuntimeError('Couldn\'t parse root directory from '
+                                   'source file: {}'.format(source_abs_path))
+            dir = dir_
+    return _source_root
+
+
+def _get_source_relative_path(source_abs_path):
+    return os.path.relpath(source_abs_path, _find_source_root(source_abs_path))
+
+
 def linkcode_resolve(domain, info):
     if domain != 'py' or not info['module']:
         return None
@@ -361,7 +397,6 @@ def linkcode_resolve(domain, info):
         tag = 'master'
     else:
         tag = 'v{}'.format(__version__)
-    repo_root_dir = os.path.realpath('..')
 
     # Import the object from module path
     obj = _import_object_from_name(info['module'], info['fullname'])
@@ -382,9 +417,7 @@ def linkcode_resolve(domain, info):
     assert isinstance(linenum, six.integer_types)
 
     filename = os.path.realpath(filename)
-    if not filename.startswith(repo_root_dir):
-        return None
-    relpath = os.path.relpath(filename, repo_root_dir)
+    relpath = _get_source_relative_path(filename)
 
     return 'https://github.com/chainer/chainer/blob/{}/{}#L{}'.format(
         tag, relpath, linenum)


Test patch: